实现放大镜效果

1、概念明确

首先知道几个页面位置信息的apicss

image.png

补充:html

image.png

2、分割版

这一版主要是在小图右侧放一个大图,经过大图移动位置以及利用层级关系,显示大图的部分区域,展示放大的效果. 计算公式: 大图的left = -(左侧图片内滑块left / (左侧图片宽度 - 滑块宽度)) * (右侧大图宽度 - 右侧大图展示区域宽度)api

HTML代码

页面结构很简单,总的来讲就是须要两张图片,一张小图片和一张如出一辙的大图片,主要复杂的是js中的计算部分:浏览器

<div id="demo">
    <!-- 左边的小图 -->
    <div id="small-box">
        <div id="mark"></div>
        <!-- 放大镜 -->
        <div id="float-box"></div>
        <img src="small.jpg"/>
    </div>
    <!-- 显示的大图 -->
    <div id="big-box">
        <img src="big.jpg"/>
    </div>
</div>
复制代码

CSS代码

<style>
    * {
        margin: 0;
        padding: 0
    }
    #demo {
        display: block;
        width: 400px;
        height: 255px;
        margin: 50px;
        position: relative;
        border: 1px solid #ccc;
    }
    #small-box {
        position: relative;
        z-index: 1;
    }
    #float-box {
        display: none;
        width: 160px;
        height: 120px;
        position: absolute;
        background: #ffffcc;
        border: 1px solid #ccc;
        filter: alpha(opacity=50);
        opacity: 0.5;
    }
    #mark {
        position: absolute;
        display: block;
        width: 400px;
        height: 255px;
        background-color: #fff;
        filter: alpha(opacity=0);
        opacity: 0;
        z-index: 10;
    }
    #big-box {
        display: none;
        position: absolute;
        top: 0;
        left: 460px;
        width: 400px;
        height: 300px;
        overflow: hidden;
        border: 1px solid #ccc;
        z-index: 1;;
    }
    #big-box img {
        position: absolute;
        z-index: 5
    }
</style>
复制代码

此时咱们页面上就只有一张小图片markdown

JavaScript代码

<script>
    //页面加载完毕后执行
    window.onload = function () {
        var objDemo = document.getElementById("demo");
        var objSmallBox = document.getElementById("small-box");
        var objMark = document.getElementById("mark");
        var objFloatBox = document.getElementById("float-box");
        var objBigBox = document.getElementById("big-box");
        var objBigBoxImage = objBigBox.getElementsByTagName("img")[0];
        //鼠标一如事件
        objMark.onmouseover = function () {
            objFloatBox.style.display = "block"
            objBigBox.style.display = "block"
        }
        //鼠标移出事件
        objMark.onmouseout = function () {
            objFloatBox.style.display = "none"
            objBigBox.style.display = "none"
        }
        //鼠标移动事件
        objMark.onmousemove = function (ev) {
            var _event = ev || window.event;  //兼容多个浏览器的event参数模式
            var left = _event.clientX - objDemo.offsetLeft - objSmallBox.offsetLeft - objFloatBox.offsetWidth / 2;
            var top = _event.clientY - objDemo.offsetTop - objSmallBox.offsetTop - objFloatBox.offsetHeight / 2;
            if (left < 0) {
                left = 0;
            } else if (left > (objMark.offsetWidth - objFloatBox.offsetWidth)) {
                left = objMark.offsetWidth - objFloatBox.offsetWidth;
            }
            if (top < 0) {
                top = 0;
            } else if (top > (objMark.offsetHeight - objFloatBox.offsetHeight)) {
                top = objMark.offsetHeight - objFloatBox.offsetHeight;
            }
            objFloatBox.style.left = left + "px"; 
            objFloatBox.style.top = top + "px";
            var percentX = left / (objMark.offsetWidth - objFloatBox.offsetWidth);
            var percentY = top / (objMark.offsetHeight - objFloatBox.offsetHeight);
            objBigBoxImage.style.left = -percentX * (objBigBoxImage.offsetWidth - objBigBox.offsetWidth) + "px";
            objBigBoxImage.style.top = -percentY * (objBigBoxImage.offsetHeight - objBigBox.offsetHeight) + "px";
                    }
    }
