svg.js icon indicating copy to clipboard operation
svg.js copied to clipboard

added Runner.text() to swap text during animation

Open pragdave opened this issue 5 years ago • 9 comments

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

pragdave avatar Oct 28 '20 15:10 pragdave

Coverage Status

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

coveralls avatar Oct 28 '20 17:10 coveralls

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 :)

Fuzzyma avatar Oct 28 '20 22:10 Fuzzyma

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)?

pragdave avatar Oct 29 '20 00:10 pragdave

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

Fuzzyma avatar Oct 29 '20 10:10 Fuzzyma

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?

pragdave avatar Oct 29 '20 15:10 pragdave

It depends on their structure. But not sure right now

Fuzzyma avatar Oct 30 '20 04:10 Fuzzyma

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?

pragdave avatar Oct 31 '20 02:10 pragdave

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

  • https://youtu.be/L77Uq93XXzk?t=427 (Just watch for 30 secs)
  • So define it as 0 because the normal dom class state is opacity 1 and the fading class goes away when the transition ends.

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

Neon22 avatar Jun 16 '21 22:06 Neon22

@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 avatar Nov 16 '21 10:11 Fuzzyma

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

Fuzzyma avatar Sep 03 '23 12:09 Fuzzyma