100 在对node的圆周使用dashed装饰时,前后的「虚线」重合如何处理?

发布于 2025-07-14 16:42:47

如题,下面是MWE....

\documentclass[tikz,border=.5cm]{standalone}
\begin{document}
\begin{tikzpicture}
\node[
    circle,
    draw=blue,thick,
    densely dashed,
    fill=yellow,
    inner sep=2pt,
    font=\LARGE]  {2};
\end{tikzpicture}
\end{document}

image.png

查看更多

关注者
0
被浏览
134
3 个回答
shadow
shadow 14小时前
这个人懒得不得了,竟然啥也没写

重新写一下回答:

答案 2 的思路基本上就是我在群里说的思路,下面对 node 的形状为 circle 的情况,借助 pgfkey 封装成一个命令

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{
  /tikz/dash circle/minsize/.code    = \def\dc@min{#1},
  /tikz/dash circle/segments/.code   = \def\dc@seg{#1},
  /tikz/dash circle/radio/.code      = \def\dc@rat{#1}
}

\pgfkeys{
  /tikz/dash circle/.code = {%
    \pgfqkeys{/tikz/dash circle}{#1}%

    \@ifundefined{dc@min}{\errmessage{dash circle: 'minsize' is required}}{}
    \@ifundefined{dc@seg}{\errmessage{dash circle: 'segments' is required}}{}
    \@ifundefined{dc@rat}{\errmessage{dash circle: 'radio' is required}}{}

    \pgfmathsetmacro{\dc@circ}{pi * \dc@min}
    \pgfmathsetmacro{\dc@on}{(\dc@rat / (\dc@rat + 1)) * \dc@circ / \dc@seg}
    \pgfmathsetmacro{\dc@off}{(1 / (\dc@rat + 1)) * \dc@circ / \dc@seg}

    \tikz@addoption{%
      \pgfsetdash{{\dc@on pt}{\dc@off pt}}{0pt}%
      \pgfkeysalso{/tikz/shape=circle}%
    }
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}[nodes={draw, line width=1pt, red, font=\LARGE, text = blue}]
\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=10, radio=2}] at (0,0) {ABC};

\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=20, radio=2}] at (6,0) {ABC};

\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=10, radio=1}] at (0,-4) {ABC};

\node[draw, minimum size=2cm, dash circle={minsize=2cm, segments=10, radio=1}] at (6,-4) {ABC};
\end{tikzpicture}
\end{document}

image.png

其中 minisize 是 node 的 minimum size 的值,segments 是虚线的节数,radio 是 on 与 off 的比值,这比输入 on 或者 off 的值更加自然。

此外,该命令未将 minimum size 放进,也就是说用户需要在命令外重新输入 node 的 minimum size,这样是为了形式更加自然,因为本质上这个命令只是用来输入虚线的样式,不控制 node 的边界大小等内容。

缺陷: 该命令是用 node 的 minimum size 来计算 node 边界周长,这导致如果 node 内使用 inner sep 参数可能会使虚线起始点交汇处依然存在问题。

对于一般的 node 形状,涉及周长的计算,通用的解决方法可能比较困难,欢迎大家给出解答。

123
123 13小时前
这家伙很懒,什么也没写!

image.png
image.png

(图):二十段虚线
我也不知道为什么,总之我在

% 计算周长
\pgfmathsetlength{\mycircledradius}{2 * 3.141592654  * \mycircledradius - 1pt}

这一行加上了-1pt之后,一切都正常了
以下是我的完整代码,由deepseek生成,由我完成修改

\documentclass{article}
\usepackage{lipsum}
\usepackage{tcolorbox}
\usepackage{tikz}
\usepackage{tikz}
\usetikzlibrary{calc}
% \newcommand*\mycircled[1]{\tikz[baseline=(char.base)]{\node[circle,draw=blue,densely dashed,thick,fill=yellow, inner sep=2pt, dash pattern=on 2 off 1 pt] (char) {#1};}}



\newlength{\mycircledradius}
\newlength{\mydashonlength}     % 虚线段长度6
\newlength{\mydashofflength}    % 间隔长度4
\newlength{\mydashlength}       %一段虚线+一段间隔  6:4

\newcommand*\mycircled[1]{%
  \tikz[baseline=(char.base)]{
    % 临时节点用于测量尺寸
    \node[inner sep=2pt, circle] (temp) {#1};
    % 计算半径(包含内边距)
    \pgfextractx{\mycircledradius}{\pgfpointdiff{\pgfpointanchor{temp}{center}}{\pgfpointanchor{temp}{east}}}
    % 计算周长
    \pgfmathsetlength{\mycircledradius}{2 * 3.141592654  * \mycircledradius - 1pt}
    % % 确定合适的分段数
    % \pgfmathsetmacro{\n}{\mycircledradius / 16} 
    % 计算单段长度(实线+间隙)
    \pgfmathsetlength{\mydashlength}{\mycircledradius / 16}% 默认分成16段
    % 计算虚线段长度
    \pgfmathsetlength{\mydashonlength}{\mydashlength * 0.5}
    % 计算间隔长度
    \pgfmathsetlength{\mydashofflength}{\mydashlength * 0.5}

    % 动态创建虚线节点
    \node[circle, 
          draw=blue, 
          fill=yellow, 
          inner sep=2pt,
          dash pattern=on \mydashonlength off \mydashofflength] (char) {#1};
  }
}
\begin{document}

\begin{tcolorbox}
    \begin{center}\Large\bfseries
    \mycircled{2} I'm the title ahahahaha
    \end{center}
    \lipsum[2]
\end{tcolorbox}

\end{document}
Sagittarius Rover
Sagittarius Rover 12小时前
我要成为Typst糕手/(ㄒoㄒ)/~~

In the x-post, the best practice of this requirement is documented in the manual.

TL;DR

dash expand off is all what I need.

Makes the off part of a dash pattern expandable such that it can stretch. This only works when there is a single on and a single off field and requires the decorations library. Right now this option has to be specified on the path where it is supposed to take effect after the dash pattern option because the dash pattern has to be known at the point where it is applied.

image.png

Code & Result Comparsion:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{ext.shapes.superellipse}
\begin{document}
\begin{tikzpicture} [
      densely dashed,
    % dash expand off,
      every node/.append style={
        draw=blue,
        fill=yellow,
        thick,
        inner sep=2pt,
        font=\LARGE,
      },
    ]
  \node [circle] {1};
  \node [ellipse] at (1,0) {2};
  \node [ext_superellipse,font=\tiny] at (2.25,0) {233333};
\end{tikzpicture}

\begin{tikzpicture} [
    densely dashed,
    dash expand off,
    every node/.append style={
      draw=violet,
      fill=magenta,
      thick,
      inner sep=2pt,
      font=\LARGE,
    },
  ]
\node [circle] {1};
\node [ellipse] at (1,0) {2};
\node [ext_superellipse,font=\tiny] at (2.25,0) {233333};
\end{tikzpicture}

\end{document}

image.png

This can handle all the case by stretch the "off" part at the end, regardless of the node's content or the shape. IMHO, it's the best practice of this case.

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览