JS实现购物网站商品放大镜效果

一、需求说明

1、鼠标移入图片显示遮罩层和右边的放大镜
      鼠标移出图片隐藏遮罩层和右边的放大镜
2、鼠标经过下面的图片列表区切换显示的图片
3、鼠标在显示的图片上移动,遮罩层也会跟着移动,并且放大的图片也会跟着对应移动


二、核心代码

// 放大镜构造函数
// 参数1    生成放大镜内容的标签对象
// 参数2    放大镜参数数据数组
class setGlass {
    constructor(element, array) {
        // 定义属性存储参数
        this.ele = element;
        this.arr = array;
        // 定义属性存储数据
        this.show;
        this.img;
        this.mask;
        this.list;
        this.listLiImg;
        this.glass;
    }

    // 入口函数
    init() {
        // 入口函数中调用所有需要执行的函数程序
        this.setPage();
        this.setMouseOver();
        this.setMouseMove();
    }

    // 动态生成页面
    setPage() {
        // 创建标签对象
        this.show = document.createElement('div');
        this.mask = document.createElement('div');
        this.glass = document.createElement('div');
        this.img = document.createElement('img');
        this.list = document.createElement('ul');

        // 设定标签对象的相关属性

        // 显示区 设定 class选择器
        this.show.classList.add('show');
        this.mask.classList.add('mask');
        this.list.classList.add('list');
        this.glass.classList.add('glass');

        // 图片标签 默认显示 数组中 第一组数据中 large图片
        this.img.setAttribute('src', `./images/${this.arr[0].large}`);
        // 图片标签 添加name属性值
        this.img.setAttribute('name', 'showImg');
        this.mask.setAttribute('name', 'showImg');


        // 显示区中 有 图片标签 和 遮盖层标签
        this.show.appendChild(this.img);
        this.show.appendChild(this.mask);

        // 给 this.show  这个节点 直接 绑定事件
        // 绑定好事件之后 再 执行写入操作
        // 之后 即使 再次动态渲染生成页面 也是 创建新的this.show节点 同时绑定事件 再写入节点
        this.show.addEventListener('mouseenter', () => {
            // 移入 让 遮盖层 和 放大镜 显示
            this.mask.style.display = 'block';
            this.glass.style.display = 'block';
        })

        this.show.addEventListener('mouseleave', () => {
            // 移入 让 遮盖层 和 放大镜 隐藏
            this.mask.style.display = 'none';
            this.glass.style.display = 'none';
        })
        
        // 根据数组生成 list 中 li 标签对象
        let liStr = '';

        this.arr.forEach((item, key) => {
            liStr += key === 0 ? `<li><img name="liImg" class="active" index="${key}" src="./images/${item.small}" alt=""></li>` : `<li><img name="liImg" index="${key}" src="./images/${item.small}" alt=""></li>`
        })

        // 将 字符串 写入 list,ul标签中
        this.list.innerHTML = liStr;

        // 将 标签对象 写入 box,div标签 中
        this.ele.appendChild(this.show);
        this.ele.appendChild(this.list);
        this.ele.appendChild(this.glass);

        // 将 标签对象 写入 box,div标签 之后 
        // 获取 list 标签中的 li标签 中的 img标签
        this.listLiImg = this.list.querySelectorAll('li>img');

    }

    // 鼠标 移入 图片
    // 只有 移入没有移出 可以 事件委托添加给 图片标签
    setMouseOver() {
        // 给 父级div标签 添加 鼠标移入事件
        this.ele.addEventListener('mouseover', e => {
            // 如果 移入的标签 name 是 liImg 证明 移入的是 列表 图片标签
            if (e.target.getAttribute('name') === 'liImg') {
                // 1 清除其他的img标签 class,active 给 移入的img标签添加 class,active
                // 循环遍历 所有的 li>img 清除 class,active
                this.listLiImg.forEach(item => {
                    // item 就是 图片标签对象
                    item.classList.remove('active');
                })
                // 给经过的 li>img 添加 class,active
                e.target.classList.add('active');

                // 2 设定 show显示区域中img标签src属性 
                // 是 鼠标进过的 li>img 标签 index属性中 存储的索引下标
                this.img.setAttribute('src', `./images/${this.arr[Number(e.target.getAttribute('index'))].large}`);

                // 3 设定 glass放大镜中背景图片的css样式
                this.glass.style.backgroundImage = `url('./images/${this.arr[Number(e.target.getAttribute('index'))].large}')`;

            }
        })
    }

