gpt4 book ai didi

javascript - HTMLElement.offsetTop 不适用于亚像素精度

转载 作者:行者123 更新时间:2023-12-01 02:15:52 26 4
gpt4 key购买 nike

我正在编写一个小程序,以指定的速度移动 DOM

当我以每秒 20 像素的速度移动它时,添加到 elem.style.top 的偏移量约为每帧 0.3px

问题是,当这个offset小于0.5px时,elem不会移动!

我构建了一个简化的示例来演示我的程序中的问题:

var requestFrameAnimationId;

function myMove(offset) {
var elem = document.getElementById("animate");
requestFrameAnimationId = animationLoop(frame);
function frame() {
console.log(elem.offsetTop);
if (elem.offsetTop === 350) {
cancelAnimationFrame(requestFrameAnimationId);
} else {
elem.style.top = elem.offsetTop + offset + 'px';
elem.style.left = elem.offsetLeft + offset + 'px';
}
}
}

function animationLoop(render) {
var running, lastFrame = +new Date(); // casting Date to Number
function loop(now) {`enter code here`
requestFrameAnimationId = requestAnimationFrame(loop);
running = render(now - lastFrame);
lastFrame = now;
}
loop(lastFrame);
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<!DOCTYPE html>
<html>
<body>
<p>
<button onclick="myMove(0.3)">Move at 0.3px per frame</button>
<button onclick="myMove(0.5)">Move at 0.5px per frame</button>
</p>

<div id="container">
<div id="animate"></div>
</div>
</body>
</html>

尝试单击每帧移动 0.5 像素。矩形应该是移动的。单击运行代码片段重置它。

现在尝试单击每帧移动 0.3 像素。它应该更慢地移动 DOM,但您可以看到 DOM 没有移动。

这很奇怪,因为当我最初跟踪 JavaScript 变量 topPos 中的 top 位置,并应用 ${topPos + offset}elem.style.top,它的工作速度甚至更慢!

所以我的猜测是 elem.offsetTop 对小数值进行四舍五入,因此 0.3 变为 0,0.5 变为 1。

如何才能使 DOM 以指定的速度精确移动?我无法为此使用任何库。

<小时/>

编辑:我更深入地研究了这个问题,我相信是 offsetTop 将数字四舍五入为整数。

但是,我发现CSS OM规范将offsetTop的类型更改为float,并且the Chromium team was working on applying the change on the browser more than 4 years ago, and it seems that it should be fixed by now .

为什么它不能在我的程序上运行?我怎样才能让它运行?

<小时/>

EDIT2:我从 CSSOM working draft 找到offsetTop 的类型是整数。

readonly attribute long offsetTop;

我认为他们只是将 scrollTopscrollLeft 的类型更改为 double 字。

attribute unrestricted double scrollTop;
attribute unrestricted double scrollLeft;

最佳答案

HTMLElement.offset[Left | Top]返回long类型值(即整数)。

使用Element.getBoundingClientRect如果你想要浮点值。

var requestFrameAnimationId;

function myMove(offset) {
var elem = document.getElementById("animate");
requestFrameAnimationId = animationLoop(frame);

function frame() {
// build up our own high precision offsetTop
var parentRect = elem.offsetParent && elem.offsetParent.getBoundingClientRect() || {top: 0, left:0};
var elemRect = elem.getBoundingClientRect();
var rect = {
top: elemRect.top - parentRect.top,
left: elemRect.left - parentRect.left
};
if (rect.top >= 350) {
cancelAnimationFrame(requestFrameAnimationId);
} else {
// so we can substract it here
elem.style.top = (rect.top + offset) + 'px';
elem.style.left = (rect.left + offset) + 'px';
}
}
}

function animationLoop(render) {
var running, lastFrame = +new Date(); // casting Date to Number
function loop(now) {
requestFrameAnimationId = requestAnimationFrame(loop);
running = render(now - lastFrame);
lastFrame = now;
}
loop(lastFrame);
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}

#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<p>
<button onclick="myMove(0.3)">Move at 0.3px per frame</button>
<button onclick="myMove(0.5)">Move at 0.5px per frame</button>
</p>

<div id="container">
<div id="animate"></div>
</div>

或者简单地将您的值添加到变量中:

var requestFrameAnimationId;

function myMove(offset) {
var elem = document.getElementById("animate");
requestFrameAnimationId = animationLoop(frame);
var pos = 0;

function frame() {
pos += offset;
if (pos >= 350) {
cancelAnimationFrame(requestFrameAnimationId);
} else {
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}

function animationLoop(render) {
var running, lastFrame = +new Date(); // casting Date to Number
function loop(now) {
requestFrameAnimationId = requestAnimationFrame(loop);
running = render(now - lastFrame);
lastFrame = now;
}
loop(lastFrame);
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}

#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<p>
<button onclick="myMove(0.3)">Move at 0.3px per frame</button>
<button onclick="myMove(0.5)">Move at 0.5px per frame</button>
</p>

<div id="container">
<div id="animate"></div>
</div>

关于javascript - HTMLElement.offsetTop 不适用于亚像素精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49505016/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com