jonobr1 / two.js

A renderer agnostic two-dimensional drawing api for the web.
https://two.js.org
MIT License
8.29k stars 455 forks source link

Commands should not belong to Two.Anchors #443

Open adroitwhiz opened 4 years ago

adroitwhiz commented 4 years ago

This may be related to #328.

Currently, each Two.Anchor has a Command property. However, these are a value from the Two.Commands enum, which mirrors SVG commands. The problem is that SVG commands refer to a segment, while an anchor is a vertex, so you can't really apply a command to an anchor. Instead, anchors could have properties like the number of handles, whether they are "smooth" (e.g. handles are all in a straight line), etc.

Paths could internally calculate a list of segments from these anchors, which the renderers could then more easily consume. Segments would also be a much more useful abstraction for calculating paths' beginnings and endings.

As an example, consider the following path, which consists of one "C" command (cubic bezier) and one "Q" command (quadratic bezier), and its corresponding "anchor" representation:

Anchors Segments
anchordemo-anchors anchordemo
jonobr1 commented 4 years ago

This is a good question and an underlying existential issue with Two.js. When I started making in 2012, I noticed that the move, line, and curve command took a majority of the commands when writing my own SVG and canvas2d shapes. So, while it looks like it mirrors the SVG spec, it's actually a simplification and only uses those three commands. The command on the Anchor loosely refers to the commands which as you note reference information on the previous anchor.

For the most part this isn't a perceptible issue for the user of Two.js as your two images show effectively the same curve. But, it would be far more advantageous to render them in segments, like pretty much every 2D renderer does, including the well written Paper.js. In addition it would disambiguate the Path._renderer.vertices and Path._renderer.collection because we could have Path._renderer.segments which is the intermediary between how Two.js has anchors like Adobe Illustrator and how SVG and Canvas expect to render specific commands.

I'm all for it, just haven't had the guts to take on the challenge 😉