提问者:小点点

通过javascript重新定位的元素之间的空白


我正在用JavaScript创建一个图像拼图。 我在2行中创建了14个div元素,然后我给它们添加了背景图像,设置了它们的位置和宽度等。。。 运转良好。 但是当我重新定位它们(洗牌)时,不需要的空白出现了。 不总是,不是每个图像,也不是同一个地方。 我同时只改变两个元素。

下面是我的更改函数:


let original_pos = [];

// I choose two element randomly, and pushing the first element positions into the original_pos array
// and I pass the second element to the shuffle_elem() function
function shuffle() {
    let random_elem = document.querySelectorAll(".bg-elem");
    for(let i = 0; i <= 50; i++) {
    let random_num = Math.floor(Math.random() * random_elem.length);
    let random_num2 = Math.floor(Math.random() * random_elem.length);
    original_pos.push(random_elem[random_num].offsetTop);
    original_pos.push(random_elem[random_num].offsetLeft);
    cserel_elem(random_elem[random_num],random_elem[random_num2]);
}

// Here are the positions change
function shuffle_elem(elem1, elem2) {
    elem1.style.left = elem2.offsetLeft+'px';
    elem1.style.top = elem2.offsetTop+'px';
    elem2.style.top = original_pos[0]+'px';
    elem2.style.left  = original_pos[1]+'px';
    original_pos = [];
}

一切工作都很好,所以我可以更改这两个元素,但是会有一点空白。 在这张图中,你可以看到两个紧挨着的元素,但有时根本没有空白,或者只有一个元素有,或者几乎每个元素都有。。。 完全随机。

只有1个像素,但它在那里,非常令人沮丧。 请帮我找出这一个像素藏在哪里。 请不要jQuery

一些附加信息(CSS):

// the main holder div where my elements are
.PlayGround {
    position: relative;
    overflow: hidden;
}
// one element
.bg-elem {
    position: absolute;
    margin: 0;
    padding: 0;
}

共1个答案

匿名用户

与您的链接提供,我能够重现问题,检查您的代码,并找到一个或两个修复。

是的,您可以看到由javascript定位的原始元素,然后我等待1.5秒,然后将它们洗牌。 这里!
-Bálint Gácsfalvy
注释引用,用于文档。

问题相当简单:
您的图像可能大小相同,但它们没有四舍五入到全像素,如代码所示:

// ratio is already already not an integers
let new_width = imgwidth * ratio;
let new_height = imgheight * ratio;
// and then some lines later you do divide by 7 and 2.
element[i].style.width = new_width/7+'px';
element[i].style.height = new_height/2+'px';

除此之外,您还将lefttop设置为不是整数像素。
所有这些都会导致这些奇怪的背景线在图像之间闪烁。 因为浏览器的呈现引擎只能显示由整数像素位置和大小定义的“框”的图像,所以浏览器通过舍入到最接近的像素来拟合图像。
如果舍入错误,可能会发生相邻的图像正好相隔一个像素的情况。 (它们也可以重叠一个像素,但通常会被忽略。)

现在您知道为什么了,让我们来解决这个问题:
有很多方法可以解决这个问题,最好是在设置大小和偏移量(lefttop)时自己将舍入到全像素,而不是依赖于渲染引擎的舍入。 但这需要花费更多的时间,我相信如果你想这样做的话,你会自己想出来的。

我选择在这里向您展示的快速而肮脏的方法是,在您使用new_widtsnew_height值之前,将它们除以整数的个数。 这超级容易,只要这样做:

let new_width = Math.floor(imgwidth * ratio / 7) * 7;
let new_height = Math.floor(imgheight * ratio / 2) * 2;

取而代之的是:

let new_width = imgwidth * ratio;
let new_height = imgheight * ratio;

这个修复的缺点是:你最多会在水平方向和垂直方向上松掉6个像素。 (我知道,糟透了。)

看看这里的固定代码是如何工作的!

如果你有问题,请在评论中提问。 如果这对您有帮助,并且您使用此答案来解决您的问题,那么将此答案标记为已接受将是很好的。 这不仅对我有帮助,对其他有同样问题的人也有帮助,并且在搜索时遇到这个问题。