前端放大镜效果

224 阅读1分钟

Dom结构

第一个div盒子放置一个小尺寸的图片,第二个div盒子中放置大尺寸的图片

  • 当鼠标移入小图片中时,鼠标位置出现一个标识放大区域的小方块,同时bigBox由display:none变为display:block展示图片放大区域
    <div class="smallBox">
        <img src="./small.jpg" alt="smallImage">
        <!--<div class="mark"></div>-->
    </div>
    <div class="bigBox">
        <img src="./big.jpg" alt="bigImage">
    </div>

CSS

.smallBox {
    position: relative;
    width: 300px;
    height: 300px;
    overflow: hidden;
    img{
    	display: block;
        width: 100%;
    	height: 100%;
    }
    .mark {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
    width: 100px;
    height: 100px;
    background: rgba(255, 0, 0, .3);
    cursor: move;
 }
}

.bigBox {
    display: none;
    position: relative;
    width: 300px;
    height: 300px;
    overflow: hidden;
    img { // 图片尺寸溢出包含块,图片相当于一个容器,bigBox相当于放大区域对应smallBox中的mark,可以看做是bigBox在图片中移动
     position: absolute;
     top: 0;
     left: 0;
     width: 900px;
     height: 900px;
 }
}

js

let smallBox = document.querySelector('.smallBox'),
    bigBox = document.querySelector('.bigBox'),
    bigImg = bigBox.querySelector('img'),
    mark = null;
smallBox.onmouseenter = function () {
    if (!mark) {
        mark = document.createElement('div');
        mark.className = 'mark';
        this.appendChild(mark);
        bigBox.style.display = 'block';
    }
};
smallBox.onmousemove = function (ev) {
    if (!mark) return;
    let curL = ev.pageX - smallBox.offsetLeft - mark.offsetWidth / 2,
        curT = ev.pageY - smallBox.offsetTop - mark.offsetHeight / 2;
    // 边界判断
    let minL = 0,
        minT = 0,
        maxL = smallBox.offsetWidth - mark.offsetWidth,
        maxT = smallBox.offsetHeight - mark.offsetHeight;
    curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
    curT = curT < minT ? minT : (curT > maxT ? maxT : curT);

    mark.style.left = curL + 'px';                
    mark.style.top = curT + 'px';

/*
	重点:计算图片需要移动的坐标
    将bigImg看做一个盒子,bigBox在其中移动;这等价于mark在smallBox中移动,它们应该是成比例的
    big_x/(bigImg.offsetWidth-bigBox.offsetWidth) = curL/(smallImg.offsetWidth-mark.offsetWidth);
    big_y/(bigImg.offsetHeight-bigBox.offsetHeight) = curT/(smallImg.offsetHeight-mark.offsetHeight);
*/
    bigImg.style.left = curL/(smallImg.offsetWidth-mark.offsetWidth) * (bigImg.offsetWidth-bigBox.offsetWidth) + 'px';
    bigImg.style.top =  curT/(smallImg.offsetHeight-mark.offsetHeight) * (bigImg.offsetHeight-bigBox.offsetHeight) + 'px';
};
smallBox.onmouseleave = function () {
    if (mark) {
        this.removeChild(mark);//(页面中移除是DOM元素,并清除js变量,手动赋值为NULL)
        mark = null;

        bigBox.style.display = 'none';
    }
};