</script>
复制代码

3、糅合版

image.png

所谓优雅版就是把鼠标变成放大镜,这样就会有比较真实的用放大镜看东西的效果函数

大体实现思路以下:url

1)原图部分添加mouseover监听函数,在鼠标移入原图后,获取鼠标距离原图的top和left的位置spa

2)在鼠标放大镜区域,设置区域背景为放大后的图片,设置为backgroundcode

3)反向计算放大后图片应该移动的距离,设置background-positionorm

HTML代码

html部分代码很是简单,就是一个原图背景图,还有就是两个不显示的img元素,这两个不显示的元素,主要是用来获取图片的宽高

<div id="background" className={styles.originImage} style={{backgroundImage: `url(${url})`}}>
      <img src={url} />
      <img id="bigger" src={url} />
      <div id="manifier" className={styles.biggerImage} style={{backgroundImage: `url(${url})`}} />
</div>
复制代码

JavaScript代码

js代码主要分为两部分

1)监听鼠标在原图上的移动

const listenBackMousemove = (e: globalThis.MouseEvent) => {
    if (!manifier || !background) return
    let left = e.offsetX - manifier.offsetWidth / 2,
      top = e.offsetY - manifier.offsetHeight / 2
    if (left < 0) left = 0
    else if (left > background.offsetWidth - manifier.offsetWidth)
      left = background.offsetWidth - manifier.offsetWidth
    if (top < 0) top = 0
    else if (top > background.offsetHeight - manifier.offsetHeight)
      top = background.offsetHeight - manifier.offsetHeight
    manifier.style.visibility = 'visible'
    manifier.style.left = left + 'px'
    manifier.style.top = top + 'px'
    imgMove(left, top)
}
复制代码

2)根据鼠标在原图上移动的距离,反向计算放大后的图片应该移动的距离

const imgMove = (left: number, top: number) => {
    if (!bigger || !background || !manifier) return
    const imgWidth = bigger.offsetWidth
    const imgHeight = bigger.offsetHeight
    const backHeight = background.offsetHeight
    const backWidth = background.offsetWidth
    const manHeight = manifier.offsetHeight
    const manWidth = manifier.offsetWidth
    const rateX = left / (backWidth - manWidth)
    const rateY = top / (backHeight - manHeight)
    let imgLeft = -(rateX * (imgWidth - manWidth)),
      imgTop = -(rateY * (imgHeight - manHeight))
    if (imgLeft > 0) imgLeft = 0
    else if (imgLeft < -(imgWidth - manWidth)) imgLeft = -(imgWidth - manWidth)
    if (imgTop > 0) imgTop = 0
    else if (imgTop < -(imgHeight - manHeight)) imgTop = -(imgHeight - manHeight)
    manifier.style.backgroundPosition = `${imgLeft}px ${imgTop}px`
}
复制代码

CSS部分代码

.originImage {
  background-position: center center;
  background-size: contain;
  background-repeat: no-repeat;
  position: relative;
  & > img:nth-child(1) {
    width: 100%;
    height: auto;
    visibility: hidden;
  }

  & > img:nth-child(2) {
    width: auto;
    height: auto;
    position: absolute;
    left: -9999px;
    top: 0;
  }

  .biggerImage {
    position: absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #ededed;
    border-radius: 10px;
    cursor: none;
    pointer-events: none;
  }
}
复制代码

css部分有一个点须要注意,须要将鼠标放大镜的鼠标属性设置为none,即穿透效果,这样在背景原图上的移动就不会受影响。不然可能会走进鼠标放大镜区域的mouseover事件

相关文章
相关标签/搜索