Mark implementation #10
Replies: 2 comments 1 reply
-
Progress! With the PR in flight, the most basic versions of going from declaration to rendered graphics is operational. The pattern that I leaned into use was having each mark be responsible for generating data instances that represent the individual symbols, and all the details needed to render them, given a drawing area specified as a The I thought about having each symbol know how to render itself, but opted instead to have the I do rather wish that As I'm writing this, I've generated all the data structures for the shapes for dots/points, simple straight lines, and bars for charting, but am only rendering the points currently. The others to be included fully through rendering before I merge the PR. There's no notable test coverage as yet, which remains to be done - and the drawing area is super-basic, without any axis, override capabilities, etc - but it proves the end-to-end flow from declaration with data into a visual canvas. One of the work items I'm planning on adding quickly after this is complete is a simple benchmark to capturing the time it takes to go from data & declaration to rendered canvas so that I can track that and keep an eye out for unexpected regressions in algorithms or exponential loops. There's a couple in sequence through fairly divorced code sections, which could be easy to do inefficiently or accidentally. The process of getting this working end-to-end illuminated some limitations (and mistakes) in earlier API structure - and in some of the assumptions I'd made in scale, so various updates have been back-propagated there as well. |
Beta Was this translation helpful? Give feedback.
-
Starting into the bits of code that draw and lay out one of more axis on a chart has helped highlight some quandaries for the declaration semantics. So far I've been tracking the scaling and domains of input for each mark with that mark - so if you declared something like:
The two marks would each have their own scales and map into the space available, basically ignoring each other.
What would you expect to happen? They can't all display on the xAxis without terribly muddling things - although maybe that's appropriate. But in the case of the Do we go with "whatever defined the first (or last) .xAxis() wins" kind of scenario? Or should all three attempt to draw an axis, and muddle it up because that's what the declaration appears to ask to do? There is a use case where we'd like to have two X axis - one drawn on the bottom, and a second on top - so there's room in a standard 2D chart for two. Is there a case where you'd merge the domains of the incoming values, using a coordinated scale to display values from two data sources together in the same chart? |
Beta Was this translation helpful? Give feedback.
-
Mark
Extending into "what and how" of the implementation,
Mark
is a core consideration of this design.A mark represents a set of visual shapes (one or more), but more importantly it doesn't represent a single specific shape - with the various parameters applied, but a means to generate those shapes. The mark itself has mappings to describe how data should get transformed into something visual (I'm describing the mapping as
VisualChannel
in the code).I initially see two potential options for implementing this such that we get scribbles drawn into a canvas.
The first is that we make the
Mark
responsible for directly drawing into aGraphicsContext
provides from a canvas. The idea being that there's a method onMark
that takes a GraphicsContext and data, iterates through the data, and renders symbols at the appropriate positions on the canvas.Another is not to have
Mark
render directly to the canvas, but generate a series of individual symbols generated by iterating through the data, and those symbols are captured by something above the mark (Chart object, in this case) and it's responsible for rendering those symbols into a GraphicsContext from a Canvas.In order to know the specific locations of the symbols, the space available to the charting area needs to be known, which means this step of the drawing needs to take into account space for any other visual elements that don't overlap - such as axis, caption, and potentially a legend. In both of the above cases, I'm expecting that the final values are known by the end of this process, and any mapping from upstream data has taken place.
Beta Was this translation helpful? Give feedback.
All reactions