    // 鼠标 拖住效果
    setMouseMove() {
        // 如果视窗窗口大小改变,刷新页面
        window.addEventListener('resize', function () {
            window.location.reload();
        })

        // 获取 数据 

        // 获取 box,div的 外间距
        let oBoxLeft = this.ele.offsetLeft;
        let oBoxTop = this.ele.offsetTop;

        // 获取 show,div的 边框线
        let oShowBorderLeft = this.show.clientLeft;
        let oShowBorderTop = this.show.clientTop;

        // 获取 show,div的 占位 内容+padding
        // 用来设置极值
        let oShowWidth = this.show.clientWidth;
        let oShowHeight = this.show.clientHeight;
        console.log(oShowWidth);
        let oShowWidth1 = this.show.offsetWidth;
        let oShowHeight1 = this.show.offsetHeight;

        // 获取 mask,div的 占位 内容+padding+border
        let oMaskWidth = parseInt(window.getComputedStyle(this.mask).width);
        let oMaskHeight = parseInt(window.getComputedStyle(this.mask).height);

        // 给 父级div标签 添加 鼠标移动事件
        // 如果 是 在 show,div 中 img标签 触发移动事件 执行 鼠标拖拽效果
        this.ele.addEventListener('mousemove', e => {
            // 事件对象标签 name 是 showImg 证明 触发的标签是 show,div中的img标签
            if (e.target.getAttribute('name') === 'showImg') {
                // 1, 计算设定 遮盖层定位数据
                let x = e.pageX - oBoxLeft - oShowBorderLeft - oMaskWidth / 2;
                let y = e.pageY - oBoxTop - oShowBorderTop - oMaskHeight / 2;
                // 2, 设定极值
                x = x < 0 ? 0 : x;
                y = y < 0 ? 0 : y;
                x = x > oShowWidth - oMaskWidth ? oShowWidth - oMaskWidth : x;
                y = y > oShowHeight - oMaskHeight ? oShowHeight - oMaskHeight : y;
                // 3, 将 遮盖层定位赋值
                this.mask.style.left = x + 'px';
                this.mask.style.top = y + 'px';
                // 4, 设定 背景图片定位数值 
                // 和 遮盖层定位数值方向相反 比例关系 是 2.5 倍
                this.glass.style.backgroundPosition = `${-x * 2.5}px ${-y * 2.5}px`;
            }
        })
    }
}

三、解释说明

放大镜
        1, 放大镜 默认起始显示 第一组图片内容
        2, 放大镜div中显示的 背景图片
        3, 各个区域内容的原始比例关系
                        遮盖层              放大镜
                        --------     =     -----------
                        显示区             背景图片

  1. 重点内容:外部 js 文件中的相对路径

    ​ 不是写外部 js 文件的相对路径,写的是加载执行这个 js 文件的 html 文件的相对路径,意思就是: js 里面的图片路径是从这个 html 文件出发去寻找图片的,而不是从 js 出发。

  2. 重点内容:子级标签添加鼠标移入移出事件

    ​ 不能通过事件委托给父级标签添加事件,实现子级标签的移入、移出;因为子级标签触发over 移入的同时也会触发父级标签的 out 移出事件。

    ​ 在创建标签时直接给创建的子级标签节点添加事件,添加好事件之后,将标签节点写入,也就是每次写入的节点都是绑定好事件的节点。

  3. 给列表区中的 img标签添加鼠标移入事件

    只有鼠标移入,没有鼠标移出,因此可以通过事件委托的语法形式给 img标签添加事件。

    需要注意:

    • img标签设定的是标签的 src属性的属性值
    • div标签设定的是 backgroundImage背景图片的路径样式
  4. 鼠标拖动效果

    获取数据:

    • display: none / 绝对定位 / 固定定位 的标签,没有占位大小,

    • 只能通过标签的 css 样式属性获取占位大小。在获取 mask的占位时用到了。

    • 遮盖层移动和背景图片移动的比例关系

      • 遮盖层移动和背景图片移动方向相反

      • 移动数值成等比例关系

        遮盖层                显示区               遮盖层定位            

        ----------     =      -------------    =    ------------------        

        放大镜               背景图片          背景图片定位            

      • 比例关系怎么确定?

        • 若遮罩层移动到最右边,那么背景图要移动到最左边
        • 遮罩层到最右边需要移动 显示区的大小(400) - 遮罩层的大小(200) = 200
        • 背景图到最左边需要移动 背景图的大小(1000) - 放大镜的大小(500) = 500
        • 他们移动距离的比值是:200/500 = 1/2.5

四、效果演示

在这里插入图片描述


五、完整代码下载

           下载地址

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值