二十二、ES6新增语法(class类,继承)

知识回顾

语法概念
原型:js给每个函数分配的公共空间

原型好处:减少代码冗余、便于后期维护

设置原型

构造函数中普遍是属性
构造函数公共空间普遍是方法

构造函数.prototype.键 = 值
构造函数.prototype.键 = 对象 (留心:修改构造函数原型执行

获取原型

实例对象.键

原型链:多个原型的集合

原型链特性:

 调用对象属性和方法
先  自身找  没有
去  原型链  找
一直 Object构造函数的公共空间
还是 没有
属性 undefined
方法 报错

面向对象思想使用回顾

面向过程:根据思路一步一步写
面向对象(可以理解为一个固定格式

let obj = new 构造函数(父box类名, option)

function  构造函数(el, option = null) {

	this.el = document.qs(el)
	this.option = option || {}
    
    this.init()
}

构造函数.prototype.init = function() {
    // 去调用默认要启动的方法
}

Tab选项卡:一个bindEvent 其实越细越好   标题移入方法、内容切换
Page分页:创建分页标签、创建分页页码、创建P标签、父点击事件、标签禁用方法

ES6构造函数/类!!!

纯面向对象:封装(定义公共模板 类似女娲造人脑海中的印象/车模型、继承(子继承父、多态(子既又自己的特色))
封装:class 类 模板

继承:extends

创建对象:new

JS中面向对象:封装(函数升级、继承(原型、多态(原型链)
封装:function

继承:原型prototype

创建对象:new

  • 发现: JS中面向对象和纯面向对象有区别

1-封装模板 ,2-继承

  • 解决: 在es6中增加了class、extends关键词,但是仅仅是语法糖

语法
以前

function  函数名(形参1,...,形参n) {
   this.键 = 值
   //...
}

函数名.prototype.键=  值

let obj = new 函数名(实参1,...,实参n)

现在

class 类名
{	
	// 当你实例化时会自动触发这个方法
	    constructor(形参1,...,形参n) {
	        this.键 = 值
	        //...
	    }
	    
	    // 这里面的方法都在原型链上
	    函数名() {
	        
	    }
	    
	}
	
	let obj = new 函数名(实参1,...,实参n)

练习

  • 需求:定义一个学生类(姓名-张三,年龄-18,和sayName方法)
  • 在ES5中
  • 在ES6中
<script>
// 需求:定义一个学生类(姓名-张三,年龄-18,和sayName方法)

// ------------------------------------------ES6
class Stu
{
    constructor(name, age) {
        // 构造函数的this
        this.name = name
        this.age = age
    }

    sayName() {
        // 原型链上的this
        console.log(this.name)
    }
}
let obj2 = new Stu('李四', 18)
console.log(obj2)
obj2.sayName()
//-------------------------------------------------------------------------------
//------------------------------------------ ES5
 function Stu(name, age) {
     this.name = name
     this.age = age
 }

 Stu.prototype.sayName = function() {
     // 原型链this = 构造函数this = 实例对象
     console.log(this.name)
 }

 let obj1 = new Stu('测试', 18)
 console.log(obj1)
 obj1.sayName()
</script>

ES6继承!!!

语法

class  父类名
{
	constructor() {
        this.键 = 值
        // ... 
	}
	
	方法名() {
        
	}
	// ....
}


class  子类名  extends  父类名
{
	// 留心1:constructor不能覆盖
	// 解决1:子不写或父不写(不现实
	// 解决2:子调用父的constructor  通过系统内置关键词super(实参,...,实参)
	constructor() {
		
		super(父所需实参,...,...)
	
        this.键 = 值
        // ... 
	}
	
	// 留心2:子覆盖父同名方法
	方法名() {
        
	}
	// ....
}

练习
验证1:子调用父、重名覆盖

<script>
// 验证1:子调用父、重名覆盖
class Father
{
    a() {
        console.log('this is father a')
    }
    
    b() {
        console.log('this is father b')
    }
}


// class Son
class Son extends Father
{
    a() {
        console.log('this is son a')
    }
}
let obj1 = new Son
obj1.a()
obj1.b()
</script>

结果
在这里插入图片描述
验证2:父的construct不能覆盖、解决通过super关键词


class Father 
{
    constructor()
    {
        console.log('this is father constructor')
    }
}

class Son extends Father
{
    constructor()
    {
        super()  // 调用父的constructor

        console.log('this is son constructor')
    }
}
let obj1 = new Son

在这里插入图片描述
验证3:父的construct不能覆盖、解决通过super关键词,分析super的传参过程

<script>

class Father 
{
    constructor()
    {
        console.log('this is father constructor')
    }
}

class Son extends Father
{
    constructor(name, age)
    {
        super()  // 调用父的constructor
        console.log('this is son constructor')
    }
}
let obj1 = new Son('张三', 18)
</script>

在这里插入图片描述
正确传参方式

<script>
class Father 
{
    constructor(name, age)
    {
        console.log(name, age);
        console.log('this is father constructor')
    }
}

class Son extends Father
{
    constructor(name, age)
    {
        super(name, age)  // 调用父的constructor
        console.log('this is son constructor')
    }
}
let obj1 = new Son('张三', 18)
</script>

在这里插入图片描述
传参过程分析
在这里插入图片描述

ES6语法总结!!!

定义

// 定义
class 类名
{
	// 当实例化也就是new时候会自动触发
    constructor(形参1,...,形参n) {
        this.键 = 值
    }
    
    // 原型链上
    函数名() {
        
    }
}

子会覆盖父的方法

 class 子 extends 父
{
	// 留心1:子写constructor就必须加super
	// 留心2:子可以不写constructor
    constructor(形参1,...,形参n) {
        this.键 = 值
    }
    
    // 原型链上
    函数名() {
        
    }
}

// 调用
let obj = new 子

实战练习

放大镜(enlarge)

坐标相关语法

offsetWidth = width + padding + border
clientWidth = width + padding

offsetX   =  自身左上角的X(注:容易有坑 一闪一来一去效果 鼠标提示、放大镜
clientX   =  网页左上角
pageX     =  网页左上角 + 滚动条
screenX   =  屏幕左上角

在这里插入图片描述
获取样式

标签对象.currentStyle.属性名
window.getComputedStyle(标签对象).属性名

标签对象.style.属性名

需求
在这里插入图片描述
调用

 new Enlarge(最大的盒子类名)

结构
es5语法

 function Enlarge(el) {
    this.el = document.qs(el)
    // ...
    
    this.init() 
}


Enlarge.prototype.init = function() {
    this.移入移除方法()
    this.移动方法 ()
    this.点击切换  ()
}
Enlarge.prototype.移入移除方法 = function() {}
Enlarge.prototype.移动方法 = function() {}
Enlarge.prototype.点击切换 = function() {}

es6语法

 定义:
	 class Enlarge
     {
     	constructor(CSS选择器)
     	{
            // 1. 保存全局信息
			this.el =  ..
			
			// 2. 默认调用
			this.init()
     	}
     	
     	init() {
            // 功能1
            // 功能2
           // 功能3
           // ....
            // 功能n
           this.enlargeOverOut()
           this.enlargeSetWH()
           this.maskMove()
           this.enlargeSetBg()
          this.smallImgChange()
    	}
     	
    }

调用:let 变量名 = new Enlarge(CSS选择器,配置信息略)

代码-静态页面

在这里插入图片描述

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active">
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li>
            <img src="./imgs/2.small.jpg" alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
// new Enlarge('.box')
</script>
</body>
</html>

代码-移入移出

鼠标移动到盒子大图上(1-显示遮罩,2-显示放大镜)

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active">
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li>
            <img src="./imgs/2.small.jpg" alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
class Enlarge
{
    constructor(el)
    {
        // 1. 保存全局信息
        this.el =  document.querySelector(el)
        
        // 2. 默认调用
        this.init()
    }
    
    init() {
        // 功能1
        // 功能2
        // 功能3
        // ....
        // 功能n
        this.enlargeOverOut()
        // this.enlargeSetWH()
        // this.maskMove()
        // this.enlargeSetBg()
        // this.smallImgChange()
    }

    // 鼠标移入到大图上:1-显示遮罩框,2-显示放大镜
    enlargeOverOut() { // this  === 构造函数中this
        // 给大图片增加鼠标移入事件
        // this.el.querySelector('.img').addEventListener('mouseover', function () { // this事件源
        // this.el.querySelector('.img').addEventListener('mouseover', () => { // 父function this
        //     // 1-显示遮罩框,2-显示放大镜
        //     this.el.querySelector('.mask').style.display = 'block'
        //     this.el.querySelector('.enlarge').style.display = 'block'
        // })

        // this.el.querySelector('.img').addEventListener('mouseover', () => {
        //     this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block'
        // }) 

        this.el.querySelector('.img').addEventListener('mouseover', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block') 
        this.el.querySelector('.img').addEventListener('mouseout', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'none') 
    }
}
new Enlarge('.box')
</script>
</body>
</html>

代码-盒子比例

  • 目的:让放大镜显示的内容 和 遮罩框黄色 一样
  • 公式
遮罩层尺寸(黄色)1       放大镜【盒子尺寸】 1
-----------------  =  ----------------------
bigImg盒子尺寸  2        放大镜【背景尺寸】 2
----------------------------------------------------------------------------

交叉相乘:

放大镜【盒子尺寸】 * bigImg盒子尺寸  =  遮罩层尺寸(黄色) * 放大镜【背景尺寸】

活用:

放大镜【盒子尺寸】  = 遮罩层尺寸(黄色) * 放大镜【背景尺寸】 / bigImg盒子尺寸 

代码

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active">
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li>
            <img src="./imgs/2.small.jpg" alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
class Enlarge
{
    constructor(el)
    {
        // 1. 保存全局信息
        this.el =  document.querySelector(el)
        this.enlarge = this.el.querySelector('.enlarge')
        this.mask = this.el.querySelector('.mask')
        this.bigImg = this.el.querySelector('.img')
        
        // 2. 默认调用
        this.init()
    }
    
    init() {
        // 功能1
        // 功能2
        // 功能3
        // ....
        // 功能n
        this.enlargeOverOut()
        this.enlargeSetWH()
        // this.maskMove()
        // this.enlargeSetBg()
        // this.smallImgChange()
    }


    // 设置放大镜宽度
    enlargeSetWH() {
        // 放大镜【盒子尺寸】  = 遮罩层尺寸(黄色) * 放大镜【背景尺寸】 / bigImg盒子尺寸 

        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))
 
        let enlarge = this.getStyle(this.enlarge, 'background-size')  // 800px 800px
        // console.log(enlarge.split(' ')) ["800px", "800px"]
        let enlargeW = parseInt(enlarge.split(' ')[0])
        let enlargeH = parseInt(enlarge.split(' ')[1])

        let bigImgW = parseInt(this.getStyle(this.bigImg, 'width'))
        let bigImgH = parseInt(this.getStyle(this.bigImg, 'height'))

        let w = maskW * enlargeW / bigImgW
        let h = maskH * enlargeH / bigImgH
        
        this.enlarge.style.width = w + 'px'
        this.enlarge.style.height = h + 'px'
    }

    // 获取非行内样式 - 留心:形参就是变量
    getStyle(tagObj, attr) 
    {
        if (window.getComputedStyle)
        {
            // return window.getComputedStyle(标签对象).属性名
            // return window.getComputedStyle(tagObj).attr  // 对象的属性是变量 加中括号
            return window.getComputedStyle(tagObj)[attr]
        } else {
            // return 标签对象.currentStyle.属性名 
            // return tagObj.currentStyle.attr 
            return tagObj.currentStyle[attr]  
        }
    }

    // 鼠标移入到大图上:1-显示遮罩框,2-显示放大镜
    enlargeOverOut() { // this  === 构造函数中this
        // 给大图片增加鼠标移入事件
        // this.el.querySelector('.img').addEventListener('mouseover', function () { // this事件源
        // this.el.querySelector('.img').addEventListener('mouseover', () => { // 父function this
        //     // 1-显示遮罩框,2-显示放大镜
        //     this.el.querySelector('.mask').style.display = 'block'
        //     this.el.querySelector('.enlarge').style.display = 'block'
        // })

        // this.el.querySelector('.img').addEventListener('mouseover', () => {
        //     this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block'
        // }) 

        this.el.querySelector('.img').addEventListener('mouseover', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block') 
        this.el.querySelector('.img').addEventListener('mouseout', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'none') 
    }
}
new Enlarge('.box')
</script>
</body>
</html>

代码-移动

思路

步骤1:给大图绑定鼠标移动事件
步骤2;事件处理函数中
// 2.1 获取鼠标位置
// 2.2 计算给遮罩框设置left和top
// 2.3 范围判断

留心坐标
在这里插入图片描述
范围
在这里插入图片描述
代码

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active">
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li>
            <img src="./imgs/2.small.jpg" alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
class Enlarge
{
    constructor(el)
    {
        // 1. 保存全局信息
        this.el =  document.querySelector(el)
        this.enlarge = this.el.querySelector('.enlarge')
        this.mask = this.el.querySelector('.mask')
        this.bigImg = this.el.querySelector('.img')
        
        // 2. 默认调用
        this.init()
    }
    
    init() {
        // 功能1
        // 功能2
        // 功能3
        // ....
        // 功能n
        this.enlargeOverOut()
        this.enlargeSetWH()
        this.maskMove()
        // this.enlargeSetBg()
        // this.smallImgChange()
    }

    // 遮罩框移动
    maskMove() {

        // this.bigImg.addEventListener('mousemove', function(e) {
        this.bigImg.addEventListener('mousemove', (e) => {
            // 获取事件对象
            e = e || window.event

            let w = e.pageX - this.el.offsetLeft - this.mask.clientWidth / 2
            let h = e.pageY - this.el.offsetTop - this.mask.clientHeight / 2

            if (w<0) w = 0
            if (h<0) h = 0
            if (w> this.bigImg.clientWidth-this.mask.clientWidth) w = this.bigImg.clientWidth-this.mask.clientWidth
            if (h> this.bigImg.clientHeight-this.mask.clientHeight) h = this.bigImg.clientHeight-this.mask.clientHeight

            // 最终设置mask
            this.mask.style.left = w + 'px'
            this.mask.style.top = h + 'px'
        })

    }

    // 设置放大镜宽度
    enlargeSetWH() {
        // 放大镜【盒子尺寸】  = 遮罩层尺寸(黄色) * 放大镜【背景尺寸】 / bigImg盒子尺寸 

        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))
 
        let enlarge = this.getStyle(this.enlarge, 'background-size')  // 800px 800px
        // console.log(enlarge.split(' ')) ["800px", "800px"]
        let enlargeW = parseInt(enlarge.split(' ')[0])
        let enlargeH = parseInt(enlarge.split(' ')[1])

        let bigImgW = parseInt(this.getStyle(this.bigImg, 'width'))
        let bigImgH = parseInt(this.getStyle(this.bigImg, 'height'))

        let w = maskW * enlargeW / bigImgW
        let h = maskH * enlargeH / bigImgH
        
        this.enlarge.style.width = w + 'px'
        this.enlarge.style.height = h + 'px'
    }

    // 获取非行内样式 - 留心:形参就是变量
    getStyle(tagObj, attr) 
    {
        if (window.getComputedStyle)
        {
            // return window.getComputedStyle(标签对象).属性名
            // return window.getComputedStyle(tagObj).attr  // 对象的属性是变量 加中括号
            return window.getComputedStyle(tagObj)[attr]
        } else {
            // return 标签对象.currentStyle.属性名 
            // return tagObj.currentStyle.attr 
            return tagObj.currentStyle[attr]  
        }
    }

    // 鼠标移入到大图上:1-显示遮罩框,2-显示放大镜
    enlargeOverOut() { // this  === 构造函数中this
        // 给大图片增加鼠标移入事件
        // this.el.querySelector('.img').addEventListener('mouseover', function () { // this事件源
        // this.el.querySelector('.img').addEventListener('mouseover', () => { // 父function this
        //     // 1-显示遮罩框,2-显示放大镜
        //     this.el.querySelector('.mask').style.display = 'block'
        //     this.el.querySelector('.enlarge').style.display = 'block'
        // })

        // this.el.querySelector('.img').addEventListener('mouseover', () => {
        //     this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block'
        // }) 

        this.el.querySelector('.img').addEventListener('mouseover', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block') 
        this.el.querySelector('.img').addEventListener('mouseout', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'none') 
    }
}
new Enlarge('.box')
</script>
</body>
</html>

代码-背景同步

  • 目的:根据遮罩框移动距离 同样比例 移动 放大镜
  • 公式
放大镜背景图片移动距离         放大镜盒子尺寸
-----------------     =    ------------
遮罩框移动距离				   遮罩框尺寸


放大镜背景图片移动距离 * 遮罩框尺寸  =   放大镜盒子尺寸  *  遮罩框移动距离


放大镜背景图片移动距离  =   放大镜盒子尺寸  *  遮罩框移动距离  / 遮罩框尺寸


this.enlarge.style.backgroundPosition = `-${left}px -${top}px`

代码

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active">
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li>
            <img src="./imgs/2.small.jpg" alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
class Enlarge
{
    constructor(el)
    {
        // 1. 保存全局信息
        this.el =  document.querySelector(el)
        this.enlarge = this.el.querySelector('.enlarge')
        this.mask = this.el.querySelector('.mask')
        this.bigImg = this.el.querySelector('.img')
        
        // 2. 默认调用
        this.init()
    }
    
    init() {
        // 功能1
        // 功能2
        // 功能3
        // ....
        // 功能n
        this.enlargeOverOut()
        this.enlargeSetWH()
        this.maskMove()
        this.enlargeSetBg()
        // this.smallImgChange()
    }


    // 放大镜背景同步
    enlargeSetBg() 
    {
        // 放大镜背景图片移动距离  =   放大镜盒子尺寸  *  遮罩框移动距离  / 遮罩框尺寸

        let enlargeW = parseInt(this.getStyle(this.enlarge, 'width'))
        let enlargeH = parseInt(this.getStyle(this.enlarge, 'height'))

        let maskLeft = parseInt(this.getStyle(this.mask, 'left'))
        let maskTop = parseInt(this.getStyle(this.mask, 'top'))
        
        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))

        let left = enlargeW * maskLeft / maskW
        let top = enlargeH * maskTop / maskH

        this.enlarge.style.backgroundPosition = `-${left}px -${top}px`
    }

    // 遮罩框移动
    maskMove() {

        // this.bigImg.addEventListener('mousemove', function(e) {
        this.bigImg.addEventListener('mousemove', (e) => {
            // 获取事件对象
            e = e || window.event

            let w = e.pageX - this.el.offsetLeft - this.mask.clientWidth / 2
            let h = e.pageY - this.el.offsetTop - this.mask.clientHeight / 2

            if (w<0) w = 0
            if (h<0) h = 0
            if (w> this.bigImg.clientWidth-this.mask.clientWidth) w = this.bigImg.clientWidth-this.mask.clientWidth
            if (h> this.bigImg.clientHeight-this.mask.clientHeight) h = this.bigImg.clientHeight-this.mask.clientHeight

            // 最终设置mask
            this.mask.style.left = w + 'px'
            this.mask.style.top = h + 'px'

            // 同步显示背景
            this.enlargeSetBg() 
        })

    }

    // 设置放大镜宽度
    enlargeSetWH() {
        // 放大镜【盒子尺寸】  = 遮罩层尺寸(黄色) * 放大镜【背景尺寸】 / bigImg盒子尺寸 

        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))
 
        let enlarge = this.getStyle(this.enlarge, 'background-size')  // 800px 800px
        // console.log(enlarge.split(' ')) ["800px", "800px"]
        let enlargeW = parseInt(enlarge.split(' ')[0])
        let enlargeH = parseInt(enlarge.split(' ')[1])

        let bigImgW = parseInt(this.getStyle(this.bigImg, 'width'))
        let bigImgH = parseInt(this.getStyle(this.bigImg, 'height'))

        let w = maskW * enlargeW / bigImgW
        let h = maskH * enlargeH / bigImgH
        
        this.enlarge.style.width = w + 'px'
        this.enlarge.style.height = h + 'px'
    }

    // 获取非行内样式 - 留心:形参就是变量
    getStyle(tagObj, attr) 
    {
        if (window.getComputedStyle)
        {
            // return window.getComputedStyle(标签对象).属性名
            // return window.getComputedStyle(tagObj).attr  // 对象的属性是变量 加中括号
            return window.getComputedStyle(tagObj)[attr]
        } else {
            // return 标签对象.currentStyle.属性名 
            // return tagObj.currentStyle.attr 
            return tagObj.currentStyle[attr]  
        }
    }

    // 鼠标移入到大图上:1-显示遮罩框,2-显示放大镜
    enlargeOverOut() { // this  === 构造函数中this
        // 给大图片增加鼠标移入事件
        // this.el.querySelector('.img').addEventListener('mouseover', function () { // this事件源
        // this.el.querySelector('.img').addEventListener('mouseover', () => { // 父function this
        //     // 1-显示遮罩框,2-显示放大镜
        //     this.el.querySelector('.mask').style.display = 'block'
        //     this.el.querySelector('.enlarge').style.display = 'block'
        // })

        // this.el.querySelector('.img').addEventListener('mouseover', () => {
        //     this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block'
        // }) 

        this.el.querySelector('.img').addEventListener('mouseover', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block') 
        this.el.querySelector('.img').addEventListener('mouseout', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'none') 
    }
}
new Enlarge('.box')
</script>
</body>
</html>

代码-小图切换

步骤1:获取所有smallImgObjs
步骤2:遍历增加点击事件
步骤3:在事件处理函数中(1-改bigImg,2-放大镜图)

代码

<style>
* { margin: 0; padding: 0; }
img {width: 100%;height: 100%;display: block;}
.box {width: 450px;position: relative;margin: 30px;}
.box > .img {width: 450px;height: 450px;border: 1px solid #333;position: relative;}
.box > .img > .mask {width: 200px;height: 200px;background-color: yellow;opacity: .4;position: absolute;top: 0px;left: 0px;display: none;}
.box > ul {display: flex;list-style:none;margin-top:10px;}
.box > ul > li {width: 54px;height: 54px;border: 1px solid #333;margin-right: 10px;cursor: pointer;}
.box > ul > li.active {border-color: red;}
.box .enlarge {width: 400px;height: 400px;position: absolute;top: 0;left: 101%;background: url(./imgs/1.big.jpg) no-repeat;background-size: 800px 800px;background-position: 0 0;display: none;}
</style>
<body>

<div class="box">
    <div class="img">
        <img src="./imgs/1.jpg" alt="" />
        <div class="mask"></div>
    </div>
    <ul>
        <li class="active" bigImg="1.jpg" enlarge="1.big.jpg" >
            <img src="./imgs/1.small.jpg" alt="">
        </li>
        <li  bigImg="2.jpg" enlarge="2.big.jpg" >
            <img src="./imgs/2.small.jpg"alt="">
        </li>
    </ul>
    <div class="enlarge"></div>
</div>

<script>
class Enlarge
{
    constructor(el)
    {
        // 1. 保存全局信息
        this.el =  document.querySelector(el)
        this.enlarge = this.el.querySelector('.enlarge')
        this.mask = this.el.querySelector('.mask')
        this.bigImg = this.el.querySelector('.img')
        
        // 2. 默认调用
        this.init()
    }
    
    init() {
        // 功能1
        // 功能2
        // 功能3
        // ....
        // 功能n
        this.enlargeOverOut()
        this.enlargeSetWH()
        this.maskMove()
        this.enlargeSetBg()
        this.smallImgChange()
    }

    // 1. 获取所有小图 遍历绑定 点击事件
    // 2. 事件处理函数中
    //    2.1 移除所有class 给自己加
    //    2.2 大图换
    //    2.3 放大镜换
    smallImgChange()
    {
        let _this = this
        let liObjs = this.el.querySelectorAll('ul li')
        liObjs.forEach((liObj, liIndex) => {
            liObj.addEventListener('click', function() {
                //    2.1 移除所有class 给自己加
                liObjs.forEach((item) => {
                    item.removeAttribute('class')
                })
                this.setAttribute('class', 'active')
                //    2.2 大图换
                _this.bigImg.querySelector('img').src = './imgs/' + this.getAttribute('bigImg')
                //    2.3 放大镜换
                _this.enlarge.style.background = 'url(./imgs/'+this.getAttribute('enlarge')+') no-repeat'
            })
        })
    }

    // 放大镜背景同步
    enlargeSetBg() 
    {
        // 放大镜背景图片移动距离  =   放大镜盒子尺寸  *  遮罩框移动距离  / 遮罩框尺寸

        let enlargeW = parseInt(this.getStyle(this.enlarge, 'width'))
        let enlargeH = parseInt(this.getStyle(this.enlarge, 'height'))

        let maskLeft = parseInt(this.getStyle(this.mask, 'left'))
        let maskTop = parseInt(this.getStyle(this.mask, 'top'))
        
        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))

        let left = enlargeW * maskLeft / maskW
        let top = enlargeH * maskTop / maskH

        this.enlarge.style.backgroundPosition = `-${left}px -${top}px`
    }

    // 遮罩框移动
    maskMove() {

        // this.bigImg.addEventListener('mousemove', function(e) {
        this.bigImg.addEventListener('mousemove', (e) => {
            // 获取事件对象
            e = e || window.event

            let w = e.pageX - this.el.offsetLeft - this.mask.clientWidth / 2
            let h = e.pageY - this.el.offsetTop - this.mask.clientHeight / 2

            if (w<0) w = 0
            if (h<0) h = 0
            if (w> this.bigImg.clientWidth-this.mask.clientWidth) w = this.bigImg.clientWidth-this.mask.clientWidth
            if (h> this.bigImg.clientHeight-this.mask.clientHeight) h = this.bigImg.clientHeight-this.mask.clientHeight

            // 最终设置mask
            this.mask.style.left = w + 'px'
            this.mask.style.top = h + 'px'

            // 同步显示背景
            this.enlargeSetBg() 
        })

    }

    // 设置放大镜宽度
    enlargeSetWH() {
        // 放大镜【盒子尺寸】  = 遮罩层尺寸(黄色) * 放大镜【背景尺寸】 / bigImg盒子尺寸 

        let maskW = parseInt(this.getStyle(this.mask, 'width'))
        let maskH = parseInt(this.getStyle(this.mask, 'height'))
 
        let enlarge = this.getStyle(this.enlarge, 'background-size')  // 800px 800px
        // console.log(enlarge.split(' ')) ["800px", "800px"]
        let enlargeW = parseInt(enlarge.split(' ')[0])
        let enlargeH = parseInt(enlarge.split(' ')[1])

        let bigImgW = parseInt(this.getStyle(this.bigImg, 'width'))
        let bigImgH = parseInt(this.getStyle(this.bigImg, 'height'))

        let w = maskW * enlargeW / bigImgW
        let h = maskH * enlargeH / bigImgH
        
        this.enlarge.style.width = w + 'px'
        this.enlarge.style.height = h + 'px'
    }

    // 获取非行内样式 - 留心:形参就是变量
    getStyle(tagObj, attr) 
    {
        if (window.getComputedStyle)
        {
            // return window.getComputedStyle(标签对象).属性名
            // return window.getComputedStyle(tagObj).attr  // 对象的属性是变量 加中括号
            return window.getComputedStyle(tagObj)[attr]
        } else {
            // return 标签对象.currentStyle.属性名 
            // return tagObj.currentStyle.attr 
            return tagObj.currentStyle[attr]  
        }
    }

    // 鼠标移入到大图上:1-显示遮罩框,2-显示放大镜
    enlargeOverOut() { // this  === 构造函数中this
        // 给大图片增加鼠标移入事件
        // this.el.querySelector('.img').addEventListener('mouseover', function () { // this事件源
        // this.el.querySelector('.img').addEventListener('mouseover', () => { // 父function this
        //     // 1-显示遮罩框,2-显示放大镜
        //     this.el.querySelector('.mask').style.display = 'block'
        //     this.el.querySelector('.enlarge').style.display = 'block'
        // })

        // this.el.querySelector('.img').addEventListener('mouseover', () => {
        //     this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block'
        // }) 

        this.el.querySelector('.img').addEventListener('mouseover', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'block') 
        this.el.querySelector('.img').addEventListener('mouseout', () => this.el.querySelector('.mask').style.display = this.el.querySelector('.enlarge').style.display = 'none') 
    }
}
new Enlarge('.box')
</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值