zoom1.vue
<template>
<div id="zoomBox" :style="getStyleStr">
<div id="small-box">
<div id="float-box"></div>
<img :style="getStyleStr" :src="minImgUrl" />
</div>
<div id="big-box" :style="getStyleStr">
<img class="maxImg" :style="`width: ${boxWidth}px`" :src="maxImgUrl" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
objZoomBox: null,
objSmallBox: null,
objFloatBox: null,
objBigBox: null,
objBigBoxImg: null,
nowSacle: null,
};
},
props: {
// 缩放比列
sacle: {
type: Number,
default: 1.5,
},
// 最大缩放比例
maxSacle: {
type: Number,
default: 3,
},
// 最小缩放比例
minSacle: {
type: Number,
default: 1,
},
// 盒子宽
boxWidth: {
type: Number,
default: 343,
},
// 盒子高
boxHeight: {
type: Number,
default: 430,
},
// 图片地址
minImgUrl: {
type: String,
default:
'https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
},
// 图片地址
maxImgUrl: {
type: String,
default:
'https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
},
},
computed: {
getStyleStr() {
return `width: ${this.boxWidth}px; height: ${this.boxHeight}px`;
},
},
mounted() {
this.nowSacle = this.sacle;
//找五个个元素:demo,smallBox,foatBox,bigfloatBox,imgs,
const objZoomBox = document.getElementById('zoomBox');
const objSmallBox = document.getElementById('small-box');
const objFloatBox = document.getElementById('float-box');
const objBigBox = document.getElementById('big-box');
const objBigBoxImg = document.querySelector('.maxImg');
const _this = this;
this.objZoomBox = objZoomBox;
this.objSmallBox = objSmallBox;
this.objFloatBox = objFloatBox;
this.objBigBox = objBigBox;
this.objBigBoxImg = objBigBoxImg;
//给小盒子添加事件,移入和移出
//移入:浮动的box和和bigBox显示
objZoomBox.onmouseover = function () {
objFloatBox.style.display = 'block';
objBigBox.style.display = 'block';
_this.changeImgWidth();
};
//移除:浮动的box和bigBox隐藏
objZoomBox.onmouseout = function () {
objFloatBox.style.display = 'none';
objBigBox.style.display = 'none';
objBigBoxImg.style.width = objZoomBox.clientWidth + 'px';
_this.changeImgWidth(true);
};
// 鼠标滑动事件
objZoomBox.onmousewheel = function (event) {
if (event.deltaY < 0) {
_this.nowSacle += 0.05;
} else {
_this.nowSacle -= 0.05;
}
if (_this.nowSacle < _this.minSacle) {
_this.nowSacle = _this.minSacle;
}
if (_this.nowSacle > _this.maxSacle) {
_this.nowSacle = _this.maxSacle;
}
_this.changeImgWidth();
event.preventDefault();
};
//给小盒子添加鼠标移动事件
objZoomBox.onmousemove = function (ev) {
_this.setSize(ev);
};
},
methods: {
// 改变放大图片的大小
changeImgWidth(notRender) {
const { objZoomBox, objBigBoxImg, nowSacle } = this;
if (!notRender) {
const demoWidth = objZoomBox.clientWidth;
objBigBoxImg.style.width = demoWidth * nowSacle + 'px';
this.setSize(event);
}
},
// 设置放大图片数据
setSize(ev) {
const { objZoomBox, objSmallBox, objFloatBox, objBigBox, objBigBoxImg } = this;
const _event = ev || window.event; //做兼容性,兼容IE
//1计算当前坐标值 = 鼠标距离屏幕左边的距离 - 当前盒子距离距离屏幕左边的距离 - 浮动盒子的一半
const zoomBoxLeft = objZoomBox.getBoundingClientRect().left;
const zoomBoxTop = objZoomBox.getBoundingClientRect().top;
let left = _event.clientX - zoomBoxLeft - objFloatBox.offsetWidth / 2;
let top = _event.clientY - zoomBoxTop - objFloatBox.offsetHeight / 2;
//5.优化,在前面加判断,不让其溢出,加判断
if (left < 0) left = 0;
if (top < 0) top = 0;
if (left > objSmallBox.offsetWidth - objFloatBox.offsetWidth) {
left = objSmallBox.offsetWidth - objFloatBox.offsetWidth;
}
if (top > objSmallBox.offsetHeight - objFloatBox.offsetHeight)
top = objSmallBox.offsetHeight - objFloatBox.offsetHeight;
//2把值赋值给放大镜
objFloatBox.style.left = left + 'px';
objFloatBox.style.top = top + 'px';
//3计算比例
const percentX = left / (objSmallBox.offsetWidth - objFloatBox.offsetWidth);
const percentY = top / (objSmallBox.offsetHeight - objFloatBox.offsetHeight);
//4利用这个比例计算距离后赋值给右侧的图片
objBigBoxImg.style.left = -percentX * (objBigBoxImg.offsetWidth - objBigBox.offsetWidth) + 'px';
objBigBoxImg.style.top = -percentY * (objBigBoxImg.offsetHeight - objBigBox.offsetHeight) + 'px';
},
},
};
</script>
<style>
* {
margin: 0;
padding: 0;
}
#zoomBox {
display: block;
margin: 5px;
position: relative;
border: 1px solid #ccc;
}
#small-box {
position: relative;
z-index: 1;
}
/* #small-box img {
width: 343px;
height: 430px;
} */
#float-box {
display: none;
width: 160px;
height: 120px;
position: absolute;
background: #ffffcc;
border: 1px solid #ccc;
filter: alpha(opacity=50);
opacity: 0.5;
}
#big-box {
display: none;
position: absolute;
top: 0;
left: 0px;
/* width: 343px;
height: 430px; */
overflow: hidden;
border: 1px solid #ccc;
z-index: 10;
cursor: crosshair;
}
#big-box img {
display: inline-block;
/* width: 343px; */
position: absolute;
z-index: 5;
max-width: inherit;
}
</style>
zoom2.vue
<template>
<div id="moveBox" :style="`width: ${boxWidth}px`">
<div id="mirror">
<img :src="maxImgUrl" class="maxImg2" />
</div>
<div id="pic">
<img :style="`width: ${boxWidth}px`" :src="minImgUrl" class="nowImg" />
</div>
</div>
</template>
<script>
export default {
props: {
boxWidth: {
type: Number,
default: 323,
},
sacle: {
type: Number,
default: 3,
},
// 最大缩放比例
maxSacle: {
type: Number,
default: 3,
},
// 最小缩放比例
minSacle: {
type: Number,
default: 1,
},
// 图片地址
minImgUrl: {
type: String,
default:
'https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
},
// 图片地址
maxImgUrl: {
type: String,
default:
'https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
},
},
data() {
return {
nowSacle: null,
mirror: null,
moveBox: null,
nowImg: null,
maxImg2: null,
};
},
mounted() {
this.nowSacle = this.sacle;
this.$nextTick(() => {
const mirror = document.querySelector('#mirror');
const moveBox = document.querySelector('#moveBox');
const nowImg = document.querySelector('.nowImg');
const maxImg2 = document.querySelector('.maxImg2');
const _this = this;
this.mirror = mirror;
this.moveBox = moveBox;
this.nowImg = nowImg;
this.maxImg2 = maxImg2;
moveBox.onmousemove = function (e) {
const ev = e ? e : window.event;
mirror.style.display = 'block';
_this.moving(ev);
};
moveBox.onmouseout = function () {
mirror.style.display = 'none';
};
moveBox.onmouseover = function () {
mirror.style.display = 'block';
};
maxImg2.onmousewheel = function (event) {
if (event.deltaY < 0) {
_this.nowSacle += 0.05;
} else {
_this.nowSacle -= 0.05;
}
if (_this.nowSacle < _this.minSacle) {
_this.nowSacle = _this.minSacle;
}
if (_this.nowSacle > _this.maxSacle) {
_this.nowSacle = _this.maxSacle;
}
_this.moving(event);
// 放大图片宽度
event.preventDefault();
};
});
},
methods: {
moving(e) {
const { mirror, nowImg, maxImg2, nowSacle } = this;
const nowImgLeft = nowImg.getBoundingClientRect().left;
const nowImgTop = nowImg.getBoundingClientRect().top;
const mirrorWidth = mirror.offsetWidth;
const mirrorHeight = mirror.offsetHeight;
const nowImgWidth = nowImg.offsetWidth;
const nowImgHeight = mirror.offsetHeight;
const picWidth = document.querySelector('.nowImg').offsetWidth;
const picHeight = document.querySelector('.nowImg').offsetHeight;
// 鼠标距离
const x = e.clientX - nowImgLeft;
const y = e.clientY - nowImgTop;
const _this = this;
/**(当前x位置 - 放大镜盒子一半) / 当前图片宽度 <这一步操作得到位置与盒子宽度的比例>
* 用刚才得到的比例 * (当前图片的宽度 * 缩放比例) <得到放大后的盒子的大概位置>
* 因为放大镜也有宽度,用刚才得到的值 + 放大镜的一半 * (放大倍数 - 1) <得到最后放大图片的准确x位置,y位置同理>
*/
const maxImgX =
((x - mirrorWidth / 2) / nowImgWidth) * nowImgWidth * nowSacle + (mirrorWidth / 2) * (nowSacle - 1);
const maxImgY =
((y - mirrorHeight / 2) / nowImgHeight) * nowImgHeight * nowSacle + (mirrorHeight / 2) * (nowSacle - 1);
// 放大图片宽度
maxImg2.style.width = nowImg.clientWidth * nowSacle + 'px';
if (Math.floor(x) === nowImgWidth || Math.floor(x) <= 0) {
mirror.style.display = 'none';
}
// 左边缘限制
if (x - mirrorWidth / 2 < 0 && y - mirrorHeight / 2 > 0 && y + mirrorHeight / 2 < picHeight) {
mirror.style.left = 0 + 'px';
maxImg2.style.top = -maxImgY + 'px';
mirror.style.top = y - mirrorHeight / 2 + 'px';
}
// 上边缘限制
if (y - mirrorHeight / 2 < 0 && x - mirrorWidth / 2 > 0 && x + mirrorWidth / 2 < picWidth) {
mirror.style.top = 0 + 'px';
maxImg2.style.left = -maxImgX + 'px';
mirror.style.left = x - mirrorWidth / 2 + 'px';
if (x - mirrorWidth / 2 < 0) {
mirror.style.left = 0 + 'px';
}
}
// 右边缘限制
if (x + mirrorWidth / 2 > picWidth && y + mirrorHeight / 2 < picHeight && y - mirrorHeight / 2 > 0) {
mirror.style.left = picWidth - mirrorWidth + 'px';
maxImg2.style.top = -maxImgY + 'px';
mirror.style.top = y - mirrorHeight / 2 + 'px';
}
// 下边缘限制
if (y + mirrorHeight / 2 > picHeight && x + mirrorWidth / 2 < picWidth && x - mirrorWidth / 2 > 0) {
mirror.style.top = picHeight - mirrorHeight + 'px';
maxImg2.style.left = -maxImgX + 'px';
mirror.style.left = x - mirrorWidth / 2 + 'px';
}
if (x <= picWidth && y <= picHeight && x >= -picWidth && y >= -picHeight) {
_this.changePosition(x, y);
}
},
changePosition(x, y) {
const { mirror, nowImg, maxImg2, nowSacle } = this;
// 放大镜宽
const mirrorWidth = mirror.offsetWidth;
// 放大镜高
const mirrorHeight = mirror.offsetHeight;
const nowImgWidth = nowImg.offsetWidth;
const nowImgHeight = mirror.offsetHeight;
const picWidth = document.querySelector('.nowImg').offsetWidth;
const picHeight = document.querySelector('.nowImg').offsetHeight;
if (
x + mirrorWidth / 2 < picWidth + 50 * nowSacle &&
y + mirrorWidth / 2 < picHeight + 50 * nowSacle &&
x - mirrorWidth / 2 > 0 - 50 * nowSacle &&
y - mirrorWidth / 2 > 0 - 50 * nowSacle
) {
// mirror 放大镜
mirror.style.left = x - mirrorWidth / 2 + 'px';
mirror.style.top = y - mirrorHeight / 2 + 'px';
// const maxImgX = (x - 55) / 323 * 323 * nowSacle + 55 * (nowSacle - 1)
// const maxImgY = (y - 55) / 430 * 430 * nowSacle + 55 * (nowSacle - 1)
const maxImgX =
((x - mirrorWidth / 2) / nowImgWidth) * nowImgWidth * nowSacle + (mirrorWidth / 2) * (nowSacle - 1);
const maxImgY =
((y - mirrorHeight / 2) / nowImgHeight) * nowImgHeight * nowSacle + (mirrorHeight / 2) * (nowSacle - 1);
// 大图
maxImg2.style.left = -maxImgX + 'px';
maxImg2.style.top = -maxImgY + 'px';
}
},
},
};
</script>
<style>
body * {
margin: 0;
padding: 0;
}
#moveBox {
position: relative;
}
#mirror {
position: absolute;
overflow: hidden;
height: 100px;
width: 100px;
/* border: 5px black solid; */
cursor: crosshair;
display: none;
}
.maxImg2 {
position: absolute;
max-width: inherit;
}
</style>