Draw SVG rope using JavaScript
muffinman.io
muffinman.io
Woah! This kinda exploded, thank you so much for the kind words!
Lately, I'm trying to add more interactivity to my posts. Mainly inspired by amazing work of Bartosz Ciechanowski [1].
I started drawing with code a few years ago and completely fell in love with it. Problems like this one scratch my itch for creative programming.
I hope some of my posts will inspire people to try making pictures using code, just for the sake of it. Programming should be fun :)
edit: typos
P.S. Unfortunately I had some bad experiences with leaving contact info public.
edit: typo
EDIT: Fixed it, thanks again!
There’s also <content type="xhtml"> which requires an XHTML-namespaced wrapper div and goes full XML, but you should only use that if your tooling will guarantee its XML validity. <https://datatracker.ietf.org/doc/html/rfc4287#section-4.1.3> is the spec for all of this. Reflecting on this and your particular content, there’s a fun technicality that probably theoretically makes type="xhtml" unsuitable for you: you can only use <noscript> in HTML syntax, not XML syntax, because it’s resolved at parse time.
Plotting is the reason I always try to generate vector images. I'll probably try to plot a drawing with these ropes. But I would like to add some kind of shading and to figure out how to tie knots.
(a calligraphic pen is simply a solid angled ellipse that you move along the stroked path without changing its orientation)
After seeing the GPS post [1] on that website, I also decided that I wanted to write posts with more visualizations. I wonder how many people the author has inspired!
Something small seems a little off and I'm trying to quantify it. It's something to do with the rope in the tighter bends. Somehow I think the rope needs to be a little tighter — the twisted bits a little closer together as the bend tightens.
Maybe tightening the spacing between "knots" relative to the amount of curvature — rather than using a fixed spacing? Imagine some longitudinal compression occurs as the bend tightens.
Here's an example of an "analog" rope image that might be illustrative: https://cpartyrentals.com/wp-content/uploads/2015/06/rope-le...
I feel the same way. Of course it's easier for visual tasks like this one, but I tend to think of programs developing in space and time as trees and graphs, even for abstract stuff like complex algorithms and data structures.
Though I think most programmers are more language-oriented. It is often hard for me to find the exact syntax required for coding a particular problem which is fully formed in my mind eye as visual steps. Programming languages are oriented to represent each concept with a precise linguistic abstract syntax, instead of representing concrete changes in the program state, and most developers don't seem to mind.
I’ve found this to work out well for me:
- Use languages and tools that let you defer correctness while prototyping. I lose track of “the bigger picture” if I have to context switch to thinking pedantically about syntax and type systems. That’s ok when everything is in place, but is disruptive when experimenting.
- Find good visualization aids, such as sequence diagrams, dependency trees, call graphs etc. Even if you just do it on paper, they can be great tools.
- Read up a bit about dataflow programming. It fits my brain very well, and you can apply the thinking in any language. (Unfortunately existing dataflow oriented programming environments are quite limited and come with other downsides).
Let me know if you have tips to share as well.
I like environments where you can keep visualization aids close to the code to which they apply; nowadays, that means using online notebooks a la Jupyter and ObservableHQ, or at least markdown files with a preview plugin integrated in your IDE. There you can represent diagrams as code, like Graphviz and Mermaid.
I long for the day that those visual representations can be accessed programmatically and used as part of the code itself, like VB6 interactive widgets were created graphically yet usable in the application; e.g. creating state machines visually by representing states and transitions as boxes and arrows, then compiling the diagram to add conditions and access their values from code (there are some libraries doing this in some environments and languages, but I'm not aware of one that is portable to many languages). I think we're really close to that being possible with modern languages.
I would like to comment that for the animation it has the rope anchored on the left. I think that a up and down loop animation would be most natural to have the center of the rope anchored since that motion is generated with two hands going in and out, the center should not look like it slides back and forth as the visible length changes.
I've kept the interactive image short on purpose, so it doesn't cover too much content. Then I tried to squeeze as much movement in that short area.
I may go back and update examples a little bit.
37 years in myself
unfortunately SVG 2 has been stuck in draft for pretty much an eternity
- design a rope pattern as you like (or any other pattern) as if it were perfectly straight - e.g. design your pattern as if the X axis were the path and the Y axis were the normals.
- now take your actual (non-straight) path, divide it into sections and calculate the normals just as described in the post. Don't do any skewing.
For now, I assume the path has a fixed length, so the length of your pattern must be the same as the length of the path.
- divide the pattern into the same number of sections as the path has.
- now you have a 1:1 correspondence between sections on the path and sections on the pattern. Each section begins and ends with a normal perpendicular to the length of the path or pattern. The only difference is that the pattern's sections are rectangular while the path's sections are trapezoids.
- you can map the coordinate systems between them with a linear transformation.
- finally, you can take the vectors that make up your rope pattern and transformation them into the coordinate systems of the path, section by section. Now your previously straight pattern follows the path!
Caveats:
1) This assumes your path has a fixed length and your pattern is defined over the entire length. It would probably be more practical to have a repeating pattern or a function that can generate a pattern given the desired path length.
2) Each section is transformed individually, so if in the pattern, you have a straight line that crosses a section boundary, the line will have a visible kink after transformation. A way to mitigate this would be to use multiple overlapping sets of sections and interpolate the transformation between them.
3) The shape of the path sections is only determined by the two normals bounding the section - so all the path curvature inside a section is lost. If the path is very "curvy" and the sections are too coarse, the pattern will not correctly follow the path. This can be improved by increasing the number of sections and making the individual sections smaller.
This blew my mind for some reason.
* I have vimium binded, so the sample keys aren't conflict
That's not to say it's not possible, just so extremely rare that it's not a reasonable design consideration.
Best and clearest advice I've seen for quite a while :)
The proper way to bend some graphics around a curve is by transforming it to the tangent frame.
If you have a parametric curve c(t) = (x(t), y(t)), it’s easy to see that for each parameter value t, the tangent of the curve is going to point towards dc/dt = (dx/dt, dy/dt). You can take a perpendicular vector to this tangent by rotating it 90 degrees, and the two vectors will form a so-called tangent frame at t.
If you want to bend your bitmap around this curve, the key idea is to transform the domain of the bitmap. That is, instead of putting your bitmap pixel at (x, y), you would put it at something like c(x) + (dc/dt)(y) (some scaling factors omitted for brevity).
(In practice, you would want to invert this mapping, and map the pixels around the curve back to the domain of the bitmap, to avoid holes, but that’s an implementation detail. The key idea is thinking in terms of warping the bitmap’s domain.)
Now do it in a webgl vertex shader
https://chagai.website/chagai-website-react/
Or the code here: