以任一点 A 缩放的基本原理:this
A 点为鼠标位置,正常放大是以原点放大,那么放大后 A 点就会变到 A1 点的位置 x1, y1。而后再将画布进行位移,将 A1 的位置移动到 A,则完成以 A 点缩放的功能。spa
代码示例:code
this.scale 是当前缩放比例,this.offsetX, this.offsetY 是当前原点位移距离,step 是每次缩放的增量blog
if (wheelDelta > 0) { // 放大 if (this.scale < max) { // 缩放值小于设定的最大值,则能够继续放大 this.scale += step; // 累加后 this.scale 为放大后的缩放值 if (this.scale > max) { // 越界处理 this.scale = max; } this.painter.scale(this.scale); // 进行缩放 // 要根据鼠标位置缩放,则要在缩放后再次移动,将缩放点的位置移动到鼠标位置 const x = e.offsetX; const y = e.offsetY; offsetX = (x - this.offsetX) * this.scale / (this.scale - step) - (x - this.offsetX); offsetY = (y - this.offsetY) * this.scale / (this.scale - step) - (y - this.offsetY); this.move(-offsetX, -offsetY); }
为何是 x - this.offsetX?由于代码中,当画布左移后,this.offsetX 是负数,因此使用减号获得的才是正确的坐标。io
this.scale / (this.scale - step) 是缩放后的缩放值除以缩放前的缩放值,获得缩放率。class
this.move() 对画布进行移动,并累加 this.offsetX 和 this.offsetY原理
化简得:im
const move = (e) => { const x = e.offsetX - this.offsetX; // 鼠标位置换算到相对原点的坐标 const y = e.offsetY - this.offsetY; const offsetX = x * (this.scale - preScale) / preScale; // x * 绝对缩放率 获得位移 const offsetY = y * (this.scale - preScale) / preScale; this.move(-offsetX, -offsetY); };