svgdotjs / svg.js

The lightweight library for manipulating and animating SVG
https://svgjs.dev
Other
11.04k stars 1.08k forks source link

added Runner.text() to swap text during animation #1164

Closed pragdave closed 1 year ago

pragdave commented 3 years ago

This is more a request for review than a pull request.

I needed to be able to change text as part of the timeline (think of a counter that gets updated every second). It needs to be in a runner so that the displayed value is accurate when I scrub back and forth in the timeline.

I added the function Runner.text() to do this. It first checks that it is being called on a Text element, and then sets up a morphable from 0 to 1. In the update function, I switch between the old and new text as the morph position crosses 0.5 (in either direction). I also fade the old text down during the first half of the morph, and the new text up in the second half (again, in a reversible way).

I all seems to work fine. The reasons I suggest it might need review is:

  1. It seems a little hokey updating the element in the morphable callback inside Runner. The other values are handled inside Morphable itself, but I couldn't find an obvious way to handle the fact that the animated value (the number) was not directly affecting an element's attribute.

  2. I must be misunderstanding how the tests are set up, because the tests don't see the value of the text changing (but it does change IRL).

  3. I haven't done any documentation changes (which I will).

Cheers

Dave

coveralls commented 3 years ago

Coverage Status

Coverage decreased (-0.8%) to 99.083% when pulling 816e12536aeaf6935269b6472463a3be334c12e8 on pragdave:animate-text into 99e176f76332b47a6c026dbd9dcf7742191b8b29 on svgdotjs:master.

Fuzzyma commented 3 years ago

I think you overkilled that one a bit :D. While I agree that the runner needs a text method, it should just change the text at the end of the animation (that's usually how non-morohable animations are done). We already have a non-morohable which we can use their. If you also want to change the opacity you can do that in a different parallel animation :)

pragdave commented 3 years ago

Indeed, overkill is my middle name... :)

First, I did try just switching text. It felt a little abrupt. This might be because in my framework I normally fade all text in and out (really quickly), which I think makes it look more polished.

If you want to have a simple text switch function, is there any chance we could also keep this one, perhaps as something like ftext() ("f" for fade)?

Fuzzyma commented 3 years ago

Well the idea is to just fade the text in a parallel animation. You can simply schedule the fade to happen to the end of the animation, then the text is switched and you can fade it in with a different animation

pragdave commented 3 years ago

Cool. I keep what I wrote locally, then, as something specific to my particular project.

I'm not sure how I'd use NonMorphable, though: wouldn't getClassForType interpret a string parameter as a Color. PathArray. or SVGArray?

Fuzzyma commented 3 years ago

It depends on their structure. But not sure right now

pragdave commented 3 years ago

I spent a little time looking at this, and I'm even more confused.

Are you meaning something like this:

text(toText) {
   this._queueObject("text", new SVGText(toText))
}

So then I'd create an SVGText wrapper, and add it to _getClassFor in Morphable?

Neon22 commented 3 years ago

I'll just leave this here. In Vue3 they define transitions like fade like in here:

I'm hoping this is relevant for parallel effects like this.

Fuzzyma commented 2 years ago

@pragdave sorry for the long delay. Here is what I came up with: https://codepen.io/fuzzyma/pen/LYjXqPv

const t = canvas.text('Hello World').amove(100, 100)

t.animate().opacity(0).animate(0).queue(() => t.text('asd')).animate().opacity(1)

It boils down to 3 animations. First one is changing the opacity to 0. Second one just changes the text. Third one animates opacity back to 1

Fuzzyma commented 1 year ago

I am so sorry that I am closing all your PRs. Thank you so much for contributing. It is hard to keep up 😅