Skip to content

feat: absolute draw order / rank property #4676

Closed

Description

@gvwilson

Currently, there is no way to set an absolute draw order for traces. It would be very useful to have a property to determine the global draw order, e.g. to give a trace the value of 1 to make sure it is always drawn on top of all other traces and another trace the value of 9999 to make sure it is drawn behind all other traces.

Activity

  1. self-assigned this
    on Jul 17, 2024
  2. gvwilson commented on Jul 17, 2024

    @gvwilson
    ContributorAuthor

    Let me break down the current behavior a little:
    (0) in SVG, there's no concept like z-index in HTML; items later in the DOM are always on top of items earlier in the DOM.
    (1) if you have multiple sets of x or y axes overlaying each other, all the traces on the same axes are grouped together and either in front or behind other axes. I would need to verify the details, but I believe higher-index x axes are in front, and for the same x axis higher-index y axes are in front, ie x2y2>x2y>xy2>xy.
    (2) Traces of different type have a fixed order, as we put them all in different "layer" groups:

        traceLayerClasses: [
            'imagelayer',
            'heatmaplayer',
            'contourcarpetlayer', 'contourlayer',
            'funnellayer', 'waterfalllayer', 'barlayer',
            'carpetlayer',
            'violinlayer',
            'boxlayer',
            'ohlclayer',
            'scattercarpetlayer', 'scatterlayer'
        ],
    

    Meaning scatter traces are always on top, image traces are always on bottom, everything in between is as in this list.
    (3) After that, traces of the same type are ordered by their index in data.

    So with all of that in mind, which of these three categories describes your use cases?

    It would be fairly easy to add an attribute to change (3) - the ordering of traces of the same type on the same axes, but hard to add a way to change the other orderings (different types, or on different axes).

    But there's a workaround: make extra axes - that can be set to be overlaying and matching the main axes and with all their marks disabled, so really their only effect is to change the layering - and put the traces intended to be in back on lower-numbered axes, traces in front on higher-numbered axes.

  3. gvwilson commented on Jul 17, 2024

    @gvwilson
    ContributorAuthor

    The scenario we encountered is in the area of (1). We have scatter traces linked to yaxis2 and bar traces linked to yaxis1. The scatter traces should be drawn on top of the bar traces. From your explanation, the best solution would be to add additional axes with higher indexes (e.g. yaxis3) and re-assign the bar traces to these.

    We simplified the axis logic for our less technical end users as follows:

    • There are only two y-axes, one left and one right.
    • There are only two x-axes, one top and one bottom.
    • There is a rank parameter on each trace object, which specifies the global drawing order for the traces.

    We could build a workaround on our side that would be invisible to the user by automatically creating multiple axes based on the rank parameter under the hood. However, I feel like such a property could be useful to the plotly community at large and it would probably be easier for you guys to implement than for us.

    To summarize:
    It would be great, if the rank property on the traces would cover (1), (2) and (3) of your list above.

  4. gvwilson commented on Jul 17, 2024

    @gvwilson
    ContributorAuthor

    Summing up past discussions of solution design for this one.

    API

    • Add zindex property to cartesian traces, which accepts an integer
    • Traces of higher zindex are drawn on top of traces of lower zindex (consistent with CSS convention)
    • Questions
      • Property name and stacking direction -- i.e. are lower or higher numbers drawn on top? I like following an existing convention for simplicity but open to other conventions
      • Applies to all cartesian traces, or do any need to be excluded?

    Implementation (based on notes from @alexcjohnson)

    • Changes to trace drawing logic -- largely within src/plots/cartesian/index.js
    • Separate traces into overlapping sets, i.e. traces that don't overlap each other should be in different sets (different subplots, basically)
    • Figure out stacking order implied by zindex
    • Figure out how many different stacked containers are needed to make the default trace stacking order match the order specified by zindex (Currently, just one container per axis pair is used)
    • Create containers and draw traces in their correct containers
    • Make sure all containers are transformed during zoom/pan rather than just one per axis pair
  5. gvwilson commented on Jul 17, 2024

    @gvwilson
    ContributorAuthor

    See great progress: plotly/plotly.js#6918

  6. archmoj commented on Jul 24, 2024

    @archmoj
    Contributor

    We could possibly close this one as zorder is implemented. No?

  7. gvwilson commented on Jul 24, 2024

    @gvwilson
    ContributorAuthor

    agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

cscustomer successfeaturesomething new

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions