JS-part14.4-面向对象的放大镜

面向对象的放大镜

 准备构造函数
   1. show 盒子 属性: 移入移出事件
   2. mask 盒子 属性: 显示隐藏 / 移动
   3. enlarge 盒子 属性: 显示隐藏 / 背景图片移动
   4. list 盒子 属性: 切换图片
   5. 一对方法
<style>
    *{
        margin: 0;
        padding: 0;
    }

    .box{
        width: 450px;
        height: 600px;
        border: 1px solid #333;
        margin: 100px;
        position: relative;
    }

    .box > .show{
        width: 450px;
        height: 450px;
        border-bottom: 1px solid #333;
        position: relative;
        cursor: none;
    }

    .box > .show .mask{
        width: 200px;
        height: 200px;
        background-color: rgba(120, 120, 120, .5);
        position: absolute;
        left: 10px;
        top: 10px;
        display: none;

        /* 我不当做事件目标 */
        pointer-events: none;
    }

    .box > .show .mask.active{
        display: block;
    }

    img{
        width: 100%;
        height: 100%;
        display: block;
    }

    .box > .enlarge{
        width: 500px;
        height: 500px;
        border: 1px solid red;
        position: absolute;
        left: 110%;
        top: 0;

        background: url(./imgs/big.jpg) no-repeat;
        background-size: 800px 800px;
        background-position: 0 0;

        display: none;
    }

    .box > .enlarge.active{
        display: block;
    }

    .box > .list{
        width: 100%;
        height: 149px;
        box-sizing: border-box;
        padding: 47px 40px;
    }

    .list > p{
        width: 54px;
        height: 54px;
        float: left;
        margin-right: 20px;
        border: 1px solid transparent;
        cursor: pointer;
    }

    .list > p.active{
        border: 1px solid red;
    }
</style>

<body>
    <div class="box">
        <div class="show">
            <!-- 展示图片 -->
            <img src="./imgs/show.jpg" alt="">
            <!-- 遮罩层 -->
            <div class="mask"></div>
        </div>

        <div class="enlarge"></div>

        <div class="list">
            <p class="active">
                <img src="./imgs/small.jpg" 
                data-show="./imgs/show.jpg"
                data-big="./imgs/big.jpg"
                alt="">
            </p>
            <p>
                <img src="./imgs/small1.jpg" 
                data-show="./imgs/show1.jpg" 
                data-big="./imgs/big1.jpg" 
                alt="">
            </p>
        </div>
    </div>
</body>
<script src="./enlarge.js"></script>

<script>
    /*
      面向对象的放大镜

      准备构造函数
        1. show 盒子 属性: 移入移出事件
        2. mask 盒子 属性: 显示隐藏 / 移动
        3. enlarge 盒子 属性: 显示隐藏 / 背景图片移动
        4. list 盒子 属性: 切换图片
        5. 一对方法
    */
    
    new Enlarge('.box')

    // new Enlarge('.box', { 配置
    // })

</script>
调整盒子示意图

在这里插入图片描述

右边背景图跟着动示意图

在这里插入图片描述

/*
  enlarge.js 
  代码实现

  0. 找到我们各种要操作的元素
    => show
    => mask
    => enlarge
    => list

  1. 移入移出
    => 移入 show 盒子显示
    => 移出 show 盒子隐藏
  
  2. 需要调整某一个盒子的大小, 让它成比例
      遮罩层尺寸       enlarge 盒子
    ------------- = --------------
      show 盒子        背景图尺寸

    enlarge 盒子 = 遮罩层尺寸 / show 盒子尺寸 * 背景图尺寸

    => 怎么拿尺寸? 
        -> offsetWidth? 不行, 页面一打开, overOut()一执行, display: none, 尺寸拿到 0; 应该在鼠标移入时拿尺寸, 但是这样每次移入都要重新获取尺寸
    
    3. 移动
      => 直接移动 mousemove 事件就可以, 绑定给谁? show 盒子
      => 获取坐标, 哪一套? 
        -> offset 一套
        -> 当你光标在 遮罩层的时候, 会按照遮罩层来拿坐标
      => 移动的边界值判断
      => 右边背景图片跟着动
          遮罩层的尺寸       enlarge 盒子尺寸
        -------------- = --------------------
         遮罩层移动距离      enlarge 盒子移动的距离(负的背景图移动距离)
        enlarge 盒子移动距离(负的背景图移动距离) = enlarge 盒子尺寸 * 遮罩层移动距离 / 遮罩层的尺寸

    4. 切换图片
      => list 里面的每一个绑定一个点击事件
      => 事件委托, 委托给 list
      => 切换边框的显示样式
        -> 让所有的兄弟元素 p 都没有
        -> 当前点击的这个 img 的父元素有类名
      => 换图片
        -> 在布局的时候, 就把图片的地址写在元素身上
*/

