Closed vojtamolda closed 4 years ago
The issue happens because association between axes and traces is done via string matching in JavaScript. For example, two scatter subplots with customized x-axes are created in the following way:
var scatter1 = { "xaxis": "x1", "type": "scatter" ... }
var scatter2 = { "xaxis": "x2", "type": "scatter" ... }
var layout = {
"xaxis1": { /* x1 axis customization goes here */ },
"xaxis2": { /* x2 axis customization goes here */ }
}
Or two polar subplots to be displayed side-by-side can be constructed like this:
var barpolar1 = { "subplot": "polar1", "type": "barpolar", ... }
var barpolar2 = { "subplot": "polar2", "type": "barpolar", ... }
var layout = {
"polar1": { /* polar subplot customization goes here */ },
"polar2": { /* polar subplot customization goes here */ }
}
While it's possible to create the same figure in Swift by setting the .subplot
or .xAxis
trace properties to corresponding strings (i.e. "polar1/2"
or "x1/2"
), it's not possible to customize the "x2"
, or "polar2"
axes. Layout
object is strictly typed and it doesn't allow addition of Layout.x1
, .x2
, .polar1
or .polar2
members ad-hoc. These members when encoded to JSON would be translated by Plotly.js to customization of the corresponding sub-plot axes.
In fact, setting the trace subplot axis correspondence via string matching as described above, is not consistent with the API Design Guidelines. Allowing it is therefore not desirable because it breaks the conventions and unwritten rules Swift developers are used to.
One idea for improvement of the Plotly.swift *Axis
API would have all the *Axis
types adopt reference semantics. Or in other words it would become a class
. The .xAxis
/.yAxis
and .subplot
properties of different traces would become references to a class instance that could be shared as needed and re-used in other traces to obtain desired subplot axis association.
There are two possible ways how this could behave in code:
Layout.create*SubPlot
Factories for all *Axis
Typesvar scatter1 = Scatter(...)
var scatter2 = Scatter(...)
var layout = Layout(...)
scatter1.xAxis = layout.createXAxis( /* x1 axis customization goes here */ )
scatter2.xAxis = layout.createXAxis( /* x2 axis customization goes here */ )
var barPolar1 = BarPolar(...)
var barPolar2 = BarPolar(...)
var layout = Layout(...)
barPolar1.subPlot = layout.createPolarSubplot( /* polar axis customization goes here */ )
barPolar1.subPlot = layout.createPolarSubplot( /* polar axis customization goes here */ )
Layout
Parameter for All *Axis
Constructorsvar scatter1 = Scatter(...)
var scatter2 = Scatter(...)
var layout = Layout(...)
scatter1.xAxis = .init(layout: layout, /* x1 axis customization goes here */ )
// = Layout.XAxis(layout: layout, /* x1 axis customization goes here */ )
scatter2.xAxis = .init(layout: layout, /* x2 axis customization goes here */ )
// = Layout.XAxis(layout: layout, /* x2 axis customization goes here */ )
var barPolar1 = BarPolar(...)
var barPolar2 = BarPolar(...)
var layout = Layout(...)
barPolar1.subplot = .init(layout: layout, /* polar subplot customization goes here */ )
// = Layout.Polar(layout: layout, /* polar subplot customization goes here */ )
barPolar1.subplot = .init(layout: layout, /* polar subplot customization goes here */ )
// = Layout.Polar(layout: layout, /* polar subplot customization goes here */ )
Both proposals imply that all properties of Layout
struct that currently store the *Axis
type would have to privately store a and manage a list of references [*Axis]
instead.
Done!
Currently, the
Layout
struct doesn't allow customization of subplot axes. When one creates aFigure
with multiple traces that are displayed as sub-plots, there's no way to set properties of the second and all the following axes of any type.Here's the full list of axis types that exist in the
Layout
object and can't be customized and shared between subplots:XAxis
YAxis
Scene
subplot axes:XAxis
YAxis
ZAxis
Polar
subplot axes:RadialAxis
AngularAxis
Ternary
subplot axes:AAxis
BAxis
CAxis
Geo
subplot axes:LatitudeAxis
LongitudeAxis
ColorAxis