6

I can find fat arrows and thin arrows,

I can find fancy curly arrows that start thin and get fat,

All I want is a basic arrow that is thick at the origin, and thin at the other end, indicating that we are going "from" a "larger" space "to" a smaller space.

For use in something like a commutative diagram.

Does tikz have any such thing?

enter image description here

enter image description here

4
  • 2
    Is this supposed to be a shape like one of those from the shapes.arrows? Or should it be a path, connecting two coordinates or nodes? TikZ doesn't really support variable line width in one path (but solutions exist). But in this simple case it could be replicated by drawing the area itself. Commented Oct 26, 2022 at 12:06
  • Well, a path, I suppose. But in the commutative diagram library, I can just draw my arrow with \arrow. I've added a hand-drawn picture of the diagram I was trying to draw (ignore the squiggly red line).
    – DrM
    Commented Oct 26, 2022 at 12:50
  • I had seen the solutions you link, but they all seem overcomplicated for what I wanted to do. I think if I wanted to design my own arrow, I could just do it by drawing two slightly offset arrows with one-sided heads. I was hoping there might be a solution without having to design my own though...
    – DrM
    Commented Oct 26, 2022 at 12:55
  • you can define a pic for your arrow, then use \path (A)--(B) pic[sloped,midway]{myarrow};
    – Black Mild
    Commented Oct 26, 2022 at 14:15

3 Answers 3

14

Well, it's not perfect but maybe this can get you started:

enter image description here

Basically I just made an arrow tip with Latex followed by Triangle, and then used it as a decoration on the arrow line (which is drawn in white).

\documentclass{article}

\usepackage{tikz-cd}
\usetikzlibrary{decorations.markings}

\tikzset{mytip/.tip={Latex[{color=black, fill=white, length=5mm, width=1.5mm, sep=-.9mm}]Triangle[color=black, fill=white]},
    myarrow/.style={white, decoration={transform={xshift=2.75mm}, markings, mark=at position .5 with {\arrow{mytip}}}, postaction=decorate}
    }

\begin{document}

\begin{tikzcd}[arrows={myarrow}]
K\arrow[dr]\\
\Omega\arrow[u]\arrow[r] & k
\end{tikzcd}

\end{document}
1
  • thanks, yeah, something relatively simple like this was what I was looking for
    – DrM
    Commented Oct 26, 2022 at 20:21
11

You second sketch is much easier to implement, I believe.

Idea:

  1. Get the length of the path. (This only permits one segment, i.e. one line-to or one curve-to.)
  2. Use that length to set the length of the second arrow tip.

Unfortunately, when the Triangle tip becomes too sharp the head gets beveled off but the arrow tip defintion doesn't account for that and adjust the drawing which is why I'm using line join=round here for both parts.
Though, PGF still uses the length calculations as if the sharp angle would be drawn mitered.

