metafizzy / zdog

Flat, round, designer-friendly pseudo-3D engine for canvas & SVG
https://zzz.dog
10.38k stars 394 forks source link

SVG path import for custom shapes and text #16

Open chrisgannon opened 5 years ago

chrisgannon commented 5 years ago

The ability to draw a bezier path (in a vector program) and convert that path data into usable Zdog code would be very useful.

desandro commented 5 years ago

Add a πŸ‘ reaction to this issue if you would like to see this feature added. Do not add +1 comments β€” They will be deleted.


Thanks for this feature request. Yeah, currently you have to hard code all your path commands. Adding SVG path importing would open up Zdog to a lot more custom designs, including proper typography.

chrisgannon commented 5 years ago

I have a rudimentary workflow for this using Greensock's MorphSVGPlugin method pathDataToBezier (to convert, well, path data to an array of bezier objects). You then pass that output into my own makeZdogBezier function that creates a Zdog-specific bezier structure.

I'm also animating and sequencing using Greensock.

Here's a few examples: https://codepen.io/chrisgannon/pen/4ef3e5deaf41cf81415c52112ea2692c https://codepen.io/chrisgannon/pen/886fb698e67c13b8369a2ec05a640900

eeropic commented 5 years ago

Cooool stuff!! Was actually working on the same thing, but through Paper.JS - it can import SVG and makes handling and conversion of the vector objects very easy

https://codepen.io/eeropic/pen/rgQapW)

zdog-svg2

chrisgannon commented 5 years ago

@eeropic Nice demo! It seems we're both having to use large libraries for just one conversion operation which is quite wasteful and bloated. I would love to see Zdog have this built in.

Here's another demo - this one is pure SVG (with transparency)!

https://codepen.io/chrisgannon/pen/OYadbL Zdog-Shades

eeropic commented 5 years ago

Agree. But there’s just a lot of stuff to cover if you want to support using defs, embedded css classes for object styles etc. Maybe the SVG parsing part could be forked.

eeropic commented 5 years ago

@chrisgannon should we make a PoC with DOMParser? :) Combined with something like https://github.com/jkroso/parse-svg-path/blob/master/index.js

turbo commented 5 years ago

@chrisgannon or @eeropic can either one of you please detail the workflow you've used to create and import these shapes? A short bullet point summary with code samples would be much appreciated. Trying to wrap my head around this πŸ˜….

chrisgannon commented 5 years ago

image

turbo commented 5 years ago

@chrisgannon Thx, was able to adapt that technique to vectors created with https://vectr.com.

chrisgannon commented 5 years ago

If you don't have a Greensock license, https://path2bezier.netlify.com/ is an (untested) alternative to using MorphSVGPlugin to convert path data. I have tried it a few times and it seems to work fine so far.

turbo commented 5 years ago

@chrisgannon I chose vectr because its one of the few free online vector tools. I usually work in Inkscape locally. I tested your tool with a few shapes copied from vectr and it seems to work :)

charlesr1971 commented 5 years ago

@chrisgannon I have used your makeZDogBezier() function, after getting an array from https://path2bezier.netlify.com/. It does a great job, however 3 of my paths close, when they shouldn't. The result of which, generates diagonal lines from certain points along the bezier. You can see from the screenshot that the white outline is the result of using your function. The red shape is the pure SVG! 6AC95006-0E8D-4A50-AD2A-EE4A7ED0B664

chrisgannon commented 5 years ago

Do you have closed:true on your constructor? If so set it to false.

charlesr1971 commented 5 years ago

Hi Chris

Well, I have tried it with:

closed: true

And

closed: false

And, it makes no difference.

I have analysed the path carefully and have taken out the 'Z', one by one, but again this does not resolve the problem.

The path is made up of 4 Bezier. I think this signifies:

3 Bezier for each cut out [head, 2 legs] 1 Bezier for the path outline [I reckon this is the big path at the start]

Anyway, for what it's worth, here is my path:

