js实现放大镜

这篇博客详细介绍了如何使用HTML、CSS和JavaScript实现一个图片浏览时的放大镜效果。通过监听鼠标事件,调整焦点框和放大图片的位置,实现平滑的缩放查看。同时,还提供了切换图片的功能,并附带了完整的代码示例。
摘要由CSDN通过智能技术生成
  • 元素获取
  • 鼠标事件
  • 比例设置
  • 边界检测

一、HTML部分

<div class="container">
        <!-- 左侧图片部分 -->
        <div class="img">
            <img src="./images/1.jpg" alt="">
            <!-- 焦点框 -->
            <div class="focus"></div>
        </div>
        <!-- 左侧小图列表 -->
        <div class="list">
            <div class="button-prev">&lt;</div>
            <div class="button-next">></div>
            <span class="active">
                <img src="./images/1.small.jpg" alt="">
            </span>
            <span>
                <img src="./images/2.small.jpg" alt="">
            </span>
            <span class>
                <img src="./images/1.small.jpg" alt="">
            </span>
            <span>
                <img src="./images/2.small.jpg" alt="">
            </span>
        </div>
        <!-- 右侧放大图片部分 -->
        <div class="big-img">
            <img src="./images/1.big.jpg" alt="">
        </div>
    </div>

二、CSS部分

<style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            width: 350px;
            margin-left: 100px;
            position: relative;
        }

        .img {
            width: 350px;
            height: 350px;
        }

        .img img {
            width: 100%;
            height: 100%;
        }

        .focus {
            border: 1px solid #aaa;
            background: no-repeat #fede4f;
            opacity: .5;
            cursor: move;
            position: absolute;
            left: 0;
            top: 0;
            z-index: 9;
            display: none;
        }

        .big-img {
            width: 540px;
            height: 540px;
            position: absolute;
            left: 350px;
            top: 0;
            /* 关键 */
            overflow: hidden;
            display: none;
        }

        .big-img img {
            width: 800px;
            height: 800px;
            position: absolute;
        }

        .list span {
            display: inline-block;
            border: 2px solid #fff;
            margin-left: 5px;
        }

        .list span.active {
            border-color: #f10;
        }

        .list span:hover {
            border-color: #f10;
        }

        .list {
            width: 100%;
            position: relative;
            padding-left: 40px;
        }

        .button-next,
        .button-prev {
            width: 30px;
            height: 30px;
            position: absolute;
            left: 0;
            background-color: skyblue;
            top: 50%;
            margin-top: -15px;
            text-align: center;
            line-height: 30px;
        }

        .button-next:hover,
        .button-prev:hover {
            opacity: .7;
            cursor: pointer;
        }

        .button-next {
            left: 100%;
            margin-left: -70px;
        }
    </style>

三、JS部分

  • offset:
  1. 从当前元素开始逐层向父级进行查找, 如果有带有position属性的元素,那么就以这个元素为参照,如果查找到了body依旧没有找到参照物,那么就以body为参照物。
  2. 只能取值,不能赋值

  3. 以距离鼠标最近的元素为参照物定位的 鼠标位置

  • client:
  1. 以浏览器可视区边缘为参照物定位的 鼠标位置
