放大镜功能

本文介绍了如何利用JavaScript实现一个鼠标悬停时显示放大镜的功能。通过在小方块上移动鼠标,用户可以查看到不同位置的放大视图。主要涉及HTML结构、JavaScript逻辑以及可能的CSS样式设置。
摘要由CSDN通过智能技术生成

完成一个放大镜的功能
在这里插入图片描述

在这里插入图片描述

当鼠标经过小方块时,旁边会出现一个放大镜,跟随鼠标的移动可以放大各种位置

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            width: 1000px;
            height: 600px;
            background:#ccc;
            margin:100px auto;
        }
        img{
            display:block;
        }
        .show{
            width: 350px;
            height: 350px;
            position:relative;
            border:2px solid #000;
            float:left;
        }
        .mask {
            width: 200px;
            height: 200px;
            background-color:yellow;
            opacity:0;
            position:absolute;
            left: 0;
            top: 0;
        }
        .bigBox{
            width: 400px;
            height: 400px;
            border:2px solid red;
            overflow:hidden;
            float:left;
            margin-left: 20px;
            opacity: 0;
            position:relative;
        }
        .bigBox img{
            position:absolute;
            left: 0;
            top: 0;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="show">
            <div class="mask"></div>
            <img src="img/show.jpg" />
        </div>
        <div class="bigBox">
            <img src="./img/big.jpg" />
        </div>
    </div>
    <script src="./js/utils.js"></script>
    <script src="./js/index.js"></script>
    <script>
        const m1 = new Magnifier()
        m1.init()
    </script>
</body>
</html>

utils.js

/* 
    工具类函数

*/
/* 
    检测一个字符串是否是可回文字符串
    @param a 要检测的字符串
    @return 返回值是一个布尔值  
*/
function fn(a) {
    return a.split('').reverse().join('') === a ? true : false
}
/* 
    求一个范围之间的随机数
    @param a 范围下限
    @param b 范围上限
    @return 范围之间的随机数
*/
function getRandom(a, b) {
    return Math.floor(Math.random() * (b - a + 1) + a)
}

/* 
    随机颜色
    @return  随机颜色字符串
*/
function getColor() {
    return "rgb(" + getRandom(0, 255) + "," + getRandom(0, 255) + "," + getRandom(0, 255) + ")"
}

/* 
    通过选择器获取元素
    @param selector 要获取的元素的 id/class/标签名
    @param context 从哪个范围获取
    @return 获取到的元素或者元素伪数组
*/
function my$(selector, context) {
    context = context || document
    if (selector.indexOf('#') === 0) {
        return document.getElementById(selector.slice(1))
    }
    if (selector.indexOf('.') === 0) {
        return context.getElementsByClassName(selector.slice(1))
    }
    return context.getElementsByTagName(selector)
}
/* 
    获取/设置元素的样式 
    @param ele 元素
    @param attr 要获取/设置的属性
    @param value 要获取/设置的属性值
    @return 获取/设置好的属性值
*/
function css(ele, attr, value) {
    if (value) {
        ele.style[attr] = value
    }
    // 有第三个参数就是设置 没有就是获取
    return window.getComputedStyle ? window.getComputedStyle(ele)[attr] : ele.currentStyle[attr]
}

/* 
    绑定事件 兼容处理
    @param ele  要绑定事件的元素
    @param type 事件类型
    @param fn 事件处理函数
*/
function on(ele, type, fn) {
    if (ele.addEventListener) {
        if (type.indexOf('on') === 0) {
            type = type.slice(2)
        }
        ele.addEventListener(type, fn)
    } else {
        if (type.indexOf('on') !== 0) {
            type = 'on' + type
        }
        ele.attachEvent(type, fn)
    }
}

function off(){
    
}
/* 
    对 ie8 不支持  pageX pageY 做的兼容处理
    @param e event 对象
    @return 光标距离页面左边和上边的距离数据对象
*/
function page(e) {
    if (e.pageX) {
        return { x: e.pageX, y: e.pageY }
    }
    var _x = document.documentElement ? document.documentElement.scrollLeft + e.clientX : document.body.scrollLeft + e.clientX 
    var _y = document.documentElement ? document.documentElement.scrollTop + e.clientY : document.body.scrollTop + e.clientY
    return { x:_x,y:_y}
}


/* 
    运动框架函数
    @param ele 执行运动的元素 
    @param options 终点值 是一个对象
    @param duration 运动的总时间
    @param fn 运动执行完毕的回调函数

*/
function animate(ele, options, duration,fn) {
    
    clearInterval(ele.timer)
    const start = {}, range = {}
    for (var key in options) {
        start[key] = parseFloat(css(ele, key))
        range[key] = options[key] - start[key]
    }
    const startTime = +new Date()
    ele.timer = setInterval(() => {
        let nowTime = +new Date()
        let timeDifference = Math.min(nowTime - startTime,duration)
        for (let attr in options) {
            let result = start[attr] + range[attr] / duration * timeDifference
            result = attr === 'opacity' ? result : result + 'px'
            ele.style[attr] = result
        }
        if (timeDifference === duration) {
            clearInterval(ele.timer)
            fn && fn()
        }
    }, 10)
}
/* 
    淡入

*/
function fadeIn(ele,time,fn){
    css(ele,'display','block')
    css(ele,'opacity','0')
    animate(ele,{opacity:1},time,fn)
}
/* 
    淡出
*/
function fadeOut(ele,time,fn){
    css(ele,'display','block')
    css(ele,'opacity','1')
    animate(ele,{opacity:0},time,fn)

}

index.js

function Magnifier(options) {
    options = options || {}
    this.box = options.box || document.querySelector('.box')
    this.show = options.show || this.box.querySelector('.show')
    this.showInfo = {
        width: this.show.offsetWidth,
        height: this.show.offsetHeight
    }
    this.mask = options.mask || this.box.querySelector('.mask')
    this.maskInfo = {
        width: this.mask.offsetWidth,
        height: this.mask.offsetHeight
    }
    this.bigBox = options.bigBox || this.box.querySelector('.bigBox')
    this.bigBoxInfo = {}
    this.bigImg = options.bigImg || this.bigBox.querySelector('img')
    this.bigImgInfo = {
        width: this.bigImg.offsetWidth,
        height: this.bigImg.offsetHeight
    }

}
Magnifier.prototype.init = function () {
    // 1、计算比例 重置大盒子大小
    this.resetBigBox()
    // 2、限定范围拖拽
    this.enterOut()
    this.move()
    // 3、计算比例 设置大图在大盒子里面的移动距离
}
Magnifier.prototype.resetBigBox = function () {
    /* 
        mask 在 show 盒子里面 移动 
        大图 是在 bigBox 里面移动
        mask     bigBox
        ----- = --------    
        show     bigImg
        bigBoxwidth = maskwidth * bigImgWidth / showWidth
    */
    const bigBoxWidth = this.maskInfo.width * this.bigImgInfo.width / this.showInfo.width
    const bigBoxHeight = this.maskInfo.height * this.bigImgInfo.height / this.showInfo.height
    this.bigBoxInfo = {
        width:bigBoxWidth,
        height:bigBoxHeight
    }
    css(this.bigBox, 'width', bigBoxWidth + 'px')
    css(this.bigBox, 'height', bigBoxHeight + 'px')
}
Magnifier.prototype.enterOut = function () {
    // 此时 箭头函数里面的  this 指向 实例化对象
    on(this.show, 'mouseenter', () => {
        css(this.mask, 'opacity', '0.3')
        css(this.bigBox, 'opacity', '1')
    })
    on(this.show, 'mouseleave', () => {
        css(this.mask, 'opacity', '0')
        css(this.bigBox, 'opacity', '0')
    })
}
Magnifier.prototype.move = function () {
    on(this.show, 'mousemove', (e) => {
        let _left = e.pageX - this.box.offsetLeft - this.maskInfo.width / 2
        let _top = e.pageY - this.box.offsetTop-this.maskInfo.height / 2

        if(_left <= 0 ){
            _left = 0
        }else if(_left >= this.showInfo.width - this.maskInfo.width){
            _left = this.showInfo.width - this.maskInfo.width
        }
        if(_top <= 0){
            _top = 0
        }else if(_top >= this.showInfo.height - this.maskInfo.height){
            _top = this.showInfo.height - this.maskInfo.height
        }

        // 计算大图 移动的比例
        /* 
        
        mask 移动的距离             大图移动的距离 
        ---------------------- = -------------------
        mask 能够移动的最大距离     大图能够移动的最大距离
        大图移动的距离 = mask 移动的距离 * 大图能够移动的最大距离 / mask 能够移动的最大距离
        */
        const bigImgLeft = _left * (this.bigImgInfo.width - this.bigBoxInfo.width) / (this.showInfo.width - this.maskInfo.width)
        const bigImgTop = _top * (this.bigImgInfo.height - this.bigBoxInfo.height) / (this.showInfo.height - this.maskInfo.height)
        // 设置大图 的 left 和 top 值

        this.bigImg.style.left = -bigImgLeft + 'px'
        this.bigImg.style.top = -bigImgTop + 'px'
        this.mask.style.left = _left + 'px'
        this.mask.style.top = _top + 'px'

    })


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值