原生JavaScript -- 放大镜效果

<!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;
        }
        .small{
            width: 400px;
            height: 400px;
            position: relative;
            margin-left: 200px;
            margin-top: 100px;
            border: 4px solid #ddd;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
        }
        .small img{
            width: 100%;
            height: 100%;
        }
        .small .wrap{
            width: 100%;
            height: 100%;
            position: relative;
            z-index: 999;
        }
        .small .grayBox{
            display: none;
            width: 200px;
            height: 200px;
            background-size: 400px 400px;
            background-position: 0 0 ;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            position: absolute;
            left: 0;
            top: 0;
        }
        .big{
            width: 400px;
            height: 400px;
            position: absolute;
            left: 700px;
            top: 100px;
            border: 1px solid red;
            display: none;
            overflow: hidden;
        }
        .big img{
            position: absolute;
        }
    </style>
</head>
<body>
    <div class="small">
        <img src="./img/timg.jpg" alt="">
        <span class="grayBox"></span>
    </div>
    <div class="big">
        <img src="./img/timg.jpg" alt="">
    </div>
</body>
<script>
    // OOP : Object Oriented Programming 面向对象编程
    function Magnifier( options ){
        this.init( options );
    }
    Magnifier.prototype = {
        constructor : Magnifier , 
        //初始化功能
        init : function( options ){
            //初始化元素
            /*
            small_box_ele : 小盒子
            cutting_box_ele : 显示一部分的盒子
            big_box_ele : 大盒子
            big_img_ele : 图片盒子
            */
            for(var attr in options ){
                this[attr+"_ele"] = this.$(options[attr]);
            }
            
            // 为了节省性能 , 所以只获取一次offsetLeft
            this.small_box_offset = {
                left : this.small_box_ele.offsetLeft,
                top  : this.small_box_ele.offsetTop,
                // 添加上宽高的获取
                // offsetWidth : 取值额时候是带有padding ,带有border的宽度
                width : parseInt(getComputedStyle(this.small_box_ele).width),
                height: parseInt(getComputedStyle(this.small_box_ele).height),
            }
            // 因为初始的状态是display : none 所以offset的测量会又0的结果
            this.cutting_box_offset = {
                width : parseInt( getComputedStyle( this.cutting_box_ele).width),
                height :parseInt( getComputedStyle( this.cutting_box_ele).height),
            }
            // big_box_ele 的宽高
            this.big_box_offset = {
                width : parseInt( getComputedStyle( this.big_box_ele).width),
                height :parseInt( getComputedStyle( this.big_box_ele).height),
            }
            // 是否移入当前放大镜
            this.magnifier_start = false;
            // console.log(this)
            this.bindEvent();
            //图片缩放功能
            this.scaleBigImg();
        },
        // 元素选择功能
        $ : function( selector ){
                return document.querySelector( selector );
        },
        // 事件绑定功能
        bindEvent : function(){
            this.small_box_ele.addEventListener( "mouseover" , function(){
                this.magnifier_start = true ;
                // 元素显示
                this.eleToggle("show");
            }.bind(this));
            this.small_box_ele.addEventListener( "mouseout" , function(){
                this.magnifier_start = false ;
                // 元素隐藏
                this.eleToggle("hide");
            }.bind(this));
            this.small_box_ele.addEventListener( "mousemove" , function( evt ){
                var e = evt || event ; 
                var x = e.clientX ;
                var y = e.clientY ;
                // 为了在缩放的时候可以得到元素的位置,那么在这里需要把当前元素的定位放在实力之中
                this.res = this.factoryPosition( x , y );
                this.eleMove( this.res );
            }.bind(this));
            // 滚轮事件
            this.small_box_ele.addEventListener( "mousewheel" , function( evt ){
                if(!this.magnifier_start){
                    return false;
                }
                var e = evt || event ; 
                // 判定向上还是向下
                this.changeCutBoxScale ( e.wheleDelta > 0 ? "narrow" : "large" );
            }.bind(this));
        },
        // 元素显示隐藏功能
        eleToggle : function( type ){
            this.cutting_box_ele.style.display = type === "show" ? "block" : "none";
            this.big_box_ele.style.display = type === "show" ? "block" : "none";
        },
        // 小图移动,大图跟随
        eleMove : function( position_obj ){
            this.cutting_box_ele.style.left = position_obj.x + "px";
            this.cutting_box_ele.style.top = position_obj.y + "px";
            // 元素运动
            this.big_img_ele.style.left = -position_obj.xp * this.big_img_boundary.left_max + "px";
            this.big_img_ele.style.top = -position_obj.yp * this.big_img_boundary.top_max + "px";
        },
        // 处理 x 和 y
        factoryPosition : function( x , y ){
            var _left = x - this.small_box_offset.left - this.cutting_box_offset.width / 2 ;
            var _top = y - this.small_box_offset.top - this.cutting_box_offset.height / 2 ;
            //做边界检测
            _left = _left <= 0 ? 0 : _left;
            _top = _top <= 0 ? 0 : _top;
            // 最大值
            var _left_max = this.small_box_offset.width - this.cutting_box_offset.width;
            var _top_max = this.small_box_offset.height - this.cutting_box_offset.height;

            _left = _left >= _left_max ? _left_max :_left;
            _top = _top >= _top_max ? _top_max :_top;

            //高频率使用的函数
            return{
                x : _left,
                y : _top,
                xp : _left / _left_max,
                yp : _top / _top_max
            }
        },
        scaleBigImg : function(){
            // 放大的比例
            var width_p  = this.big_box_offset.width / this.cutting_box_offset.width;
            var height_p = this.big_box_offset.height / this.cutting_box_offset.height;
            // 获得了big放大之后的宽高
            this.big_img_offset = {
                width : width_p * this.small_box_offset.width,
                height : height_p * this.small_box_offset.height,
            }
            //计算出大图运动的边界
            this.big_img_boundary = {
                left_max : this.big_img_offset.width  - this.big_box_offset.width,
                top_max  : this.big_img_offset.height - this.big_box_offset.height
            }
            //  给图片设置等比例宽高
            this.big_img_ele.style.width  = this.big_img_offset.width + "px";
            this.big_img_ele.style.height = this.big_img_offset.height + "px";
        },
        changeCutBoxScale : function( type ){
            switch ( type ){
                case "large" : 
                    this.cutting_box_offset.width += 2;
                    this.cutting_box_offset.height += 2;

                    this.res.x --;
                    this.res.y --;
                    breakl;
                case "narrow" : 
                    this.cutting_box_offset.width -= 2;
                    this.cutting_box_offset.height -= 2;

                    this.res.x ++;
                    this.res.y ++;
                    breakl;
                default:
                    break;
            }
            this.cutting_box_ele.style.width = this.cutting_box_offset.width + "px";
            this.cutting_box_ele.style.height = this.cutting_box_offset.height + "px";
            
            // 位置改变之后,调用相应的比例计算工具
            this.scaleBigImg();
            // 重新进行大图运动的计算
            this.eleMove( this.res );
        }
    }
    new Magnifier({
		small_box : ".small",
		cutting_box : ".grayBox",
		big_box : ".big",
		big_img : ".big img"
	});
</script>
</html>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值