以任一點 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); };