function Enlarge(ele){
    // 属性写在构造函数内部
    this.ele = document.querySelector(ele)

    // 0. 找到我们各种要操作的元素
    // 找到 show 盒子
    this.show = this.ele.querySelector('.show')

    // 找到 遮罩层 盒子
    this.mask = this.ele.querySelector('.mask')

    // 找到 放大镜 盒子
    this.enlarge = this.ele.querySelector('.enlarge')

    // 找到 列表 盒子
    this.list = this.ele.querySelector('.list')

    // 这里的 this 也是当前实例
    // 我在这里启动 启动器
    this.init()
}

// 0. 准备一个启动器函数
Enlarge.prototype.init = function(){
    // 我的 this 也是当前实例
    // 把所有要启动的方法给启动了
    this.getProp()
    this.overOut()
    this.setScale()
    this.move()
    this.bindEvent()
}

// 方法写在 构造函数的 prototype 里
// 1. 移入移出
Enlarge.prototype.overOut = function(){
    // 移入 show 显示, 移出 show 隐藏
    this.show.addEventListener('mouseover', () => {
        this.mask.classList.add('active')
        this.enlarge.classList.add('active')
    })

    this.show.addEventListener('mouseout', () => {
        this.mask.classList.remove('active')
        this.enlarge.classList.remove('active')
    })
}

// 2-0. 把获取尺寸这些事情提取出来
Enlarge.prototype.getProp = function(){

    // 2-1. 获取遮罩层尺寸
    this.mask_width = parseInt(window.getComputedStyle(this.mask).width)         //  转为数值类型 / 取整
    this.mask_height = parseInt(window.getComputedStyle(this.mask).height)         
    
    // 2-2. show 盒子尺寸
    // show 盒子不需要隐藏, 故可用 offsetWidth
    this.show_width = this.show.offsetWidth
    this.show_height = this.show.offsetHeight

    // 2-3. 背景图尺寸
    const bg = window.getComputedStyle(this.enlarge).backgroundSize.split(' ')
    this.bg_width = parseInt(bg[0])
    this.bg_height = parseInt(bg[1])

}

// 2. 调整比例
Enlarge.prototype.setScale = function(){
    
    // 2-4. 计算
    this.enlarge_width = this.mask_width / this.show_width * this.bg_width
    this.enlarge_height = this.mask_height / this.show_height * this.bg_height

    // 2-5. 设置
    this.enlarge.style.width = this.enlarge_width + 'px'
    this.enlarge.style.height = this.enlarge_height + 'px'
}

// 3. 动起来
Enlarge.prototype.move = function(){
    // 3-1. 给 show 盒子绑定一个鼠标移动事件
    this.show.addEventListener('mousemove', (e) => {
        // 处理事件对象兼容
        e = e || window.event 

        // 3-2. 拿坐标
        let x = e.offsetX - 100
        let y = e.offsetY - 100

        // 3-3. 边界值判断
        if(x <= 0) x = 0
        if(y <= 0) y = 0
        if(x >= this.show_width - this.mask_width) x = this.show_width - this.mask_width
        if(y >= this.show_height - this.mask_height) y = this.show_height - this.mask_height

        // 3-4. 给遮罩层赋值
        this.mask.style.left = x + 'px'
        this.mask.style.top = y + 'px'

        // 3-5. 右边跟着动
        const moveX = this.enlarge_width * x / this.mask_width
        const moveY = this.enlarge_height * y / this.mask_height

        // 3-6. 给背景图赋值
        this.enlarge.style.backgroundPosition = `-${ moveX }px -${ moveY }px`   // 注意单位px前不要有空格 :)

    })
}

// 4. 绑定事件
Enlarge.prototype.bindEvent = function(){
    // 4-1. 给 this.list 绑定一个点击事件
    this.list.addEventListener('click', e => {
        // 处理事件对象兼容
        e = e || window.event
        // 处理事件目标兼容
        const target = e.target || e.srcElement

        if(target.nodeName === 'IMG'){
            // 4-2. 切换边框显示
            for(let i = 0; i < this.list.children.length; i++){
                // this.list.children[i].className = ''
                this.list.children[i].classList.remove('active')
            }
            // 当前点击的是 img, 得让父元素有 active
            target.parentElement.classList.add('active')

            // 4-3. 换图片
            // 拿到当前点击的这个元素身上的自定义属性
            const showImg = target.dataset.show
            const enlargeImg = target.dataset.big

            console.log(showImg, enlargeImg)
            // 赋值给对应的盒子
            this.show.firstElementChild.src = showImg
            this.enlarge.style.backgroundImage = `url(${enlargeImg})`
        }
    })
}

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值