英文:
How to use the View Transition API (web) for transition elements that are not the same DOM element?
问题
I have a thumbnail DOM element that needs to transition into the modal DOM element that opens when that thumbnail is clicked. The thumbnail and the modal are NOT the same DOM element. For this I want to use the View Transitions API.
关于使用不同的 DOM 元素进行过渡的话题在 Chrome 文章"使用 View Transitions API 实现平滑简单的过渡" 的其中一章中有介绍。
当我尝试构建缩略图到模态的过渡时,我发现过渡元素的行为与我的预期不同。我做错了什么?
我已经编写了我希望能工作的简化代码示例在this codepen中。
<!-- HTML -->
<div id="thumbnail">点击我</div>
<div id="modal">您已打开模态<div id="closer">X</div></div>
<div id="comment">粉色轮廓=::view-transition-old<br> 绿色轮廓=::view-transition-new</div>
/* CSS */
#thumbnail {
position: relative;
border: 2px solid darkred;
display: inline-block;
padding: 40px;
cursor: pointer;
}
#thumbnail:hover {
background-color: #74747444;
}
#modal {
display: none;
position: absolute;
translate: -50% -50%;
top: 50%;
left: 50%;
padding: 80px;
border: 2px solid blue;
}
#closer {
position: absolute;
top: 4px;
right: 4px;
cursor: pointer;
}
::view-transition-old(modal),
::view-transition-new(modal) {
animation-duration: 5s;
}
::view-transition-old(modal) {
outline: 4px solid pink;
}
::view-transition-new(modal) {
outline: 4px solid green;
outline-offset: 4px;
}
// JavaScript
const thumbnail = document.querySelector("#thumbnail")
const modal = document.querySelector("#modal")
const closer = document.querySelector("#closer")
thumbnail.addEventListener("click", () => openModal())
closer.addEventListener("click", () => {
modal.style.display = "none";
})
function openModal() {
// 针对不支持的浏览器的回退处理
if (!document.startViewTransition) {
modal.style.display = "block";
return;
}
thumbnail.style.viewTransitionName = "modal";
modal.style.viewTransitionName = "";
const transition = document.startViewTransition(() => {
modal.style.display = "block";
})
transition.updateCallbackDone.then(() => {
thumbnail.style.viewTransitionName = "";
modal.style.viewTransitionName = "modal";
})
transition.finished.finally(() => {
modal.style.viewTransitionName = "";
})
}
英文:
I have a thumbnail DOM element that needs to transition into the modal DOM element that opens when that thumbnail is clicked. The thumbnail and the modal are NOT the same DOM element. For this I want to use the View Transitions API.
The topic of using transition elements that are not the same DOM element is covered in one of the chapters of the Chrome article "Smooth and simple transitions with the View Transitions API".
I was surprised to find the transition element behave differently from what I expected, when trying to build the thumbnail-to-modal transition. What am I doing wrong?
I have written a simple variant of the code I expected to work in this codepen.
<!-- HTML -->
<div id="thumbnail">Click me</div>
<div id="modal">You have opened the modal<div id="closer">X</div></div>
<div id="comment">
pink outline = ::view-transition-old<br> green outline = ::view-transition-new"
</div>
/* CSS */
#thumbnail {
position: relative;
border: 2px solid darkred;
display: inline-block;
padding: 40px;
cursor: pointer;
}
#thumbnail:hover {
background-color: #74747444;
}
#modal {
display: none;
position: absolute;
translate: -50% -50%;
top: 50%;
left: 50%;
padding: 80px;
border: 2px solid blue;
}
#closer {
position: absolute;
top: 4px;
right: 4px;
cursor: pointer;
}
::view-transition-old(modal),
::view-transition-new(modal) {
animation-duration: 5s;
}
::view-transition-old(modal) {
outline: 4px solid pink;
}
::view-transition-new(modal) {
outline: 4px solid green;
outline-offset: 4px;
}
// JavaScript
const thumbnail = document.querySelector("#thumbnail")
const modal = document.querySelector("#modal")
const closer = document.querySelector("#closer")
thumbnail.addEventListener("click", () => openModal())
closer.addEventListener("click", () => {
modal.style.display = "none"
})
function openModal() {
// Fallback for non-supporting browsers
if (!document.startViewTransition) {
modal.style.display = "block"
return
}
thumbnail.style.viewTransitionName = "modal"
modal.style.viewTransitionName = ""
const transition = document.startViewTransition(() => {
modal.style.display = "block"
})
transition.updateCallbackDone.then(() => {
thumbnail.style.viewTransitionName = ""
modal.style.viewTransitionName = "modal"
})
transition.finished.finally(() => {
modal.style.viewTransitionName = ""
})
}
答案1
得分: 3
将代码thumbnail.style.viewTransitionName = null; modal.style.viewTransitionName = "modal"
从updateCallbackDone
promise回调移到startViewTransition
回调中就解决了问题。
所以新代码如下(也请参阅此codepen)。
<div id="thumbnail">点击我</div>
<div id="modal">你已经打开了模态框<div id="closer">X</div></div>
#thumbnail {
position: relative;
border: 2px solid darkred;
display: inline-block;
padding: 40px;
cursor: pointer;
}
#thumbnail:hover {
background-color: #74747444;
}
#modal {
display: none;
position: absolute;
translate: -50% -50%;
top: 50%;
left: 50%;
padding: 80px;
border: 2px solid blue;
background-color: white;
}
#closer {
position: absolute;
top: 4px;
right: 4px;
cursor: pointer;
}
const thumbnail = document.querySelector("#thumbnail")
const modal = document.querySelector("#modal")
const closer = document.querySelector("#closer")
thumbnail.addEventListener("click", () => openModal())
closer.addEventListener("click", () => {
modal.style.display = "none";
})
function openModal() {
// 不支持的浏览器的回退
if (!document.startViewTransition) {
modal.style.display = "block";
return;
}
thumbnail.style.viewTransitionName = "modal";
const transition = document.startViewTransition(() => {
thumbnail.style.viewTransitionName = null;
modal.style.viewTransitionName = "modal";
modal.style.display = "block";
})
transition.finished.finally(() => {
modal.style.viewTransitionName = null;
})
}
英文:
Moving the code thumbnail.style.viewTransitionName = null; modal.style.viewTransitionName = "modal"
from the updateCallbackDone
promise callback to the startViewTransition
callback did the trick.
So the new code is as follows (also see this codepen).
<div id="thumbnail">Click me</div>
<div id="modal">You have opened the modal<div id="closer">X</div></div>
#thumbnail {
position: relative;
border: 2px solid darkred;
display: inline-block;
padding: 40px;
cursor: pointer;
}
#thumbnail:hover {
background-color: #74747444;
}
#modal {
display: none;
position: absolute;
translate: -50% -50%;
top: 50%;
left: 50%;
padding: 80px;
border: 2px solid blue;
background-color: white;
}
#closer {
position: absolute;
top: 4px;
right: 4px;
cursor: pointer;
}
const thumbnail = document.querySelector("#thumbnail")
const modal = document.querySelector("#modal")
const closer = document.querySelector("#closer")
thumbnail.addEventListener("click", () => openModal())
closer.addEventListener("click", () => {
modal.style.display = "none"
})
function openModal() {
// Fallback for non-supporting browsers
if (!document.startViewTransition) {
modal.style.display = "block"
return
}
thumbnail.style.viewTransitionName = "modal"
const transition = document.startViewTransition(() => {
thumbnail.style.viewTransitionName = null
modal.style.viewTransitionName = "modal"
modal.style.display = "block"
})
transition.finished.finally(() => {
modal.style.viewTransitionName = null
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论