# Arrows on Axis in Makie

**URL:** <https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015>\
**Category:** Visualization\
**Tags:** makie\
**Created:** [April 4, 2022, 5:47pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015 "2022-04-04T17:47:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![kfrb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kfrb/32/29557_2.png) [@kfrb](https://discourse.julialang.org/u/kfrb)\
**Post date:** [April 4, 2022, 5:47pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/1 "2022-04-04T17:47:27Z")

</div>

First, I love Makie and am currently switching to it as my daily plotting library!  
I often need arrow tips on the axis ends. Unfortunately, I could not find anything about it in the docs, so I used the following workaround:

```julia
using CairoMakie

function axisarrows!(ax::Axis=current_axis(); kwargs...)
    points = [
        ax.elements[:xaxis].attributes.endpoints.val[2],
        ax.elements[:yaxis].attributes.endpoints.val[2]
    ]
    directions = [Vec2f(1, 0), Vec2f(0, 1)]
    arrows!(ax.parent.scene, points, directions; kwargs...)
end

f, ax, p = lines(1:10, rand(10))
axisarrows!(arrowsize=15)
hidespines!(ax, :t, :r)
f

```

 ![test](https://global.discourse-cdn.com/julialang/original/3X/a/e/aee33c910287bccaecc384aa511992a79b50b3ab.png)

One downside is that the `axisarrows!` function always needs to be run last because it plots arrows over the whole scene. Any modification to the ticks would lead to a wrong position of the axis arrows.

So Is there a better method or a way to modify my workaround to make it more robust and flexible? Maybe if I use `Observables` so that the axis arrow position gets updated automatically? I`ve seen similar things in this thread:

> [@Break axis in Makie](https://discourse.julialang.org/t/break-axis-in-makie/62729/10):
>
> Here’s a possible implementation, although it uses some rather internal things: f = Figure() lims = Node(((0.0, 1.3), (7.6, 10.0))) g = f[1, 1] = GridLayout() ax\_top = Axis(f[1, 1][1, 1], title = "Broken Y-Axis") ax\_bottom = Axis(f[1, 1][2, 1]) on(lims) do (bottom, top) ylims!(ax\_bottom, bottom) ylims!(ax\_top, top) rowsize!(g, 1, Auto(top[2] - top[1])) rowsize!(g, 2, Auto(bottom[2] - bottom[1])) end hidexdecorations!(ax\_top, grid = false) ax\_top.bottomspinevisibl…

Is it possible that Makie will natively support axis arrows in the future?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [April 4, 2022, 5:55pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/2 "2022-04-04T17:55:16Z")

</div>

Yes exactly, you need to use observables so the endpoints auto update whenever the axis shifts. `endpoints` is already an observable, just with two points. You extract the value out of it statically but need to do it such that you make a new observable with one point. The short syntax would be `@lift($(ax.elements[:xaxis].attributes.endpoints)[1])`.

---

<div class="post-metadata">

**Author:** ![kfrb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kfrb/32/29557_2.png) [@kfrb](https://discourse.julialang.org/u/kfrb)\
**Post date:** [April 5, 2022, 9:10am UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/3 "2022-04-05T09:10:33Z")

</div>

Thank you very much, @jules, for your fast and helpful reply!  
I changed the function so that the arrow tips always stay on the axis endpoints.

```julia
function axisarrows!(ax::Axis=current_axis(); kwargs...)
    points = lift(
            @lift($(ax.elements[:xaxis].attributes.endpoints)[2]),
            @lift($(ax.elements[:yaxis].attributes.endpoints)[2]),
        ) do px, py
        [px, py]
    end
    directions = [Vec2f(1, 0), Vec2f(0, 1)]
    arrows!(ax.parent.scene, points, directions; kwargs...)
end

```

## Example:

```julia
f, ax, p = lines(1:10, rand(10))
hidespines!(ax, :t, :r)
axisarrows!(arrowsize=15)
f

```

 ![plot1](https://global.discourse-cdn.com/julialang/original/3X/c/4/c4001c67143a67f950bc9737fbe8b13caa455282.png)

Updating the axis labels, arrows change position:

```julia
ax.title = "title"
ax.xlabel = "x"
ax.ylabel = "y"
f

```

 ![plot2](https://global.discourse-cdn.com/julialang/original/3X/6/3/6350dfe378ea3838376fcc8d174584f82eaca2af.png)

After adding a new Axis:

```julia
ax2 = Axis(f[1,2], title="title 2", xlabel="x", ylabel="y")
scatter!(ax2, 1:10, rand(10))
hidespines!(ax2, :t, :r)
axisarrows!(ax2, arrowsize=15)
f

```

 ![plot3](https://global.discourse-cdn.com/julialang/original/3X/9/3/931e97628d26dbf9121fc74e0ff8ea2a3f80e4ea.png)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [April 5, 2022, 9:14am UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/4 "2022-04-05T09:14:09Z")

</div>

Nice! Note that you can do one less layer of lifting, instead of this:

```julia
points = lift(
            @lift($(ax.elements[:xaxis].attributes.endpoints)[2]),
            @lift($(ax.elements[:yaxis].attributes.endpoints)[2]),
        ) do px, py
        [px, py]
    end

```

I think this should work (didn’t test):

```julia
points = @lift [
            $(ax.elements[:xaxis].attributes.endpoints)[2],
            $(ax.elements[:yaxis].attributes.endpoints)[2],
        ]

```

---

<div class="post-metadata">

**Author:** ![kfrb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kfrb/32/29557_2.png) [@kfrb](https://discourse.julialang.org/u/kfrb)\
**Post date:** [April 5, 2022, 9:31am UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/5 "2022-04-05T09:31:28Z")

</div>

Thanks for this tip! I tested it - it works fine and is even shorter!

---

<div class="post-metadata">

**Author:** ![vladdez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vladdez/32/45806_2.png) [@vladdez](https://discourse.julialang.org/u/vladdez)\
**Post date:** [December 11, 2023, 3:43pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/6 "2023-12-11T15:43:35Z")

</div>

Where did you find such attributes: ax.elements[:xaxis]? I can not find xaxis in my figure.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [December 11, 2023, 6:10pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/7 "2023-12-11T18:10:20Z")

</div>

Those are `Axis` internals

---

<div class="post-metadata">

**Author:** ![Kolaru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kolaru/32/4574_2.png) [@Kolaru](https://discourse.julialang.org/u/Kolaru)\
**Post date:** [April 9, 2024, 12:33pm UTC](https://discourse.julialang.org/t/arrows-on-axis-in-makie/79015/8 "2024-04-09T12:33:59Z")

</div>

It seems like the endpoints can now be found with

```julia
ax.xaxis.attributes[:endpoints]

```
