案例-放大镜效果(面向对象)

Ⅰ- 壹 - 放大镜效果:

在这里插入图片描述

Ⅱ - 贰 - HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

 
</head>
<body>
    <script type="module">
      import ZoomMenu from "./js/ZoomMenu.js";
    // import CarouselMenu from "./js/CarouselMenu.js";
		//小轮播图数组
        var list=["a_icon.jpg","b_icon.jpg","c_icon.jpg","d_icon.jpg","e_icon.jpg","f_icon.jpg","g_icon.jpg","h_icon.jpg","i_icon.jpg","j_icon.jpg"]
       //实例化ZoomMenu   传入数组
		let zoomMenu=new ZoomMenu(list);
		//执行zoomMenu方法   
        zoomMenu.appendTo(document.body);
    // let carouselMenu=new CarouselMenu(list);
    // carouselMenu.appendTo(document.body);

    </script>
</body>
</html>

Ⅲ - 叁 - js

js面向对象开发:有三个模块分别为:

  1. Zoom .js 是放大镜的封装
  2. CarouselMenu.js 轮播图的封装
  3. ZoomMenu.js 为连接1,2的实现
  4. 用到了Utils.js工具类

一 Zoom .js 是放大镜的封装

import Utils from "./Utils.js";
export default class CarouselMenu {
    smallWidth = 450;//small容器的宽度
    maskWidth = 303.75;// mask容器宽度
    zoomWidth = 540;//zoom容器宽度
    constructor() {
        //this.elem:储存createElem()返回的div 为创建的所有元素  
        this.elem = this.createElem();
    }
    //创建容器  div>(div#small>div#mask)+div#zoom
    createElem() {
        //判断this.elsm如果有存入的值 直接跳出不执行下面代码    性能优化
        if (this.elem) return this.elem;
        //创建div容器   
        let div = Utils.ce("div", {
            position: "absolute",
        });
        //在div容器下面添加以下内容
        div.innerHTML =
            "<div class='small' id='small'>" +
            "<div class='mask' id='mask'></div>" +
            "</div>" +
            "<div class='zoom' id='zoom'></div>"
            ;
        //添加css样式的函数
        this.setStyle();
        //这个方法会把所有具备id的元素,放在当前对象中
        //列如id是small的div,执行后就能通过this.small直接获取
        Utils.getIdElem(div, this);//这里的this是当前这个类
        //把这个事件函数储存在mouseHanlder,有利于执行完后关闭事件
        this.mouseHanlder=e=>this.smallMouseHandler(e);
        //small容器添加事件
        this.small.addEventListener("mouseenter", this.mouseHanlder);//鼠标进入事件
        //接收 //小轮播图的小图添加鼠标经过事件抛发的事件    CarouselMenu.js   执行函数  
        document.addEventListener("Change_Menu_Img",e=>this.setImage(e.src));
        return div;
    }
    //div的样式   small:存放的容器   mask:移动的那个小容器   zoom:放大镜效果的容器
    setStyle() {
        Utils.insertCss(".small", {
            width: this.smallWidth + "px",
            height: this.smallWidth + "px",
            position: "absolute",
            border: "1px solid #000000",
        });
        Utils.insertCss(".mask", {
            width: this.maskWidth + "px",
            height: this.maskWidth + "px",
            backgroundColor: "rgba(200,170,0,0.3)",
            position: "absolute",
            display: "none"
        });
        Utils.insertCss(".zoom", {
            width: this.zoomWidth + "px",
            height: this.zoomWidth + "px",
            border: "1px solid #CCCCCC",
            position: "absolute",
            left: this.smallWidth + 2 + "px",
             display: "none"
        });
    }
    //执行 zoom.addendTo(document.body);
    appendTo(parent) {
        parent.appendChild(this.elem);
       
    }
    //鼠标事件事件方法
    smallMouseHandler(e) {
        //事件类型
        switch (e.type) {
            //鼠标进入事件
            case "mouseenter":
                //如果this.rect没有值   this.small这个div的元素位置赋值给this.rect
                //e.currentTarget始终是监听事件者,即 直接调用addEventlistener那个节点    document
                if (!this.rect) this.rect = this.small.getBoundingClientRect();//getBoundingClientRect()获取元素位置,这个方法没有参数
                e.currentTarget.addEventListener("mousemove", this.mouseHanlder);//鼠标移动事件   触发执行函数  进入case "mousemove":
                e.currentTarget.addEventListener("mouseleave", this.mouseHanlder);//鼠标离开事件   触发执行函数  进入case "mouseleave":
                //显示this.mask. this.zoom.这俩个div
                this.mask.style.display = "block";
                this.zoom.style.display = "block";
                break;
            //鼠标移动
            case "mousemove":
                //执行方法masKMove();
                this.masKMove(e.clientX,e.clientY);//鼠标当前点击位置坐标
                break;
            //鼠标离开  移除事件监听   zoom  mask  元素设置隐藏
            case "mouseleave":
                e.currentTarget.removeEventListener("mousemove", this.mouseHanlder);
                e.currentTarget.removeEventListener("mouseleave", this.mouseHanlder);
                this.mask.style.display = "none"
                this.zoom.style.display = "none"
                break;
        }

    }
    // 鼠标移动  放大镜效果
    masKMove(_x,_y){
        //拖拽元素的中心位置
        //this.rect.x:this.small这个div的元素位置的横坐标  maskWidth:mask容器宽度
        var x=_x-this.rect.x-this.maskWidth/2;
        var y = _y - this.rect.y - this.maskWidth / 2;
        //拖拽事件只能在父容器的区域  拖拽 
        if(x<0) x=0;
        if(y<0) y=0;
        //small这个div的元素位置与子容器mask之间的距离横纵坐标
        if (x > this.rect.width - this.maskWidth) x = this.rect.width - this.maskWidth;
        if (y > this.rect.height - this.maskWidth) y = this.rect.height - this.maskWidth;
        //this.mask子容器的位置变化
        Object.assign(this.mask.style,{
            left:x+"px",
            top:y+"px"
        });
        //this.zoom  放大效果  的容器
        Object.assign(this.zoom.style,{
            //背景图的位置  与mask鼠标移动方式相反方向    计算出大小图之间的比例 实现放大镜效果
            backgroundPositionX:-x*this.zoomWidth/this.maskWidth+"px",
            backgroundPositionY: -y * this.zoomWidth / this.maskWidth + "px",

        });
      

    }
    //抛发事件执行方法
    setImage(src) {
        Object.assign(this.small.style, {
            backgroundImage: "url(" + src + ")",
            backgroundSize: "100% 100%"
        });
        Object.assign(this.zoom.style, {
            backgroundImage: "url(" + src + ")",
        });
    }

}

