知识回顾
语法概念
原型: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>