FabricJS

【JavaScript】【Fabric.js】コントロールキーとマウスホイール操作でキャンバスを拡大縮小する

キャンバスは拡大縮小する際に、マウスの現在地を拡大縮小の原点として設定できると、拡大縮小の利用幅が大きく広がる。

拡大縮小の原点にマウスポインタを置いておく必要があるため、拡大縮小操作には、マウスホイール等を使うことになる。

検知するイベントとしてはマウスホイールだけでも可能だが、今回はCtrlキー+マウスホイール操作を検知で拡大縮小を行う。

コントロールキー操作の検知処理

コントロールキーが押下された状態かどうかを判別する。

var ctrlFlg = false;
/**
 * keyDownFunc
 * キーボード押下時に呼び出される処理
 */
function keyDownFunc(e){
    //コントロールキー
    ctrlFlg = e.ctrlKey;    //ctrlキーが押下された場合、trueが設定される。
}

/**
 * keyUpFunc
 * キーボードを離した時に呼び出される処理
 */
function keyUpFunc(e){
    //コントロールキー
    ctrlFlg = e.ctrlKey;    //ctrlキーが離された場合、falseが設定される。
}

document.addEventListener("keydown", keyDownFunc);
document.addEventListener("keyup", keyUpFunc);
この例だけだと、keydown時もkeyup時も同じ関数を呼び出して問題ないが、他のキー操作処理も入ってくると、別々の処理を行うことが多いので分けておく。

マウスホイール操作の検知処理

マウスホイール操作のイベントリスニングは、canvas.onのmouse:wheelで行う。

function load(){
  canvas = new fabric.Canvas('canvas');
  //キャンバス上でのマウスホイール操作をハンドリングする
  canvas.on('mouse:wheel', function(e) { mousewheel(e); });

  window.addEventListener('DOMContentLoaded', load, false);
}

 

 

ブラウザのマウスホイール操作による拡大縮小の抑止

ctrlキー+マウスホイール操作によるブラウザ自体の拡大縮小は、今回の処理と操作が被るため、抑止しておく。

抑止方法は以下の記事を参照。

https://max999blog.com/javascript-chrome-prevent-ctrl-mousewheel-zoom/

キャンバスの拡大縮小処理

キャンバス上でCtrlキー+マウスホイール操作が行われた場合に、マウス位置を原点としてキャンバスの拡大縮小を行う。

function mousewheel(e) {
    if(ctrlFlg) {
        //ポインタの位置取得
        const mouseX = e.pointer.x;
        const mouseY = e.pointer.y;

        //ホイール回転の取得
        const deltaY = e.e.wheelDeltaY;

        //現在の拡大倍率の取得
        let zoom = canvas.getZoom();

        //マウス位置を原点として拡大縮小
        canvas.zoomToPoint(new fabric.Point(mouseX, mouseY), zoom + deltaY/1200 );
    }
}

wheelDeltaY / 1200 で0.1倍ずつ拡大縮小が可能となる。

ちなみに、setZoom(倍率)を使用した場合、キャンバスの左上(x = 0, y = 0)を原点として拡大縮小をすることになるが、動作としては、setZoom内で

 

zoomToPoint( new fabric.Point(0, 0), 倍率); を実行している模様。

function load(){
  canvas = new fabric.Canvas('canvas');
  //キャンバス上でのマウスホイール操作をハンドリングする
  canvas.on('mouse:wheel', function(e) { mousewheel(e); });

  window.addEventListener('DOMContentLoaded', load, false);
}​