使用数学模式箭头匹配 TikZ 中的箭头

使用数学模式箭头匹配 TikZ 中的箭头

TikZ 擅长绘制图表,但有一个功能让我很恼火,那就是 TikZ 提供的默认箭头不一定尊重您使用的任何字体的数学模式。我知道 TikZ 库arrows允许您在几种不同类型的箭头之间进行选择,但没有一种箭头能提供与数学模式下绘制的箭头相同的箭头。

在 TikZ 中绘制图表时,我希望箭头与通过\to或等命令绘制的箭头相匹配\xrightarrow{foo}

有谁知道如何解决这一问题?


正如安德鲁·斯泰西 (Andrew Stacey) 在下面的评论中所建议的那样,我确实应该为您提供一个我所谈论的例子。

使用以下代码:

An arrow tip produced by TikZ:  
\begin{tikzpicture}
\node (A) at (0,0){$A$};
\node (B) at (1,0){$B$.};

\path (A) edge[->] node[midway,above]{$f$} (B);
\end{tikzpicture}

An arrow tip produced by \texttt{amsmath}: $A \xrightarrow{f} B$.  

我得到以下输出:

在此处输入图片描述

我希望这两个箭头完全相同。

答案1

我已经准备了一套完整的箭头尖匹配计算机现代箭头,和发布在 CTAN 上(以及有关这个问题的一些讨论和一些可能对数学图表有用的内容)。

我的箭头不如克里斯蒂安的那么精确,但它们与使用几条线条(而不是填充一个区域)所能获得的效果差不多,并且在实践中我发现结果足够好了。

这里有一个比较(上面是 Computer Modern,下面是 tikz 绘制的箭头)。

\documentclass{article} 
\usepackage{tikz,tikz-cd,graphicx} 
\begin{document} 
\noindent\hspace{2mm} \scalebox{20}{$\hookrightarrow$} 
\vspace{2cm} 
\tikz \draw[line width=8pt,cm right hook-cm to] (0,0) to (7,0); 
\end{document}

在此处输入图片描述

答案2

这是另一种绘制类似于 Computer Modern 箭头的方法,即使用细轮廓并填充。此解决方案的问题在于,当以 10 点打印时,箭头几乎不可见。因此,在有人找到解决方法之前,请不要使用此代码。当然,在屏幕上,结果看起来不错;下面包含一个示例。

交换图