二 CarouselMenu.js 轮播图的封装

import Utils from "./Utils.js";//引用Utils.js工具类
export default class CarouselMenu{

    num=5;//显示的个数  轮播图小图显示的个数
    position=0;//页数
    rre;//储存点击左右的e.target当前元素
    //arr:数组,_width:参数储存为全局  如果未传参 初始值为450 _x//轮播图容器的x轴:_y://轮播图容器的y轴
    constructor(arr,_width=450,_x=0,_y=0){
        this.x=_x;//轮播图容器的x轴
        this.y=_y;//轮播图容器的y轴
        this.menuWidth=_width;//参数储存为全局  如果未传参 初始值为450
        this.list=arr;//把数组保存到list属性中
        this.elem=this.createElem(arr);//执行函数createElem(arr)的结果储存到this.elem属性中
  
    }

    createElem(arr) {
        //防止重复创建  如果this.elem就结束方法运行
        if(this.elem) return this.elem;

        let div=Utils.ce("div");//Utils.js工具类   创建一个div
        div.className="carousel";//给div添加一个类  carousel
        //在div容器下面添加以下内容
        //使用到了字符串模板,顺带arr.reduce这回数组方法
        //img div>div>img*10 img
        div.innerHTML = `
        <img src='./img/prev.png' class='prev' id='prev'>
        <div class='carouselDiv'>
            <div class='imgCon' id='imgCon'>
                ${arr.reduce((value, item) => {
        value += '<img src=./img/' + item + ' class=imgs>'
        return value
    }, '')}
            </div>
        </div>
        <img src='./img/next.png' class='next' id='next'>
    `;
        //执行方法  添加样式
        this.setStyle(arr);
        Utils.getIdElem(div,this);//获取div包含子元素id属性      添加为这个类的全局属性         
        //获取的id  给元素添加事件
        this.prev.addEventListener("click", e => this.bnClickHandler(e));//小轮播的左图标绑定点击事件
        this.next.addEventListener("click", e => this.bnClickHandler(e));//小轮播的右图标绑定点击事件
        this.imgCon.addEventListener("mouseover", e => this.mouseHandler(e));//小轮播图的小图添加鼠标经过事件
        return div;
    }

