【发布时间】:2022-01-10 23:08:55
【问题描述】:
我正在我的网站上开发一个灯箱,并注意到它在我拥有的所有浏览器(Brave、Chrome 和 Safari)的 iOS 上都会闪烁。但是,它不会闪烁总是,只是当我将图像向左移动时,它才会离开视口。
-webkit-backface-visibility: hidden;
-webkit-transform-style: preserve-3d;
-webkit-transform: translate3d(0, 0, 0);
-webkit-perspective: 1000;
我已经尝试了所有这些,但都没有奏效。这是意料之中的,因为这些问题已经很老了,我认为这些问题早已不复存在。然而,情况似乎并非如此。
在测试了 CSS 属性和 DOM 更改的各种组合之后,我将我的代码归结为一个可重现的最小示例:
let box = document.querySelector(".lightbox");
let img = box.querySelector("img");
let rx = 0;
let ry = 0;
let x = 0;
let y = 0;
let render = () => {
img.style.transform = `translate(${rx}px, ${ry}px) scale(2)`;
};
let onDown = (e) => {
x = e.clientX;
y = e.clientY;
box.addEventListener("pointermove", onMove);
};
let onMove = (e) => {
let lastX = x;
let lastY = y;
x = e.clientX;
y = e.clientY;
if (lastX && lastY) {
rx += x - lastX;
ry += y - lastY;
}
render();
};
let onUp = (e) => {
box.removeEventListener("pointermove", onMove);
};
box.addEventListener("pointerdown", onDown);
box.addEventListener("pointerup", onUp);
box.addEventListener("pointerleave", onUp);
box.addEventListener("pointercancel", onUp);
render();
setInterval(() => {
box.classList.remove("test");
setTimeout(() => {
box.classList.add("test");
}, 100);
}, 1e3);
img {
max-width: 100%;
height: auto;
}
.lightbox {
width: 100%;
height: 100%;
touch-action: none;
}
.lightbox img {
transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
.lightbox.test img {
transition: none;
}
<div class="lightbox">
<img width="1280" height="720" style="background-image: linear-gradient(-45deg, #cc8888, #88cc88)" />
</div>
如果你想知道为什么我有一个 setInterval 来添加和删除一个类,那是因为它会触发错误。例如,如果没有间隔,并且类只是在 pointerup 事件之后添加/删除,则它不会闪烁。 transform 中的 scale(2) 也是问题的一部分。如果我删除它,闪烁就会停止。
我已经创建了一个demo site on Netlify 和一个demo video。
编辑:我已设法进一步简化:
let box = document.querySelector("div");
let rx = 0;
let ry = 0;
let x = 0;
let y = 0;
let render = () => {
box.style.transform = `translate(${rx}px, ${ry}px) scale(2)`;
};
let onDown = (e) => {
x = e.clientX;
y = e.clientY;
box.addEventListener("pointermove", onMove);
};
let onMove = (e) => {
let lastX = x;
let lastY = y;
x = e.clientX;
y = e.clientY;
if (lastX && lastY) {
rx += x - lastX;
ry += y - lastY;
}
render();
};
let onUp = (e) => {
box.removeEventListener("pointermove", onMove);
};
box.addEventListener("pointerdown", onDown);
box.addEventListener("pointerup", onUp);
box.addEventListener("pointerleave", onUp);
box.addEventListener("pointercancel", onUp);
render();
div {
width: 200px;
height: 200px;
touch-action: none;
transition: transform 0.1s ease;
background-image: linear-gradient(-45deg, #cc8888, #88cc88);
}
<div></div>
在这个 sn-p 中,没有 setInterval 和类切换。相反,transition 始终处于活动状态。现在,只要您移动图像并且它位于屏幕的左侧,该元素就会被隐藏。看来只有当我删除转换的 scale() 部分时,问题才会消失,即从这里更改它:
box.style.transform = `translate(${rx}px, ${ry}px) scale(2)`;
...到这个:
box.style.transform = `translate(${rx}px, ${ry}px)`;
但是,在我的原始应用程序中,这个比例是动态变化的,所以我需要它。
【问题讨论】:
标签: javascript css webkit css-transitions css-transforms