以下是代码:

    \usepackage{tikz}
    \usetikzlibrary{matrix,arrows}
    \newlength{\myarrowsize} 
    \newlength{\myoldlinewidth}

    \pgfarrowsdeclare{myto}{myto}{
        \pgfsetdash{}{0pt} 
        \pgfsetbeveljoin 
        \pgfsetroundcap 
        \setlength{\myarrowsize}{0.6pt}
        \addtolength{\myarrowsize}{.5\pgflinewidth}
        \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
        \pgfarrowsrightextend{.7\pgflinewidth}
    }{
        \setlength{\myarrowsize}{0.6pt} 
        \addtolength{\myarrowsize}{.5\pgflinewidth}  
        \setlength{\myoldlinewidth}{\pgflinewidth}
        \pgfsetroundjoin
        % draw top half
        \pgfsetlinewidth{0.0001pt}
        \pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
        \pgfpatharc{0}{70}{0.14\myarrowsize}
        \pgfpatharc{-110}{-169.5}{4\myarrowsize}
        \pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
        % draw bottom half
        \pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
        \pgfpatharc{0}{-70}{0.14\myarrowsize}
        \pgfpatharc{110}{169.5}{4\myarrowsize}
        \pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{170}{119.5}{4.48\myarrowsize}
        \pgfpathclose
        \pgfsetstrokeopacity{0.25}
        \pgfusepathqfillstroke
    }

    \pgfarrowsdeclare{myonto}{myonto}{
        \pgfsetdash{}{0pt} 
        \pgfsetbeveljoin 
        \pgfsetroundcap 
        \setlength{\myarrowsize}{0.6pt}
        \addtolength{\myarrowsize}{.5\pgflinewidth}
        \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
        \pgfarrowsrightextend{.7\pgflinewidth}
    }{
        \setlength{\myarrowsize}{0.6pt} 
        \addtolength{\myarrowsize}{.5\pgflinewidth}  
        \setlength{\myoldlinewidth}{\pgflinewidth}
        \pgfsetroundjoin
        % draw top half
        \pgfsetlinewidth{0.0001pt}
        \pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
        \pgfpatharc{0}{70}{0.14\myarrowsize}
        \pgfpatharc{-110}{-169.5}{4\myarrowsize}
        \pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
        \pgfpathlineto{\pgfpoint{0.43\myarrowsize-0.3em}{0}}
        \pgfpatharc{0}{70}{0.14\myarrowsize}
        \pgfpatharc{-110}{-169.5}{4\myarrowsize}
        \pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
        % draw bottom half
        \pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
        \pgfpatharc{0}{-70}{0.14\myarrowsize}
        \pgfpatharc{110}{169.5}{4\myarrowsize}
        \pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{170}{119.5}{4.48\myarrowsize}
        \pgfpathlineto{\pgfpoint{0.43\myarrowsize-0.3em}{0}}
        \pgfpatharc{0}{-70}{0.14\myarrowsize}
        \pgfpatharc{110}{169.5}{4\myarrowsize}
        \pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
        \pgfpatharc{170}{119.5}{4.48\myarrowsize}
        \pgfpathclose
        \pgfsetstrokeopacity{0.25}
        \pgfusepathqfillstroke
    }

    \pgfarrowsdeclare{myhook}{myhook}{
        \setlength{\myarrowsize}{0.6pt}
        \addtolength{\myarrowsize}{.5\pgflinewidth}
        \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
        \pgfarrowsrightextend{.7\pgflinewidth}
    }{
        \setlength{\myarrowsize}{0.6pt} 
        \addtolength{\myarrowsize}{.5\pgflinewidth}  
        \pgfsetdash{}{+0pt}
        \pgfsetroundcap
        \pgfpathmoveto{\pgfqpoint{0pt}{-4.667\pgflinewidth}}
        \pgfpathcurveto
            {\pgfqpoint{4\pgflinewidth}{-4.667\pgflinewidth}}
            {\pgfqpoint{4\pgflinewidth}{0pt}}
            {\pgfpointorigin}
        \pgfusepathqstroke
    }

答案3

这个问题元箭头提示指向手册,其中说箭头尖通常不应与支撑线宽度成比例缩放。在这里,我定义了一个-my to箭头样式,它是上面链接的问题中箭头样式的调整版本-bad to。这是我能找到的最接近您提供的样式。

在此处输入图片描述

笔记:

  • 由于这是根据线宽缩放的版本改编的,因此对于其他线宽,不会产生很好的效果(事实上,效果非常糟糕)。我尝试使 版本的线宽tikz尽可能接近 版本的线宽amsmath

代码:

\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}

\pgfarrowsdeclare{my to}{my to}
{
  \pgfarrowsleftextend{-2\pgflinewidth}
  \pgfarrowsrightextend{\pgflinewidth}
}
{
  \pgfsetlinewidth{0.8\pgflinewidth}
  \pgfsetdash{}{0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfpoint{-5.5\pgflinewidth}{7.5\pgflinewidth}}
  \pgfpathcurveto
  {\pgfpoint{-4.0\pgflinewidth}{0.1\pgflinewidth}}
  {\pgfpoint{0pt}{0.25\pgflinewidth}}
  {\pgfpoint{0.75\pgflinewidth}{0pt}}
  \pgfpathcurveto
  {\pgfpoint{0pt}{-0.25\pgflinewidth}}
  {\pgfpoint{-4.0\pgflinewidth}{-0.1\pgflinewidth}}
  {\pgfpoint{-5.5\pgflinewidth}{-7.5\pgflinewidth}}
  \pgfusepathqstroke
}


\begin{document}
\begin{tikzpicture}
    \node (A) at (0,0){$A$};
    \node (B) at (0.82,0){$B$};
    \path (A) edge[-my to,line width=0.42pt]  (B);
\end{tikzpicture}

