Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Updates to keyed lists break FLIP animations when they occur mid-animation #2612

Open
Assignees
dead-claudia
Labels
Area: CoreFor anything dealing with Mithril core itselfType: BugFor bugs and any other unexpected breakage
@dead-claudia

Description

@dead-claudia

Mithril version: 2.0.4

Browser and OS: Chrome 83.0.4103.116 on Windows 64-bit, Safari 13.1 on iOS, Firefox 78.0.2 on Windows 64-bit

Project:

Code

Live Flems

<buttonid="toggle">Toggle</button><divstyle="display:flex"><ulid="prev"><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ulid="animate"></ul><ulid="next"><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul></div>
constanimateRoot=document.getElementById("animate")letvalues=Array.from({length:8},(_,i)=>i)functionrender(){m.render(animateRoot,values.map(i=>m("li",{key:i},i)))}letinterval=setTimeout(updateBody,500)functionupdateBody(){interval=setTimeout(updateBody,500)constprev=values// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffleconstnext=values=prev.slice()for(leti=next.length-1;i>0;i--){constj=Math.floor(Math.random()*(i+1))consttemp=next[j]next[j]=next[i]next[i]=temp}requestAnimationFrame(()=>{constprevList=document.getElementById("prev").childNodesconstnextList=document.getElementById("next").childNodes// Reorder elements in DOMfor(leti=0;i<prev.length;i++){prevList[i].textContent=prev[i]}for(leti=0;i<next.length;i++){nextList[i].textContent=next[i]}constprevElems=Array.from(animateRoot.childNodes)// FirstconstfirstParent=animateRoot.getBoundingClientRect()constfirst=prevElems.map(e=>{constchild=e.getBoundingClientRect()return{top:child.top-firstParent.top,left:child.left-firstParent.left,}})render()// Last + InvertconstlastParent=animateRoot.getBoundingClientRect()constmovedElems=prevElems.filter((e,i)=>{constlast=e.getBoundingClientRect()constdx=first[i].left-(last.left-lastParent.left)constdy=first[i].top-(last.top-lastParent.top)if(dx===0&&dy===0)returnfalsee.style.transform=`translate(${dx}px,${dy}px)`e.style.transitionDuration="0s"returntrue})// Force re-layoutdocument.body.offsetHeight// PlaymovedElems.forEach((e,i)=>{constcallback=()=>{e.removeEventListener("transitionend",callback,false)e.classList.remove("transition")}e.classList.add("transition")e.addEventListener("transitionend",callback,false)e.style.transform=e.style.transitionDuration=''})})}document.getElementById('toggle').onclick=()=>{if(interval){clearTimeout(interval)interval=null}else{updateBody()}p('toggle',interval!=null)}render()

Steps to Reproduce

  1. Open web page

You can enable and disable the animations at will using the "Toggle" button, but that's not part of the repro.

Expected Behavior

The animation to be smooth.

Current Behavior

The animation appears choppy whenever the subtree updates, and list items often unexpectedly jump.

Context

The following vanilla code works correctly. It's a near-exact clone of the above, but it simply usesappendChild instead of a full keyed diff.

Live Flems

<buttonid="toggle">Toggle</button><divstyle="display:flex"><ulid="prev"><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ulid="animate"><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ulid="next"><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul></div>
constanimateRoot=document.getElementById("animate")letcachedElems=Array.from(animateRoot.childNodes)letinterval=setTimeout(updateBody,500)functionrender(){for(constelemofcachedElems)animateRoot.appendChild(elem)}functionupdateBody(){interval=setTimeout(updateBody,500)constprevElems=cachedElemsconstnextElems=cachedElems=prevElems.slice()// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shufflefor(leti=nextElems.length-1;i>0;i--){constj=Math.floor(Math.random()*(i+1))consttemp=nextElems[j]nextElems[j]=nextElems[i]nextElems[i]=temp}requestAnimationFrame(()=>{constprevList=document.getElementById("prev").childNodesconstnextList=document.getElementById("next").childNodes// Reorder elements in DOMfor(leti=0;i<prevElems.length;i++){prevList[i].textContent=prevElems[i].textContent}for(leti=0;i<nextElems.length;i++){nextList[i].textContent=nextElems[i].textContent}// FirstconstfirstParent=animateRoot.getBoundingClientRect()constfirst=prevElems.map(e=>{constchild=e.getBoundingClientRect()return{top:child.top-firstParent.top,left:child.left-firstParent.left,}})render()// Last + InvertconstlastParent=animateRoot.getBoundingClientRect()constmovedElems=prevElems.filter((e,i)=>{constlast=e.getBoundingClientRect()constdx=first[i].left-(last.left-lastParent.left)constdy=first[i].top-(last.top-lastParent.top)if(dx===0&&dy===0)returnfalsee.style.transform=`translate(${dx}px,${dy}px)`e.style.transitionDuration="0s"returntrue})// Force re-layoutdocument.body.offsetHeight// PlaymovedElems.forEach((e,i)=>{constcallback=()=>{e.removeEventListener("transitionend",callback,false)e.classList.remove("transition")}e.classList.add("transition")e.addEventListener("transitionend",callback,false)e.style.transform=e.style.transitionDuration=''})})}// Utility bitsdocument.getElementById('toggle').onclick=()=>{if(interval){clearTimeout(interval)interval=null}else{updateBody()}p('toggle',interval!=null)}render()

Edit:

Mithril's far from the only one with this issue:https://twitter.com/isiahmeadows1/status/1284726730574315522

Note: Vue isnot affected by this bug and carries the same behavior as the vanilla version - gohere and spam the "Shuffle" button to see.

Edit 2: Also relevant:https://github.com/whatwg/html/issues/5742

Metadata

Metadata

Assignees

Labels

Area: CoreFor anything dealing with Mithril core itselfType: BugFor bugs and any other unexpected breakage

Type

No type

Projects

Status

High priority

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions


    [8]ページ先頭

    ©2009-2026 Movatter.jp