web-dev-qa-db-ja.com

キャンバスでズーム

テストアプリケーションでは、単純な長方形のキャンバスがあります。メソッドdrawは100msごとに呼び出されます。

コードからわかるように、私はMousewheelを使用してすべてをスケーリングしています。ここで何が起こるかというと、すべてがスケーリングされますが、つまり、長方形が10px、10pxにあり、その真上にマウスがある場合、スケーリング後、長方形はマウスの下にありません。 (もちろん、すべてのユニットがスケールアップされているので、これは正しいです。

しかし、私がしたいのは、マウスの位置がグーグルマップのように「ズームアクションの中心」であるため、スケーリング前はマウスの下にあり、その後もマウスの下にあるコンテンツです。私は翻訳を何度か試みましたが、それを行う方法がわかりません。

前もって感謝します。

これが私のコードです:

 <script type="text/javascript">
        var scroll = 0;
        var scale = 1.0;


                    /** This is high-level function.
         * It must react to delta being more/less than zero.
         */
        function handle(delta) {

                var canvas = document.getElementById("myCanvas");
                var ctx = canvas.getContext("2d");

                scroll = delta;
                if(scroll > 0)
                {
                    scale += 0.2;
                }
                if(scroll < 0)
                {
                    scale -= 0.2;
                }


        }

        /** Event handler for mouse wheel event.
         */
        function wheel(event){
                var delta = 0;
                if (!event) /* For IE. */
                        event = window.event;
                if (event.wheelDelta) { /* IE/Opera. */
                        delta = event.wheelDelta/120;
                } else if (event.detail) { /** Mozilla case. */
                        /** In Mozilla, sign of delta is different than in IE.
                         * Also, delta is multiple of 3.
                         */
                        delta = -event.detail/3;
                }
                /** If delta is nonzero, handle it.
                 * Basically, delta is now positive if wheel was scrolled up,
                 * and negative, if wheel was scrolled down.
                 */
                if (delta)
                        handle(delta);
                /** Prevent default actions caused by mouse wheel.
                 * That might be ugly, but we handle scrolls somehow
                 * anyway, so don't bother here..
                 */
                if (event.preventDefault)
                        event.preventDefault();
            event.returnValue = false;
        }

        /** Initialization code. 
         * If you use your own event management code, change it as required.
         */
        if (window.addEventListener)
                /** DOMMouseScroll is for mozilla. */
                window.addEventListener('DOMMouseScroll', wheel, false);
        /** IE/Opera. */
        window.onmousewheel = document.onmousewheel = wheel;

        var drawX = 0;
        var drawY = 0;
        var overX = 0;
        var overY = 0;

         function startCanvas()
         {
             var myCanvas = document.getElementById("myCanvas");
             var ctx = myCanvas.getContext("2d");
             ctx.canvas.width  = window.innerWidth;
             ctx.canvas.height = window.innerHeight;                 
             setInterval(draw,100);
         }

         function draw()
         {
            var canvas = document.getElementById("myCanvas");
            var ctx = canvas.getContext("2d");

            ctx.clearRect(0,0,window.innerWidth,window.innerHeight);
            ctx.save();
            ctx.scale(scale,scale);
            ctx.fillRect(drawX,drawY,20,20);
            //ctx.translate(-scale,-scale);
            ctx.restore();
            ctx.font="20pt Arial";  
            ctx.fillText(scale+":"+drawX,0,150);                
         }

         function canvasClick(event)
         {
            console.log(event.layerX+"/"+scale);
            drawX = event.layerX/scale;
            drawY = event.layerY/scale;
         }

         function canvasOver(event)
         {
            console.log("over");
            overX = event.layerX;
            overY = event.layerY;
         }

    </script>
16
Chris

これは実際には重要な数学の質問であり、通常は「ズームポイント」として知られています。

here を見てください。別のキャンバスユーザーが同じことをしたいと思って、方法を見つけました。

<canvas id="canvas" width="800" height="600"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var scale = 1;
var originx = 0;
var originy = 0;

function draw(){
    context.fillStyle = "white";
    context.fillRect(originx,originy,800/scale,600/scale);
    context.fillStyle = "black";
    context.fillRect(50,50,100,100);
}
setInterval(draw,100);

canvas.onmousewheel = function (event){
    var mousex = event.clientX - canvas.offsetLeft;
    var mousey = event.clientY - canvas.offsetTop;
    var wheel = event.wheelDelta/120;//n or -n

    var zoom = 1 + wheel/2;

    context.translate(
        originx,
        originy
    );
    context.scale(zoom,zoom);
    context.translate(
        -( mousex / scale + originx - mousex / ( scale * zoom ) ),
        -( mousey / scale + originy - mousey / ( scale * zoom ) )
    );

    originx = ( mousex / scale + originx - mousex / ( scale * zoom ) );
    originy = ( mousey / scale + originy - mousey / ( scale * zoom ) );
    scale *= zoom;
}

</script>
12
Simon Sarris