\hspace{0.33em}$A \xrightarrow{} B$
\end{document}

答案4

这是我正在使用的代码;它相当好地再现了计算机现代箭头。特别是,尖端比使用手册第 74 节的方法得到的更薄、更不圆。这个想法是使用几个圆弧(用一半的厚度绘制)来创建轮廓,然后填充它。

以下是结果示例:黑色箭头是 Computer Modern 的箭头(用 生成\longrightarrow),红色箭头由下面的代码生成。

箭头示例

我不太擅长让箭头的大小适应字体大小等。第二个问题是,在低缩放级别或打印时,线条似乎有点太粗。由于代码不适用于,我还\pgfdeclarearrowsdouble包含了 \into和箭头的代码。\onto

    \usepackage{tikz}
    \usetikzlibrary{matrix,arrows}
    \newlength{\myarrowsize} 

    % Version similar to Computer Modern
    \pgfarrowsdeclare{cmto}{cmto}{
            \pgfsetdash{}{0pt} 
            \pgfsetbeveljoin 
            \pgfsetroundcap 
            \setlength{\myarrowsize}{0.6pt}
            \addtolength{\myarrowsize}{.5\pgflinewidth}
            \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
            \pgfarrowsrightextend{.8\pgflinewidth}
    }{
            \setlength{\myarrowsize}{0.6pt} 
            \addtolength{\myarrowsize}{.5\pgflinewidth}  
            \pgfsetlinewidth{0.5\pgflinewidth}
            \pgfsetroundjoin
            % top half
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
            \pgfpatharc{-109}{-170}{4\myarrowsize}
            \pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % bottom half
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
            \pgfpatharc{109}{170}{4\myarrowsize}
            \pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % Change line width back
            \pgfsetlinewidth{2\pgflinewidth}
    }

    \pgfarrowsdeclare{cmonto}{cmonto}{
            \pgfsetdash{}{0pt} 
            \pgfsetbeveljoin 
            \pgfsetroundcap 
            \setlength{\myarrowsize}{0.6pt}
            \addtolength{\myarrowsize}{.5\pgflinewidth}
            \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
            \pgfarrowsrightextend{.8\pgflinewidth}
    }{
            \setlength{\myarrowsize}{0.6pt} 
            \addtolength{\myarrowsize}{.5\pgflinewidth}  
            \pgfsetlinewidth{0.5\pgflinewidth}
            \pgfsetroundjoin
            % top half
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
            \pgfpatharc{-109}{-170}{4\myarrowsize}
            \pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % bottom half
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
            \pgfpatharc{109}{170}{4\myarrowsize}
            \pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % top half (2)
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth-0.3em}{0}}
            \pgfpatharc{-109}{-170}{4\myarrowsize}
            \pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % bottom half (2)
            \pgfpathmoveto{\pgfpoint{1.5\pgflinewidth-0.3em}{0}}
            \pgfpatharc{109}{170}{4\myarrowsize}
            \pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
            \pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
            \pgfpathclose
            \pgfusepathqfillstroke
            % Change line width back
            \pgfsetlinewidth{2\pgflinewidth}
    }

    \pgfarrowsdeclare{cmhook}{cmhook}{
            \pgfsetdash{}{0pt} 
            \pgfsetbeveljoin 
            \pgfsetroundcap 
            \setlength{\myarrowsize}{0.6pt}
            \addtolength{\myarrowsize}{.5\pgflinewidth}
            \pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth} 
            \pgfarrowsrightextend{.8\pgflinewidth}
    }{
            \setlength{\myarrowsize}{0.6pt} 
            \addtolength{\myarrowsize}{.5\pgflinewidth}  
            \pgfsetdash{}{0pt}
            \pgfsetroundcap
            \pgfpathmoveto{\pgfqpoint{0pt}{-4.667\pgflinewidth}}
            \pgfpathcurveto
            {\pgfqpoint{4\pgflinewidth}{-4.667\pgflinewidth}}
            {\pgfqpoint{4\pgflinewidth}{0pt}}
            {\pgfpointorigin}
            \pgfusepathqstroke
    }

相关内容