M 92.62,58.18 C 91.16,57.82 89.69,58.72 89.34,60.17 89.32,60.26 87.06,69.28 81.00,68.00 75.75,66.89 75.42,61.32 75.54,55.22 75.55,54.69 75.56,54.20 75.56,53.76 75.56,48.51 72.24,34.09 61.58,34.09 58.20,34.09 55.64,34.85 53.71,35.88 53.71,35.88 53.71,34.40 53.71,34.40 59.07,32.97 63.07,27.41 63.07,20.79 63.07,13.09 57.66,6.82 51.00,6.82 44.34,6.82 38.92,13.08 38.92,20.79 38.92,27.42 42.93,32.97 48.29,34.40 48.29,34.40 48.29,35.88 48.29,35.88 46.36,34.85 43.80,34.09 40.42,34.09 29.75,34.09 26.44,48.51 26.44,53.76 26.44,54.20 26.45,54.69 26.46,55.22 26.58,61.32 26.25,66.89 21.00,68.00 15.02,69.25 12.76,60.58 12.66,60.17 12.30,58.71 10.84,57.82 9.38,58.18 7.93,58.53 7.03,60.00 7.39,61.46 8.48,65.92 12.38,73.56 19.72,73.56 20.48,73.56 21.28,73.48 22.12,73.31 32.20,71.18 31.99,60.33 31.89,55.12 31.88,54.62 31.87,54.17 31.87,53.76 31.87,49.71 34.41,39.51 40.42,39.51 45.64,39.51 47.70,41.98 48.29,42.90 48.29,42.90 48.29,80.22 48.29,80.22 48.29,80.69 47.90,81.66 46.97,82.94 39.88,78.51 33.09,74.62 25.86,75.07 16.51,75.66 12.21,81.83 12.18,87.30 12.15,92.76 16.27,98.61 24.20,99.20 33.44,99.90 42.69,94.68 47.89,89.93 48.32,90.20 48.75,90.47 49.19,90.73 47.89,92.94 47.14,95.09 47.07,96.99 46.81,103.94 47.06,109.16 47.07,109.38 47.14,110.83 48.34,111.96 49.78,111.96 49.82,111.96 49.86,111.96 49.91,111.96 51.41,111.89 52.56,110.62 52.49,109.12 52.49,109.07 52.24,103.89 52.49,97.18 52.53,96.18 52.99,94.88 53.83,93.45 60.31,97.03 67.42,99.84 75.35,99.26 86.88,98.43 90.76,92.65 90.56,87.52 90.32,81.72 84.32,75.52 75.12,75.60 66.04,75.69 57.65,80.66 52.45,86.37 52.16,86.19 51.86,86.01 51.57,85.83 52.77,84.11 53.71,82.15 53.71,80.22 53.71,80.22 53.71,42.89 53.71,42.89 54.30,41.97 56.36,39.51 61.58,39.51 67.59,39.51 70.13,49.70 70.13,53.76 70.13,54.17 70.12,54.62 70.11,55.12 70.01,60.33 69.80,71.18 79.88,73.31 80.72,73.48 81.51,73.56 82.28,73.56 89.62,73.56 93.52,65.92 94.61,61.46 94.97,60.00 94.07,58.53 92.62,58.18 Z M 24.61,93.79 C 19.75,93.43 17.59,90.28 17.60,87.33 17.62,84.42 19.88,80.88 26.21,80.48 26.47,80.46 26.74,80.46 27.00,80.46 32.05,80.46 37.43,83.42 43.09,86.92 38.30,90.84 31.12,94.29 24.61,93.79 Z M 75.18,81.03 C 75.22,81.03 75.27,81.03 75.31,81.03 81.03,81.03 85.00,84.48 85.13,87.74 85.27,91.04 81.37,93.38 74.95,93.84 68.66,94.30 62.82,92.14 57.22,89.12 61.31,84.97 67.73,81.10 75.18,81.03 Z M 44.35,20.79 C 44.35,16.08 47.33,12.24 51.00,12.24 54.67,12.24 57.65,16.08 57.65,20.79 57.65,25.50 54.67,29.34 51.00,29.34 47.33,29.34 44.35,25.50 44.35,20.79 Z

Thanks

Charlie

Charles Robertson

Establish Mindfulness, Technical Director

E: cdesign@btinternet.com U: app.establishmindfulness.com B: www.establishmindfulness.com T: admin@establishmindfulness.com

Sent from my iPhone

On 4 Jun 2019, at 07:18, Chris Gannon notifications@github.com wrote:

Do you have closed:true on your constructor?

β€” You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

chrisgannon commented 5 years ago

Ok your issue is that you are using a compound path (several paths squished together into one path).

This is @greensock's MorphSVGPlugin pathDataToBezier output of your vector:

image

And this is the output from https://path2bezier.netlify.com/:

image

Greensock deals with it a bit better but I would recommend avoiding compound paths. These converters tend to prefer just one path.

In this particular instance, because of the shape of your vector, I would recommend drawing it with stroked paths instead - that way you will get decent 3D depth in Zdog.

charlesr1971 commented 5 years ago

Wow. Thanks for this analysis. Very interesting stuff.

I used to work with a program called POV-Ray [www.povray.org][yes, very old skool, I know!] This program had the ability to carry out path operations, like 'divide' & 'merge' etc. Anyway, I am getting side tracked.

So, you reckon that I should try and create this shape from scratch, using Ellipse etc? I did notice that there wasn't much depth to my shape, once rendered. Although, stroking it heavily did help, but then I started to lose the shape definition.

I guess, if I create it from scratch, I can control all these factors better?

I will give it a go.

Cheers

Charlie

