Search code examples
javascriptcssview-transitions-api

How to make View Transtion for a span that will shrink and expand during one transition?


I was playing with View transition API (available in Google Chrome).

I was creating demos for my library jQuery Terminal. I make what I want with two transitions. I set the text to single space and when the transition ends I use destination transition.

JavaScript:

let id = 0;
async function animate(messages, time) {
    const messages_copy = [...messages];
    const empty = wrap(' ');
    const first = wrap(messages_copy.shift());
    if (can_animate) {
        term.echo(empty);
        index = term.last_index();
        const transition = document.startViewTransition(() => {
            term.update(index, first);
        });
        await transition.finished;
        await delay(time);
        for (const message of messages_copy) {
           term.update(index, empty);
           
            const transition = document.startViewTransition(() => {
                term.update(index, wrap(message));
            });
            await transition.finished;
            await delay(time);
        }   
    } else {
        term.echo(first);
        await delay(time);
        const index = term.last_index();
        for (const message of messages_copy) {
            term.update(index, wrap(message));
            await delay(time);
        }
    }
    ++id;
}

const wrap = message => {
    return `<text name="${id}">${message}</text>`;
};

const delay = time => new Promise(resolve => {
    setTimeout(resolve, time);
});

// formatting to diplay text with given view-transition-name name and given class
$.terminal.new_formatter([
    /<text name="([^"]+)">(.*?)<\/text>/g,
    '[[;;;terminal-inverted;;{"style": "view-transition-name: t_$1"}]$2]'
]);

CSS:

/* ref: https://codepen.io/argyleink/pen/ZEmLrze */
::view-transition-old(*),
::view-transition-new(*) {
    height: 100%;
    width: 100%;
}

I've tried this:

::view-transition-old(*) {
  animation: 0.5s transition-out 0s ease;
}

::view-transition-new(*) {
  animation: 0.5s transition-in 0s ease;
}

@keyframes transition-out {
    from {
        max-width: 100%;
    }
    to {
        max-width: 0;
    }
}

@keyframes transition-in {
    from {
        max-width: 0;
    }
    to {
        max-width: 100%;
    }
}

But this transition happens on the whole page. I want it applied only for my text like in the reference CodePen.

Here is my CodePen demo for View Transistions

The code uses jQuery Terminal but in fact, it's not related to the library. Since I just update DOM with span and view-transition-name CSS property. But I can create simple Demo without the library, but note that the code will probably be the same only term.echo() and term.update() will change to directly update the DOM.


Solution

  • To remove the transition from the whole page add this CSS:

    :root {
      view-transition-name: none;
    }
    

    That will still let the other View Transitions run.

    And if you only want the animation to run on the last command line entry you might want to look at setting view-transition-name: none on the element after it finishes the animation. Then only the new entry will have a View Transition name so will be the only one to animate.