canvasのお絵描きツールに拡大機能をつけてみる

久々にcanvasのお絵描きツールに機能を追加してみた。今回追加した機能は拡大機能。

最初は、拡大画像用のcanvasを新たに作成してそこにdrawImageメソッドを使って、拡大した部分を描画し、終わったらその拡大画像用のcanvasを逆にdrawImageメソッドで元のcanvasに描画したらいけるかなぁ・・・。なんて思っていたのですが、どうにもそのやり方に少し抵抗があってなかなか手につけられずにいました。『canvas 拡大』と検索するとcanvasのtransformメソッドについてでてきましたが、何か違う気がします。あくまで今から描画する図形に対しての指定みたいなので。

ただ、transformという単語をみてふと思いました。そういえば、CSS3にtransformというプロパティがあったよな・・・と(参考:transform – CSS | MDN)。

結論からいうと、このtransformプロパティを使ってお絵描きツールの拡大機能を実装することができました。というわけで、以下そのソースコードの説明。

とりあえず、今までcanvas部分にはボーダーをつけていたのですが、transformで拡大するとボーダーまで拡大してしまうので、divタグで囲んでそのdivタグにボーダーをつけることに。

HTML <div id="CanvasDiv"> <canvas width="400" height="200" id="mycanvas"> Canvasに対応したブラウザを用意してください。 </canvas> </div> CSS

#CanvasDiv{
    border: 10px solid #999;
    cursor:crosshair;
    width:400px;
    height:200px;
    float:left;
    overflow: hidden;
}
#mycanvas{
    -moz-transform-origin:0 0;
    -ms-transform-origin:0 0;
    -webkit-transform-origin:0 0;
    transform-origin:0 0;
}

また、canvasを拡大するとdivタグからはみ出して表示されてしまうので、overflowプロパティをhiddenにして拡大してはみ出した部分は非表示とすることに。そして、transform-originプロパティで拡大するときの原点を要素の左上に指定しています(参考:transform-origin – CSS | MDN)。

つづいてメインの拡大機能の実装部分。拡大機能にはラジオボタン選択ではなく、Hammer.jsを使ってダブルクリック(もしくはダブルタップ)すると2倍に拡大することにしました。

JavaScript

// ダブルタップ(ダブルクリック)で二倍に拡大
Hammer($('#mycanvas')[0]).on("doubletap", function(e){
    scaleFactor = 3 - scaleFactor; // 2なら1、1なら2
    //console.log("scaleFactor:" + scaleFactor);
    if(scaleFactor === 2){
        var topLeftX = e.gesture.center.pageX - $(this).offset().left -(canvas.width/4);
        var topLeftY = e.gesture.center.pageY - $(this).offset().top -(canvas.height/4);
        if(topLeftX < 0){
            topLeftX = 0;
        }else if(topLeftX > canvas.width/2){
            topLeftX = canvas.width/2;
        }
        if(topLeftY < 0){
            topLeftY = 0;
        }else if(topLeftY > canvas.height/2){
            topLeftY = canvas.height/2;
        }

        var transformStyle = 'scale(%{scale}) translate(%{tx}px, %{ty}px)';
        transformStyle = transformStyle.replace('%{scale}', scaleFactor);
        transformStyle = transformStyle.replace('%{tx}', -topLeftX);
        transformStyle = transformStyle.replace('%{ty}', -topLeftY);
        //console.log("transformStyle:" + transformStyle);
        $(this).css('transform', transformStyle);


    }else{
        $(this).css('transform', '');
    }
});

これで拡大はうまくいきました。scaleFactorという変数が拡大率を表しています。もう一度ダブルクリックすると元の大きさに戻るようにもしています。

ただ、これだと拡大した後に描画しようとすると、ペン先の位置が右下にズレてしまうので、描画のx座標とy座標をscaleFactorで除算することに。

x = thisX - $(this).offset().left - borderWidth;
y = thisY - $(this).offset().top - borderWidth;
x /= scaleFactor;
y /= scaleFactor;

以下、動作サンプル。
canvasを使ったお絵描き投稿システム

拡大するときには『塗りつぶし』ではなく、『ペン』を選ぶようにしてください。塗りつぶしを選んでいる状態だとおかしな動きになりました(いまさらだけど、やっぱり普通にラジオボタンで『拡大』を増やしてそこで拡大するかどうかを判定すればよかったかもしれない)。

今回作った機能はcanvasの拡大だけではなく、画像の拡大なんかにも利用できそうです。縮小した画像を表示させといて、ダブルクリックするとその位置を拡大するというような動きにしたり(試してませんが)。

コメント

タイトルとURLをコピーしました