      //执行  追加到元素的后面
      appendTo(parent) {
        parent.appendChild(this.elem);
    }
    //添加css样式的方法
    setStyle(arr){
        //轮播图父容器的父容器  top:this.y+2+"px",距离放大镜的top距离
        Utils.insertCss(".carousel",{
            width: this.menuWidth + "px",
            height: "58px",
            position: "absolute",
            top:this.y+2+"px",
        });
        //小轮播图的左右图标
        Utils.insertCss(".prev,.next", {
            position: "absolute",
            top: "0px",
            bottom: "0px",
            height: "32px",
            margin: "auto"

        })
        //设置图标的左右位置
        Utils.insertCss(".prev", { left: "5px" });
        Utils.insertCss(".next", { right: "5px" });
        //左右图标的宽度
        var w=this.menuWidth-64;
        // 轮播图的父元素的父元素
        Utils.insertCss(".carouselDiv", {
            width: w + "px",
            height: "58px",
            position: "absolute",
            left: "32px",
            overflow: "hidden",
        });
        //轮播图之间的间距  19.2
        var gap = (w - 58 * this.num) / this.num;
        //轮播图的的长度  772
        var conW = arr.reduce(value => {
            return value + 58 + gap;
        }, 0);
        //轮播图的父元素
        Utils.insertCss(".imgCon", {
            position: "absolute",
            width: conW + "px",
            height: "58px",
            left: 0,
            transition: "all 0.5s"
        });
        //轮播图的样式
        Utils.insertCss(".imgs", {
            width: "54px",
            height: "54px",
            border: `2px solid rgba(255,0,0,0)`,
            marginRight: gap + "px"
        })
  
    }
    //小轮播图左右点击事件执行  
    bnClickHandler(e){
        //正则表达式查找prev    e.target.src当前点击元素  的src
         if(/prev/.test(e.target.src)){
            this.position--;
            if(this.position<0) this.position=0;
                        // if (this.position < 0) this.position = Math.ceil(this.list.length / this.num) - 1;

         }else{
            this.position++;
            if (this.position > Math.ceil(this.list.length / this.num) - 1) this.position = Math.ceil(this.list.length / this.num) - 1;
             // if (this.position > Math.ceil(this.list.length / this.num) - 1) this.position = 0;

         }
         //为计算后轮播图的宽度
         var w=this.menuWidth-64;
         //计算后点击左右按钮移动的 宽度
         this.imgCon.style.left = -this.position * w + "px"
    }
    //小轮播图的小图添加鼠标经过事件
    //e.target当前点击的元素
    mouseHandler(e){
        if (e.target.nodeName !== "IMG") return;
        if (this.pre) {
            this.pre.style.border = "2px solid rgba(255,0,0,0)";
        }
        this.pre = e.target;
        this.pre.style.border = "2px solid rgba(255,0,0,1)";
        //抛发事件  replace替换  _icon替换为空字符串
        var evt=new Event("Change_Menu_Img");
        evt.src=e.target.src.replace("_icon","");
        document.dispatchEvent(evt);
    }



}

三 ZoomMenu.js 为连接1,2的实现

