鼠标位置缩放图片

这几天有空研究了一下图片定点缩放。做的过程中才发现很多坑,记录一下。

思路

  1. 首先要定放缩坐标原点,这里有容器原点与图片中心点两个坐标系,任取其一即可,以下采用的是图片中心点。
  2. 基本实现思路是将图片先移动到某个位置,放缩前后鼠标位置能刚好重叠。
  3. 计算关键变量:
js 复制代码
    ratio: 当前放缩倍数 / 上一次放缩倍数
    xOffset,yOffset: 放缩后坐标点 - 放缩前坐标点,需注意坐标系转化
  1. 缩放后计算变量并应用于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})
    `
}
相关推荐
右耳朵猫AI几秒前
前端周刊2026W22 | React 13周年、TanStack Router、Deno 2.8、Node.js 26、npm 分阶段发布
前端·react.js·node.js
scan7241 分钟前
从runtime获取信息
java·服务器·前端
木头羊oll6 分钟前
Uniapp 与 H5 在 App 端的交互
前端·javascript·html
可别39014 分钟前
Vue 极简实现语音实时转写(录音转文字,低网络依赖、开箱即用)
前端·javascript·vue.js
阿猫的故乡20 分钟前
Vue插槽从入门到项目实战:默认插槽、具名插槽、作用域插槽,一次讲明白
前端·javascript·vue.js
SEO-狼术20 分钟前
Build Interactive Maps Crack
前端
小则又沐风a23 分钟前
进程最终篇---进程控制(模拟实现xshell)
java·linux·服务器·前端
Invictus_cl32 分钟前
条纹圆形进度条(彩虹色)
开发语言·前端·javascript
excel1 小时前
从封装到继承:深入理解 TypeScript 类中的 public、private、protected、static
前端
向日的葵0061 小时前
vue3路由的replace属性(四)
前端·javascript·vue.js·vue路由