Charles Robertson

Establish Mindfulness, Technical Director

E: cdesign@btinternet.com U: app.establishmindfulness.com B: www.establishmindfulness.com T: admin@establishmindfulness.com

Sent from my iPhone

On 4 Jun 2019, at 10:15, Chris Gannon notifications@github.com wrote:

Ok your issue is that you are using a compound path (several paths squished together into one path).

This is @greensock's MorphSVGPlugin pathDataToBezier output of your vector:

And this is the output from https://path2bezier.netlify.com/:

Greensock deals with it a bit better but I would recommend avoiding compound paths. These converters tend to prefer just one path.

In this particular instance, because of the shape of your vector, I would recommend drawing it with stroked paths instead - that way you will get decent 3D depth in Zdog.

β€” You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

chrisgannon commented 5 years ago

Yes - currently you're having to fill the area meaning you don't have depth. If you then stroke it, you will add depth but you will also bloat your shape and, as you say, lose definition.

charlesr1971 commented 5 years ago

Chris

One last thing.

When I am working in Adobe Illustrator, I usually create a horizontal line with 2 points.

Then I add a single Bezier point in the middle of the line. Then I pull out the left & right control handles, perfectly horizontal. Then I move the Bezier point, itself, downwards to create a curve in the line.

Is there any way to emulate this, in zDog?

Thanks

Charlie

Charles Robertson

Establish Mindfulness, Technical Director

E: cdesign@btinternet.com U: app.establishmindfulness.com B: www.establishmindfulness.com T: admin@establishmindfulness.com

Sent from my iPhone

On 4 Jun 2019, at 10:15, Chris Gannon notifications@github.com wrote:

Ok your issue is that you are using a compound path (several paths squished together into one path).

This is @greensock's MorphSVGPlugin pathDataToBezier output of your vector:

And this is the output from https://path2bezier.netlify.com/:

Greensock deals with it a bit better but I would recommend avoiding compound paths. These converters tend to prefer just one path.

In this particular instance, because of the shape of your vector, I would recommend drawing it with stroked paths instead - that way you will get decent 3D depth in Zdog.

β€” You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

chrisgannon commented 5 years ago

Do you mean like this @charlesr1971 ?

https://codepen.io/chrisgannon/pen/ca10b0aec2f6ea775cedb16b9accee6e

charlesr1971 commented 5 years ago

Anyway. No worries. I exported that segment of the stick person path out of Illustrator/GIMP as an SVG, and then used the Bezier conversion tool from Netlify.

And then used your function to get the perfect Bezier.

Now, I have what I need.

But thanks for your help! I am a beginner with zDog and just finding my feet, at the moment. It is certainly a very cool library!

Cheers

Charlie

Charles Robertson

Establish Mindfulness, Technical Director

E: cdesign@btinternet.com U: app.establishmindfulness.com B: www.establishmindfulness.com T: admin@establishmindfulness.com

Sent from my iPhone

On 4 Jun 2019, at 11:50, Chris Gannon notifications@github.com wrote:

Do you mean like this @charlesr1971 ?

https://codepen.io/chrisgannon/pen/ca10b0aec2f6ea775cedb16b9accee6e

β€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

charlesr1971 commented 5 years ago

Can anyone tell me how I access the color of a child shape, if I create a new shape, using copyGraph() on a parent shape that has two children?

turbo commented 5 years ago

@charlesr1971 Related: #6

Right now there's no easy way to access a child of a parent copied with copyGraph.

charlesr1971 commented 5 years ago

@turbo Thanks for this information. It kind of makes this API difficult to use. It's one of the most basic requirements. For instance, if I want to create a sphere, I have to add one hemisphere to another. I'm also wondering, at this point, why there isn't a sphere primitive, but that's for another day. But, if I want to change the color of the child hemisphere, dynamically, there is no way to achieve this. If you have an API that allows child objects, there should be some way of accessing them.

chrisgannon commented 5 years ago

@charlesr1971 @turbo I think you access the parent's children fairly easily when rendering to SVG.

Demo (animated using @greensock) : https://codepen.io/chrisgannon/pen/405d479f0270d31bbd77e7e7efb49fce

image

charlesr1971 commented 5 years ago

@turbo You are a life saver. Thank you sir!

turbo commented 5 years ago

Wrong person @charlesr1971

charlesr1971 commented 5 years ago

@chrisgannon Sorry. I said thank you to the wrong person. Thanks Chris. I couldn't believe there was no way to access children!

turbo commented 5 years ago

@charlesr1971 Also not sure what you mean by sphere primitive. A hemisphere is a compound shape, whereas the sphere is the default shape:

new Zdog.Shape({
  addTo: illo,
  stroke: 80, // diameter
  color: '#636',
});
charlesr1971 commented 5 years ago