import Zoom from "./Zoom.js";
import CarouselMenu from "./CarouselMenu.js";
import Utils from "./Utils.js";
export default class ZoomMenu{
    constructor(arr){
        this.elem=this.createElem(arr);//执行方法把返回的内容 (div) 储存为全局
    }
    //执行方法
    createElem(arr){
        if(this.elem) return this.elem;//单例吗模式  防止重复创建
        //创建一个div  是放大镜和轮播图的  父容器
        let div=Utils.ce("div",{
            width:"1200px",
            margin: "0 auto",
            border: "1px solid slategrey",
            position:"relative"
        });
        //Zoom   是放大镜的封装
        //shilihua实例化
        let zoom=new Zoom();
        //把新建的div  作为参数传入
        zoom.appendTo(div);
        //CarouselMenu轮播图的封装
        // //arr:数组,_width:参数储存为全局  如果未传参 初始值为450 _x//轮播图容器的x轴:_y://轮播图容器的y轴
        let carousel=new CarouselMenu(arr,450,0,450);
        carousel.appendTo(div);
 
        return div;
    }
    //执行   this.elem)内容追加到body    【zoomMenu.appendTo(document.body);】
    appendTo(parent){
        parent.appendChild(this.elem);
        console.log(this.elem);
    }
}

0 - 0 - 知识点:

1. styleSheetsdocument.styleSheets
这个接口可以获取网页上引入的link样式表和style样式表document.styleSheets.length 获取页面上样式表的长度toLowerCase() 方法用于把字符串转换为小写。
2. cssRules返回的是一个规则集合,通过索引可以获取指定位置的规则。
**3. insertBefore(newItem,existingItem);**方法可在已有的子节点前插入一个新的子节点。insertBefore(插入的元素,插入的位置)
4. innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML。可以直接写HTML标签事件
5. 使用到的事件

  • mousemove 鼠标移动
  • mouseover 鼠标经过
  • mouseout 鼠标滑出
  • mouseenter 鼠标进入
  • mouseleave 鼠标离开
    6. getBoundingClientRect()获取元素位置,这个方法没有参数
    7.currentTarget与targetcurrentTarget
    始终是监听事件者,即 直接调用addEventlistener那个节点而target是事件的真正发出者, 即 触发事件的节点,在click事件中就是被点击的节点。
    8.clientX、clientY鼠标当前点击位置坐标点击位置距离当前body可视区域的x,y坐标
    9.reduce() 方法接收一个函数作为累加器,reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(上一次回调的返回值),当前元素值,当前索引,原数组。
arr.reduce(value=>{ 
		return value+58+gap;      
  },0)

10.正则表达式test() 方法用于检测一个字符串是否匹配某个模式.
11事件抛发
EventTarget叫事件目标对象,Event实例的对象叫事件对象。侦听和派发的对象可以是DOM元素,也可以是EventTarget,或者继承EventTarget的类。

  1. // 如果侦听函数调用(addEventListener被使用),就会在内存中添加存储
  2. // 尽量减少事件的侦听,因此就会将事件委托给父容器做侦听,以达到减少事件侦听的存储
  3. // e.currentTarget 是事件侦听事件对象(什么对象执行addEventListener函数就是谁)
  4. // e.target 事件的目标对象 事件实际触发的目标阶段最后对象,e.srcElement兼容IE
  5. // 事件函数中this默认等同于e.currentTarget
  • 用法
    在CarouselMenu.js抛发事件
//抛发事件  replace替换  _icon替换为空字符串
var evt=new Event("Change_Menu_Img");
evt.src=e.target.src.replace("_icon","");
document.dispatchEvent(evt);
  • 接收事件
    在Zoom.js接收事件
//接收 //小轮播图的小图添加鼠标经过事件抛发的事件    CarouselMenu.js   执行函数  
document.addEventListener("Change_Menu_Img",e=>this.setImage(e.src));

12.replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
13.添加标签:

div.innerHTML = `
     <img src ='./ img / prev.png'class ='prev'id ='prev'> 
    <div class ='carouselDiv'> 
        <div class ='imgCon'id ='imgCon'> 
            $ {arr.reduce((value,item)=> { 
    value + ='<img src =。/ img /'+ item +'class = imgs> </ img>' 
},'')} 
        < / div> 
    </ div> 
    <img src ='./ img / next.png'class ='next'id ='next'> ` ; 
  • 效果如下:
  • 在这里插入图片描述
  • 14.箭头指向函数 更改this指向为父方法。
  • 15.innerHTML 可以添加字符串模板,模板內可以增加数组的方法进行结果的运算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值