这几天有空研究了一下图片定点缩放。做的过程中才发现很多坑,记录一下。
思路
- 首先要定放缩坐标原点,这里有容器原点与图片中心点两个坐标系,任取其一即可,以下采用的是图片中心点。
- 基本实现思路是将图片先移动到某个位置,放缩前后鼠标位置能刚好重叠。
- 计算关键变量:
js
ratio: 当前放缩倍数 / 上一次放缩倍数
xOffset,yOffset: 放缩后坐标点 - 放缩前坐标点,需注意坐标系转化
- 缩放后计算变量并应用于transform 。
(code.juejin.cn/pen/7304582...)
一、确定放缩坐标系
1.使用容器坐标系
需更改图片css属性transform-origin: 0 0,计算偏移时需将鼠标坐标转为以图片左上角坐标系为准的数据。
js
const changeToBoxOrigin = (x, y) => {
let imgRect = imgDom.getBoundingClientRect();
let imgCenterX = imgRect.left; // 如容器不在左上角,得减去容器坐标
let imgCenterY = imgRect.top;
return { x: x - imgCenterX, y: y - imgCenterY}
}
2.使用图片中心点
计算偏移时将坐标系转为以图片中心点为准的数据。
js
const changeToImageOrigin = (x, y) => {
let imgRect = imgDom.getBoundingClientRect();
let imgCenterX = imgRect.left + imgRect.width / 2; // 如容器不在左上角,得减去容器坐标
let imgCenterY = imgRect.top + imgRect.height / 2;
return { x: x - imgCenterX, y: y - imgCenterY}
}
二、确定本次移动偏移量
暂时抛开偏移变化。以图片中心点缩放。 则水平方向的偏移距离是x2-x1,x2 = x1 * ratio,由此推理水平方向偏移量xOffset = x1 * (ratio - 1) 同理可得出yOffset = y1 * (ratio - 1)。

那么x1,x2坐标如何获取呢。从mouseEvent中可以获取鼠标相对于容器的坐标x, y,经由坐标转化函数changeToImageOrigin即可获取到x1,y1。
三、组合数据并应用
这里需注意transform变化顺序,先平移,后缩放
js
const scale = ref(1)
const _offset = [0, 0]
const _scale = (s, event) => {
let x = event.x, y = event.y;
let { x: x1, y: y1 } = changeToImageOrigin(x, y);
let ratio = s / scale.value;
let xOffset = x1 * (ratio - 1);
let yOffset = y1 * (ratio - 1);
scale.value = s;
// 设置style
imgDom.style = `
transform: translate(${_offset[0] + xOffset}px, ${_offset[1] + yOffset}px) scale(${s})
`
}