<script>
        // 鼠标移入事件:显示(焦点,大图)
        // 鼠标移出事件:隐藏(焦点,大图)
        // 列表鼠标移入:切换图片
        // --解决方法:在布局时将focus框放入img盒子

        // 初始化布局时,放大镜(正常图片)和焦点框的比例非常重要,目前定义为:1:0.6
        class Magnifier {
            constructor() {
                this.img = document.querySelector(".img")
                this.focus = document.querySelector(".focus")
                this.big_img = document.querySelector(".big-img")
                this.big_bg = document.querySelector(".big-img img")
                // 为了获取元素的偏移距离,计算正确的focus位置
                this.scale = 0.6
                this.container = document.querySelector(".container")

                // 切换图片的元素
                this.btns = document.querySelectorAll(".list span")
                // 切换图片按钮
                this.next_button = document.querySelector(".button-next")
                this.prev_button = document.querySelector(".button-prev")
                // 存储自动播放定时器返回值的变量
                this.autopaly_interval = null
                // 切换小图行为核心数据
                this.index = 0
                // 图片数据
                this.img_list = [
                    {
                        small: "./images/1.jpg",
                        big: "./images/1.big.jpg"
                    },
                    {
                        small: "./images/2.jpg",
                        big: "./images/2.big.jpg"
                    },
                    {
                        small: "./images/1.jpg",
                        big: "./images/1.big.jpg"
                    },
                    {
                        small: "./images/2.jpg",
                        big: "./images/2.big.jpg"
                    }
                ]
                this.init()

                this.c_off = {
                    left: this.container.offsetLeft,
                    top: this.container.offsetTop
                }
                // offset家族不能测量display为none的元素,改用getComputedStyle
                this.f_style = getComputedStyle(this.focus)
                this.i_style = getComputedStyle(this.img)

                // focus边界数据对象
                this.boundary = {
                    x: {
                        min: 0,
                        max: parseInt(this.i_style.width) - parseInt(this.f_style.width)
                    },
                    y: {
                        min: 0,
                        max: parseInt(this.i_style.height) - parseInt(this.f_style.height)
                    }
                }
                this.bindEvent()
            }

            init() {
                // 为了让图片跟随更精准
                this.focus.style.width = 350 * this.scale + "px"
                this.focus.style.height = 350 * this.scale + "px"

                this.big_img.style.width = 800 * this.scale + "px"
                this.big_img.style.height = 800 * this.scale + "px"
            }
            bindEvent() {
                this.img.addEventListener("mouseover", () => {
                    this.show()
                })
                this.img.addEventListener("mouseout", () => {
                    this.hide()
                })
                this.img.addEventListener("mousemove", (e) => {
                    // 浏览器可视区域左上角获取的x,y,需要进行处理
                    // 如果使用offset会出现鼠标获取位置的参照物和focus元素定位的参照物不一致
                    this.move(e.clientX, e.clientY)
                })
                for (let i = 0; i < this.btns.length; i++) {
                    this.btns[i].addEventListener("mouseenter", () => {
                        this.index = i
                        this.change()
                    })
                }
                this.next_button.addEventListener("click", () => {
                    this.add()
                })
                this.prev_button.addEventListener("click", () => {
                    this.reduce()
                })
            }
            show() {
                this.focus.style.display = "block"
                this.big_img.style.display = "block"
            }
            hide() {
                this.focus.style.display = "none"
                this.big_img.style.display = "none"
            }
            move(x, y) {
                // 减parseInt(this.f_style.width)/2是为了让鼠标的位置位于focus框中间
                x = x - this.c_off.left - parseInt(this.f_style.width) / 2
                y = y - this.c_off.top - parseInt(this.f_style.height) / 2
                // 边界检测
                x = x <= this.boundary.x.min ? this.boundary.x.min : x
                x = x >= this.boundary.x.max ? this.boundary.x.max : x
                y = y <= this.boundary.y.min ? this.boundary.y.min : y
                y = y >= this.boundary.y.max ? this.boundary.y.max : y

                this.focus.style.left = x + "px"
                this.focus.style.top = y + "px"

                this.big_bg.style.left = -x * (800 / 350) + "px"
                this.big_bg.style.top = -y * (800 / 350) + "px"
            }
            change() {
                this.btns.forEach(ele => ele.classList.remove("active"))
                this.btns[this.index].classList.add("active")
                this.img.children[0].src = this.img_list[this.index].small
                this.big_bg.src = this.img_list[this.index].big
            }
            add() {
                // 获取正确下标
                if (this.index === this.btns.length - 1) {
                    this.index = 0
                } else {
                    this.index++
                }
                this.change()
            }
            reduce() {
                if (this.index <= 0) {
                    this.index = this.btns.length - 1
                } else {
                    this.index--
                }
                this.change()
            }
            autoPlay() {
                this.autopaly_interval = setInterval(() => {
                    this.add()
                }, 5000)
            }
        }
        var m = new Magnifier
        m.autoPlay()
    </script>

放大镜所用图片:图片资源(免费)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值