OK. I need to make an apology to the zDog team. In fact, you can call the 'children' property on any shape, not just anchors. I managed to access this property on my child hemisphere. Problem solved. It's just me being a stupid newbie!

charlesr1971 commented 5 years ago

@chrisgannon OK. So, in POV-Ray, we had spheres, boxes, triangles etc. But not hemispheres, so I assumed that a sphere is a primitive shape?

charlesr1971 commented 5 years ago

@chrisgannon OK. So, shape = sphere by default? Why not call it a 'sphere'?

charlesr1971 commented 5 years ago

Right. I was a little confused when I couldn't see sphere anywhere? Maybe I missed the default shape example in the docs. I will have another read through...

turbo commented 5 years ago

@charlesr1971 Because there is no such thing as a sphere. zDog is not a 3D engine, but a 2.5D engine. A sphere is the same thing as a point, which are both rendered using ellipses/circles on 2D canvas and SVG targets. Since there is neither perspective nor shading, it is inconsequential that "spheres" don't have depth. Again, no spheres here, just shapes.

The Box is also not an actual shape, but a compound group of Rectangles. You can skim the source code for the built-in compound groups to get an idea of how this works.

TL;DR 2.5D engines "trick" you into seeing 3D, but they are just rendering flat shapes. This very different from 3D canvas/SVG engines such as phoria.js or the (now removed) THREE.js canvas renderer.

charlesr1971 commented 5 years ago

@turbo Thanks for the explanation. 2.5D. Never heard of this, but I have to say I have never seen anything like zDog before. This is partly what makes it so cool. I like the fact that there is no shading. It works well for the whole flat design genre.

charlesr1971 commented 5 years ago

I like the way, that you can't always tell what the shape is until, it is dragged or animated. It messes with your head, which makes it, so interesting.

charlesr1971 commented 5 years ago

Coming from a 3D background, I need to get use to the new lingo & it's paradigm.

turbo commented 5 years ago

@charlesr1971 I think this is a good way to visualize the difference between 2.5 and 3D: http://www.kevs3d.co.uk/dev/phoria/test3.html

The point light (upper left corner) source is a "sphere" in the zDog sense. It doesn't have any depth, and is not affected by perspective (only in size (stroke in zDog)). The sphere in the centre is a conventional 3D object (which is what you're used to).

3D engines can be used in flat-shading mode to emulate zDog demo, but they will always have a viewport with perspective projection, something that doesn't exist in 2.5D (aka pseudo-3d) engines. Compare the milk demo with zDog's "Box"es - the milk carton has a vanishing point.

what the shape is until, it is dragged or animated

That's the point of 2.5D :). The idea originates from early sprite-layering games: https://images.app.goo.gl/RizABiiiGwFaa2Cz8

charlesr1971 commented 5 years ago

Nice stuff. I'm just off to destroy those 2 hemispheres & create a nice single default sphere like shape!πŸ˜‰

charlesr1971 commented 5 years ago

One last thing. How many units in a full rotation [not using TAU]. Do you use 360 or 1? I am doing a rotation animation and I want to detect, when the Anchor has done a half rotation?

chrisgannon commented 5 years ago

@charlesr1971 Zdog (and JS) natively use radians but I work in degrees so I have to pass all my radians values to a conversion function (below) so my brain can understand it!

function radiansToDegrees (_val) { return _val * (Math.PI/180); }

charlesr1971 commented 5 years ago

@chrisgannon Awesome stuff. This is perfect!

charlesr1971 commented 5 years ago

OK. So, inside my animation function, I have got:

foo.rotate.z += 0.03; console.log(radiansToDegrees(foo.rotate.z)); // output: 0.00523

I was expecting your function to spit out something between 1 - 360

I need to detect when my object has rotated more than 180 degrees. But at the moment the incremental rotation value never resets itself to zero, when it has carried out a full rotation. It just increments to infinity.

desandro commented 5 years ago

@charlesr1971 I love your interest and enthusiam for Zdog and this challenge. But I would appreciate that you use this issue thread to discuss general issues. This issue is currently the #1 requested issue, so back-and-forth conversation adds noise.

sakamies commented 5 years ago

Hi! Fell in love with Zdog and wanted this feature too. I made my own rudimentary svg shape importer. Wanted to share this even if it's just a funky prototype.

https://codepen.io/sakamies/pen/KKKaKmJ

Quite a few caveats of course.

chrisgannon commented 5 years ago

When I add some simple text outlines I get an error

Uncaught TypeError: anime.stagger is not a function
    at pen.js:256
sakamies commented 5 years ago

@chrisgannon That error most probably is just my mistake and nothing to do with Zdog. l added my script as its own github project, so we can discuss this there as an issue.

https://github.com/sakamies/zdog-svg-importer

Can't promise any maintenance for this little importer, but discussion, forks or pull requests are welcome.