功能背景
- 实现以鼠标在图中的位置为中心进行图片的滚轮缩放,现在是无论鼠标位置在哪都以图片中心进行缩放,这不符合预期;
关键点
- 缩放前鼠标在的位置是 A(clinetX,clientY) 点,缩放后鼠标的位置是 A’(x2,y2)点,为了保持鼠标位置不变,需要将A’平移到A, 就需要计算出disx的距离,即偏移量;
- 绿色代表:缩小后的图片;
- 黄色代表:原始图片;
所以需平移+缩放。
主要步骤:
- 监听图片mousewheel事件 计算scale:
- 鼠标滚轮事件event.deltaY< 0 ,滚轮向上滚,放大;
- 根据当前scale,preScale,clientx ,clienty,计算出偏移量(disx),用上一次的位置 - 计算出新旧之间的相对偏移量 (disx)= 最新的位置(x,y);
- 保存新计算得出的位置,以便后续计算;
- 根据上式得出新的scale,x,y进行transform;
缩放比例n:
n
=
w
i
d
t
h
1
w
i
d
t
h
=
s
c
a
l
e
p
r
e
S
c
a
l
e
n =\frac{width_1}{width}=\frac{scale}{preScale}
n=widthwidth1=preScalescale
已知:
w
i
d
t
h
1
=
n
∗
w
i
d
t
h
width_1 = n*width
width1=n∗width
(
x
2
−
x
′
)
=
(
c
l
i
e
n
t
x
−
x
)
n
(x_2 - x') = (clientx-x)n
(x2−x′)=(clientx−x)n
由图可知:
d
i
s
x
=
(
w
i
d
t
h
−
w
i
d
t
h
1
)
2
+
(
x
2
−
x
′
)
−
(
c
l
i
e
n
t
x
−
x
)
disx = \frac{(width-width_1)}{2} + (x_2 - x') - (clientx - x)
disx=2(width−width1)+(x2−x′)−(clientx−x)
联立上面两式可得:
d
i
s
x
=
(
w
i
d
t
h
−
n
∗
w
i
d
t
h
)
2
+
(
c
l
i
e
n
t
x
−
x
)
n
−
(
c
l
i
e
n
t
x
−
x
)
disx = \frac{(width-n*width)}{2} +(clientx-x)n - (clientx - x)
disx=2(width−n∗width)+(clientx−x)n−(clientx−x)
可简化为:
d
i
s
x
=
(
1
−
n
)
(
w
i
d
t
h
2
−
c
l
i
e
n
t
x
+
x
)
disx = (1-n)(\frac{width}{2} -clientx+x)
disx=(1−n)(2width−clientx+x)
y同理可得
handleMousewheel: debounce(function(event) {
event.preventDefault();
let { deltay,clientX,clienty }=event;
const isZoomout = deltaY<0;//小于0放大
let scale = this.getNewSacle(this.prescale,isZoomOut);// 计算此次缩放比例
this.handleZoomImg(this.scale,this.preScale,clientx,clientY);//根据新,旧比例,鼠标位置 进行图片调整
this.preScale = scale;
}
200)
methods: {
getNewSacle(preScale,isZoomout){
if(isZoomout){
return preScale*1.1;
} else return preScale /1.1;
},
handleZoomImg(scale,preScale,clientX,clienty) {
let {x: oX, y: oY}=this.lastSite;
let n = scale / preScale;
let img = this.$refs.image; // 图片dom
let { x:x1,y:y1,width, height }=img.getBoundingclientRect();
// 带入上面得到的算式, x,y减去偏移量就是新的位置
oX-= (1-n)*(width/2-clientX + x1);
oY-= (1-n)*(height/2-clientY + y1);
this.lastSite={
x: oX,
y: oY
}
this.updateDom(resScale, oX, oY);
},
updateDom(scale,x,y){
this.$refs.image.style.transform = `matrix(${scale},,θ,${scale},${x}, ${y})`,
}
注意:updateDom方法里,如果使用translate和scale要先写translate再scale