Since I'm not in the mood to do the math to adjust for the lost length, I'm just using a factor of 1.1 to stretch the second tip to about its needed length. This works well enough in this example for straight lines and not so good for curved path (with bending). But that's partly the reason why I'm using draw=none (via \tikz@mode@drawfalse) to force the (remaining) line not be drawn.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations,bending}
\usepackage{tikz-cd}
\makeatletter
\tikzset{
  ararrow/.default={open}{open},
  ararrow/.code 2 args={%
    \tikz@addoption{%
       \pgfset{tips=true}% draw tips even if the path isn't.
       \pgfgetpath\currentpath
       \pgfprocessround{\currentpath}{\currentpath}%
       \pgf@decorate@parsesoftpath{\currentpath}{\currentpath}%
       \pgfsetarrowsend{%. % dot not really needed when no line is drawn
         Triangle[
           length=1.1*(\pgf@decorate@totalpathlength-4pt+.5*\the\pgflinewidth),
           line join=round,#1]
         Triangle[angle'=60,length=+4pt,line join=round,#2]}%
       \tikz@mode@drawfalse % disable drawing of path
    }
  },
  ararrow **/.style={ararrow={}{}},     ararrow oo/.style={ararrow={open}{open}},
  ararrow *o/.style={ararrow={}{open}}, ararrow o*/.style={ararrow={open}{}},
}
\makeatother
\begin{document}
\begin{tikzcd}[/tikz/arrows={[bend]}]
 K \drar[ararrow o*] \ar[dr, ararrow **, controls={+(1.5,0.5) and +(1,0.8)}] \\
 \Omega \rar[ararrow] \uar[ararrow o*] & k
\end{tikzcd}
\end{document}

Output

enter image description here

1
  • oh, this is neat too!
    – DrM
    Commented Oct 26, 2022 at 20:22
9

You can create your own custom decoration. With the following, you can use options to customize the appearance of the arrow as described in the picture below.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations}

\newlength{\tailarrowtiplength}
\setlength{\tailarrowtiplength}{1em}
\newlength{\tailarrowtipwidth}
\newlength{\tailarrowtailwidth}
\newlength{\tailarrowjointwidth}

\pgfdeclaredecoration{tail arrow decoration}{initial}{
    \state{initial}[width=\pgfdecoratedpathlength, next state=final] {
        \pgfpathlineto{\pgfpoint{0pt}{0.5\tailarrowtailwidth}}
        \pgfpathlineto{\pgfpointadd{\pgfpointdecoratedpathlast}{\pgfpoint{-1\tailarrowtiplength}{0.5\tailarrowjointwidth}}}
        \pgfpathlineto{\pgfpointadd{\pgfpointdecoratedpathlast}{\pgfpoint{-1\tailarrowtiplength}{0.5\tailarrowtipwidth}}}
        \pgfpathlineto{\pgfpointdecoratedpathlast}
        \pgfpathlineto{\pgfpointadd{\pgfpointdecoratedpathlast}{\pgfpoint{-1\tailarrowtiplength}{-0.5\tailarrowtipwidth}}}
        \pgfpathlineto{\pgfpointadd{\pgfpointdecoratedpathlast}{\pgfpoint{-1\tailarrowtiplength}{-0.5\tailarrowjointwidth}}}
        \pgfpathlineto{\pgfpoint{0pt}{-0.5\tailarrowtailwidth}}
        \pgfpathclose
    }
    \state{final} {
        \pgfpathmoveto{\pgfpointdecoratedpathlast}
    }
}

\tikzset{
    tail arrow tip length/.code={
        \setlength{\tailarrowtiplength}{#1}
    },
    tail arrow tip width/.code={
        \setlength{\tailarrowtipwidth}{#1}
    },
    tail arrow tail width/.code={
        \setlength{\tailarrowtailwidth}{#1}
    },
    tail arrow joint width/.code={
        \setlength{\tailarrowjointwidth}{#1}
    },
    tail arrow tip length/.default={ 2em },
    tail arrow tip width/.default={ 2em },
    tail arrow tail width/.default={ 1em },
    tail arrow joint width/.default={ .2em },
    tail arrow/.style={
        tail arrow tip length,
        tail arrow tip width,
        tail arrow tail width,
        tail arrow joint width,
        decorate,
        decoration={tail arrow decoration}
    }
}

\begin{document}
\begin{tikzpicture}

\draw[tail arrow, tail arrow tip width=4em, tail arrow tip length=1em, tail arrow joint width=0.5em] (0,-1) -- (5,-2); 

\draw[tail arrow] (0,0) -- (5,0); 

% description of options

\draw[|-|, red] ([shift={(-2em,-1.5em)}]5,0) -- ([shift={(0em,-1.5em)}]5,0) node[below, midway, font=\ttfamily\scriptsize, align=center] {tail arrow \\ tip length};

\draw[|-|, red] ([shift={(0.5em,-1em)}]5,0) -- ([shift={(0.5em,1em)}]5,0) node[right, midway, font=\ttfamily\scriptsize, align=left] {tail arrow \\ tip width};

\draw[|-|, red] ([shift={(-2.5em,-0.1em)}]5,0) -- ([shift={(-2.5em,0.1em)}]5,0) node[above left, pos=0, font=\ttfamily\scriptsize, align=right] {tail arrow \\ joint width};

\draw[|-|, red] ([shift={(-0.5em,-0.5em)}]0,0) -- ([shift={(-0.5em,0.5em)}]0,0) node[left, midway, font=\ttfamily\scriptsize, align=right] {tail arrow \\ tail width};

\end{tikzpicture}
\end{document}

enter image description here

Applied in a tikzcd context, you could then do:

\documentclass[border=10pt]{standalone}
\usepackage{tikz-cd}
\usetikzlibrary{decorations}

% [above definitions]

\begin{document}

\begin{tikzcd}[arrows={tail arrow, tail arrow tip width=.75em, tail arrow tail width=.5em, tail arrow tip length=1em}]
K\arrow[dr]\arrow[d]\\
\Omega\arrow[r] & k
\end{tikzcd}

\end{document}

enter image description here

5
  • @JasperHalbricht This is good and works well with the option Rightarrow. However leftrightarrow or even Leftarrow do not produce the desired result. Is there a way to modify your solution to get such functionality?
    – encore
    Commented Jan 10, 2023 at 10:24
  • @encore Do you mean the option Rightarrow provided by tikz-cd? This solution is actually not meant to work together with these options. Rather you should be able to use the l or u options to draw arrows leftwards or upwards. The above solution just decorates a line that starts from any point and goes to another point. It does not really matter in which direction the line is drawn, the arrow tip is always at the end of the line. Commented Jan 10, 2023 at 19:00
  • @JasperHalbricht yes I meant that option. In particular, I need a leftright arrow of the type you have designed. You know, Rightarrow actually does something to your arrow, the result looks like a blackboard bold arrow.
    – encore
    Commented Jan 10, 2023 at 21:18
  • 1
    @encore As I said, it is not intended and merely by chance that the appearance of the arrow is changed when using the Rightarrow option. You should ask a new question and describe how the left-right arrow should look like exactly, because such an arrow by design cannot be thicker on one end in my opinion. Commented Jan 11, 2023 at 3:39
  • Ok will do. I was using your design with rectangular tail, same width near head as tail, so then two-sided arrow makes sense. Sorry I misspelled your surname twice :-(
    – encore
    Commented Jan 11, 2023 at 10:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .