计算子div最高位置 - 为什么需要减去父offsetHeight?

时间:2016-02-19 20:36:47

标签: javascript css

我用纯js创建了一个放大镜。我发现需要将div的鼠标位置相对于其父项进行转换时,在计算叠加放大器div的顶部时,offsetTop的工作方式与offsetLeft不同。调整 顶部后,我需要减去整个容器div的offsetHeight。

相关代码中的行是:

magnifier.style.top = yPosition - container.offsetHeight + "px";

为什么我需要减去container.offsetHeight

我知道我已经阅读过有关此事的内容,但无法找到。

免责声明此代码正常运行。我问,所以我(及其后续人员)可以理解盒子模型是如何工作的。

我知道有更多跨浏览器可靠的jQuery替代品。我喜欢自己编写代码,以便我可以了解它是如何工作的。如果您看到与现代浏览器不兼容的内容,请随时发表评论。

最后,对于使用此功能的任何人,我从此示例中删除了代码以调整转换。例如,如果包装器具有transform: translate(-50%, 0);以使包装器水平居中,则需要将结果的转换量(转换为包装器的左侧位置)添加回计算中。

我创建了一个jsfiddle here。如果有人感兴趣的话,我在方法中留下了更多关于方法论的评论。

<!DOCTYPE html>
<html>

<head>
<script type="text/javascript" src="../css/ms.js"></script>

<style type="text/css">
/********************/
body {
    background-color: #FFF;
    margin-left: 30px;
    margin-top: 10px;
}
.wrapper {
    position: absolute;
    left: 100px;
}

#container {
    width: 527px;
    height: 450px;
    border: 5px black solid;
    overflow: hidden;
    background-color: #F2F2F2;
    cursor: pointer;
}

#image {
    width: 527px;
    height: 450px;
}

#magnifier {
    width: 250px;
    height: 250px;
    overflow:hidden;   
    position:relative;
    z-index: 1000;
    border: solid 1px;
}

#magnifier img {
    position: absolute;    
}

</style>
</head>
<body>
<div class="wrapper" id="wrapper">
    <div id="container">
    <img id="image" src="../docs/grade-2/jpg/g2-bb-saints-francis.jpg">
    <div id="magnifier" class="magnifier">
        <img id="imagecopy">        
    </div>
        <br>
    </div>
    <input type="button" value="Zoom" onClick="initmagnifier('magnifier', 'image', 'imagecopy');"><br>
</div>


<script>

function initmagnifier(magnifier, image, imagecopy){
    var magnifier = document.getElementById("magnifier");
    var container = document.getElementById("container");
    var wrapper = document.getElementById("wrapper");
    var img = document.getElementById(image);
    var imgcopy = document.getElementById(imagecopy);
    var zoom = 2;
    container.addEventListener("mousemove", 
    function(e){
        movemagnifier(e, img, imgcopy, magnifier, container, wrapper, zoom)
    }, false);
    var src = img.src;
    imgcopy.src = src;
    var src2 = imgcopy.src;

    imgcopy.height = img.height * zoom;
    imgcopy.width = img.width * zoom ;
}

 function movemagnifier(e, img, imgcopy, magnifier, container, wrapper, zoom) {
    // to get the left & top of the magnifier    
    // position needs to be adjusted for WRAPPER & CONTAINER top and left    
    // gets the top and left of the container
    var containerPosition = getPosition(e.currentTarget);

    // adjust out the CONTAINER's top / left
    // Then takes 1/2 the hight of the MAGNIFIER and subtracts it from the MOUSE position to center MAGNIFIER around the MOUSE cursor
    var xPosition = e.clientX - containerPosition.x - (magnifier.clientWidth / 2);
    var yPosition = e.clientY - containerPosition.y - (magnifier.clientHeight / 2);

    magnifier.style.left = xPosition + "px";
    magnifier.style.top = yPosition - container.offsetHeight + "px";

    // Adjust for zoom
    // adjust the MAGNIFIER's top/left at an equal pace to the zoom amount
    var yTravel = (e.clientY - containerPosition.y ) * (zoom - 1);
    var yimgPosition = -(yPosition - container.clientTop + yTravel);
    imgcopy.style.top = yimgPosition  + "px";

    var xTravel = (e.clientX - containerPosition.x) * (zoom - 1);   // * 1.5
    var ximgPosition = -(xPosition + xTravel);
    imgcopy.style.left = ximgPosition + "px";

console.log('****');
console.log(e.clientY); // MOUSE POSTION
console.log(containerPosition.y);
console.log(wrapper.offsetTop);
console.log(wrapper.clientHeight);

console.log(container.offsetTop);
console.log(container.clientHeight);
console.log(yPosition);
console.log(container.offsetHeight);
console.log(magnifier.style.top);
}

function getPosition(element) {
    var xPosition = 0;
    var yPosition = 0;
    // element is the CONTAINER
    // This calculates the postion of the element (CONTAINER) TOP & LEFT relative to ALL parents
    while (element) {
    // if transform: translate in place for x and y,
    // add it back as it skews the offsetLeft offsetTop values by the translate amount
        xPosition += ((element.offsetLeft) - element.scrollLeft);
        yPosition += ((element.offsetTop) - element.scrollTop);
        element = element.offsetParent;
    }
    return { x: xPosition, y: yPosition };
}
</script>
</body>
</html>

1 个答案:

答案 0 :(得分:1)

我花了很长时间才承认,但我找到了原因。在您的小提琴中,您将#magnifier - 元素置于相对位置,这意味着您必须将其从“自然”位置移动,该位置位于容器内的图像下方。

因此,每次移动都需要对此进行补偿,将#magnifier拉到容器的顶部/左侧位置,左侧位置已匹配,但{{1}的“自然”顶部位置}}是容器的完整高度,当您从#magnifier的顶部/左侧位置计算时,需要减去#container高度。

一个简单的解决方法是将#container添加到position: relative并将#container更改为position: relative。{/ p>

这将为#magnifier提供position: absolute的预期坐标系,因为绝对定位元素是其相对父元素的左上角(第一个定位的父元素,在本例中为{ {1}})。

a working example,无需减去#magnifier

虽然我很喜欢,但您可能需要查看Element.getBoundingClientRect功能,因为您可以获得确定一次通话中所需位置所需的所有信息。