140

Like this:

.------<------.
|             |
v             ^
|             |
'------>------'

I am currently using

\begin{scope}[very thick,->]
  \draw (-4,1)--(-4,0)--(0.1,0);
  \draw (0,0)--(4,0)--(4,1.1);
  \draw (4,1)--(4,2)--(-0.1,2);
  \draw (0,2)--(-4,2)--(-4,0.9);
\end{scope}

but this is rather inelegant. I prefer something more like

\begin{scope}[very thick,middle decoration=>] 
             %           ^^^^^^^^^^^^^^^^^ a hypothetical option
  \draw (-4,0)--(4,0);
  \draw (4,0)--(4,2);
  \draw (4,2)--(-4,2);
  \draw (-4,2)--(-4,0);
\end{scope}

9 Answers 9

106

The decorations library can be used to all kinds of stuff like this. Unfortunately it is slightly verbose.

\usetikzlibrary{decorations.markings}

\begin{scope}[very thick,decoration={
    markings,
    mark=at position 0.5 with {\arrow{>}}}
    ] 
    \draw[postaction={decorate}] (-4,0)--(4,0);
    \draw[postaction={decorate}] (4,0)--(4,2);
    \draw[postaction={decorate}] (4,2)--(-4,2);
    \draw[postaction={decorate}] (-4,2)--(-4,0);
\end{scope}
7
  • But with a few every path/.style={}s then it shouldn't be too wordy. Nice! (Better than mine) Commented Sep 16, 2010 at 20:56
  • @Andrew When I put postaction={decorate} into the every path/.style={}, I get an error: Undefined control sequence. \pgf@decorate@processnextinputsegmentobject. I have no idea why.
    – Caramdir
    Commented Sep 16, 2010 at 21:09
  • 2
    Hm, it also says "I cannot decorate an empty path". Is it possible that pgf is trying to apply the decoration even to the paths that the arrow is made from, and one of the paths is empty? Commented Sep 17, 2010 at 2:11
  • 2
    Indeed this seems to be the case: tex.stackexchange.com/questions/3184/…
    – Caramdir
    Commented Sep 17, 2010 at 2:37
  • 4
    @Sigur: I suppose changing \arrow{>} to \arrow{latex} should work.
    – Caramdir
    Commented Sep 5, 2014 at 3:39
64

Edit: A general solution to apply some some styles (like put an arrow in the middle) to each segment of an arbitrary path.

There are two styles:

  • the on each segment style uses the show path construction decoration of decorations.pathreplacing library to apply some styles (its argument) on each segment of a path.

  • the mid arrow style uses the method of Caramdir's answer (via decorations.markings library) to put an arrow in the middle of a path (its argument is the color of the arrow).

First, the preamble:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,decorations.markings}

The two styles:

\tikzset{
  % style to apply some styles to each segment of a path
  on each segment/.style={
    decorate,
    decoration={
      show path construction,
      moveto code={},
      lineto code={
        \path [#1]
        (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
      },
      curveto code={
        \path [#1] (\tikzinputsegmentfirst)
        .. controls
        (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb)
        ..
        (\tikzinputsegmentlast);
      },
      closepath code={
        \path [#1]
        (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
      },
    },
  },
  % style to add an arrow in the middle of a path
  mid arrow/.style={postaction={decorate,decoration={
        markings,
        mark=at position .5 with {\arrow[#1]{stealth}}
      }}},
}

Then the result and the document:

enter image description here

\begin{document}
\begin{tikzpicture}
  \path [draw=blue,postaction={on each segment={mid arrow=red}}]
  (.2,0) -- (3,1) arc (0:180:1.4 and 1) -- cycle
  (4,1) circle(.8)
  (6,1) ellipse(.5 and 1)
  (0,3) to [bend left] (3,4)
  (4,3) rectangle (6,4)
  ;
\end{tikzpicture}
\end{document}
12
  • This is really useful. I wonder if this is included in the latest version of Tikz.
    – berkus
    Commented Jun 27, 2017 at 13:01
  • @BarisErkus The show path construction decoration is already included in the current version of TikZ. My on each segment style is just a simple application of this decoration. Commented Jun 27, 2017 at 13:22
  • @PaulGaborit I wanted to modify this for other arrowheads, e.g. double arrow, but it did not work. What I did was to replace "{\tikz \draw[-triangle 90] (0,0) -- +(.1,0);}" by "{\tikz \draw[-triangle 90] (0,0) -- +(.1,0); \draw[-triangle 90] (0,0)--+(.145,0);}", but this head no effect
    – klirk
    Commented Jan 31, 2019 at 15:47
  • @klirk You can use the arrows.meta library (a TikZ library) and, in my code, replace stealth by Stealth[]Stealth[] or Triangle[]Triangle[]. Commented Jan 31, 2019 at 20:28
  • Does this mean that arcs, circles and ellipses have 4 paths? I would have expected them to be drawn all in one piece and therefore to see only one arrow in them.
    – Andyc
    Commented Mar 3, 2021 at 21:20
31

Update: 2020-02-22: This code has been superseded and shouldn't be used. It also nests tikzpictures, something that I later realised was Not Good. Caramdir's answer is the best all-round solution, but if you want something that is close to this one then Kpym's answer using pics has the same spirit as this but without the drawbacks.


Given that the precise syntax you specify isn't possible, here's something that achieves the desired effect without having to specify the coordinates of the midpoints.

\documentclass{article}
\thispagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{arrows}
\newcommand{\midarrow}{\tikz \draw[-triangle 90] (0,0) -- +(.1,0);}

\begin{document}
\begin{tikzpicture}
\begin{scope}[very thick, every node/.style={sloped,allow upside down}]
  \draw (-4,0)-- node {\midarrow} (4,0);
  \draw (4,0)-- node {\midarrow} (4,2);
  \draw (4,2)-- node {\midarrow} (-4,2);
  \draw (-4,2)-- node {\midarrow} (-4,0);
\end{scope}
\end{tikzpicture}
\end{document}

(the arrows tikz library is just to get more prominent arrowheads)

This produces:

alt text

(not sure what that vertical line is down the right-hand side. It's not in the original so must be an artefact of the pdf->png process)

20

(A modification of Caramdir's solution using Ulrich Schwarz's answer to ”Applying a postaction to every path in TikZ”.)

\makeatletter
\tikzset{nomorepostaction/.code={\let\tikz@postactions\pgfutil@empty}}
\makeatother
\begin{tikzpicture}[
    every path/.style={
        very thick,
        postaction={nomorepostaction,decorate,
                    decoration={markings,mark=at position 0.5 with {\arrow{>}}}
                   }
        }
    ]
    \draw (-4,0)--(4,0);
    \draw (4,0)--(4,2);
    \draw (4,2)--(-4,2);
    \draw (-4,2)--(-4,0);
\end{tikzpicture}
10

Without decoration and with a "unique" path, a new code is :

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows}  

\begin{document}
\tikzset{%
          insert new path/.style={%
             insert path={%
                  node[midway,sloped]{\tikz \draw[#1,thick] (-.2pt,0) -- ++(.2 pt,0);}
                  }
             }
         }

\begin{tikzpicture}
\begin{scope}[a/.style = {insert new path = {-triangle 90}}]
  \draw[red] (-4,0) -- (4,0) -- (4,2) -- (-4,2) -- (-4,0);
  \draw[red] (0,-4pt)--(0,+4pt); % it's a  test
  \draw (-4,0)-- (4,0)[a] -- (4,2)[a] -- (-4,2)[a] -- (-4,0)[a];
\end{scope}
\end{tikzpicture}

\end{document}

It's possible to adjust the position of the arrows with something like node[midway,sloped,right=-2pt]

enter image description here

9

PSTricks equivalent (out of the box):

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pstricks-add}

\begin{document}

\begin{pspicture}[showgrid=bottom](4,4)
    \pspolygon[ArrowInside=->,linecolor=red](0,0)(4,0)(4,4)(0,4)
\end{pspicture}

\end{document}
1
  • 8
    The original asked for a TikZ solution, not a pstricks one.
    – James C.
    Commented Nov 15, 2012 at 1:02
8

This is revisited version of Loop Space's answer using pic in place of node that were not available in 2010.

The main advantages is that the pic inherits the path style (line width, color, ...) from the current path.

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{arrows}
\tikzset{
  arrow/.pic={\path[tips,every arrow/.try,->,>=#1] (0,0) -- +(.1pt,0);},
  pics/arrow/.default={triangle 90}
}

\begin{document}
  \begin{tikzpicture}
    \begin{scope}[very thick,nodes={sloped,allow upside down}]
      \draw (-4,0) -- pic{arrow} (4,0);
      \draw (4,0) -- pic[blue]{arrow} (4,2);
      \draw[thin,purple] (4,2) -- pic{arrow=latex} (-4,2);
      \draw[every arrow/.style=red] (-4,2) -- pic[pos=.3]{arrow} pic[pos=.7]{arrow} (-4,0);
    \end{scope}
  \end{tikzpicture}
\end{document}

enter image description here

And you can draw your own arrow using pics, for example by redefining arrow style

arrow/.pic={\fill[every arrow/.try,scale={\pgflinewidth/1cm}] 
    (0,0) -- (-150:7) -- (150:7) -- (0,0) circle(2);}

will produce the following picture

enter image description here

6

I accidentally discovered this, using circuitikz:

\draw (0,0) to node[currarrow] {} (1,0);

arrow in the middle of a line

could not yet find an alternative for currarrow in TikZ, and it doesn't work with the basic TikZ arrows. But you can do everything in circuitikz what you can in TikZ, and more!

5
  • 1
    i forgot, the environment is: \begin{circuitikz} % code \end{circuitikz}
    – matekatona
    Commented May 14, 2015 at 14:00
  • you mean alternatives except the top three answers above?
    – percusse
    Commented May 14, 2015 at 14:09
  • no, I mean I did not find an alternative to the currarrow node in the basic TikZ nodes. So you have to use the circuitikz package with this solution.
    – matekatona
    Commented Jul 27, 2015 at 12:07
  • 1
    btw: circuitikz also works with the basic tikzpicture environment. I personally recommend to always use the tikzpicture environment to make it easier to parse for tikzpictures in latex-code
    – tc88
    Commented Dec 19, 2017 at 10:55
  • 3
    "you can do everything in circuitikz what you can in TikZ, and more" >>> It should be the converse: "you can do everything in TikZ what you can in circuitikz, and more"
    – Black Mild
    Commented Aug 22, 2019 at 7:43
-1
\documentclass[]{standalone}
\usepackage{circuitikz}
\begin{document}
 
\begin{tikzpicture}
\draw (0,0) to node[currarrow] {} (1,0)to node[currarrow,rotate=90]{}(1,1)to node[currarrow,rotate=180]{}(0,1)to node[currarrow,rotate=-90]{}(0,0);
\end{tikzpicture}
\end{document}
2
  • 1
    Welcome to TeX.SX! You could improve your answer by adding some description and an image of the result.
    – dexteritas
    Commented Jan 31, 2023 at 14:17
  • 1
    What is the difference to matekatona's answer?
    – dexteritas
    Commented Jan 31, 2023 at 14:19

You must log in to answer this question.

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