Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
351 views
in Technique[技术] by (71.8m points)

html - Zooming with canvas

In a test application i have a canvas with a simple rectangle on it. The method draw is called every 100ms.

as you can see from the code i'm using the Mousewheel to scale everything. What happens now is, that everything is scaled, but i.e. when the rectangle is at 10px,10px and i have the mouse right over it the rectangle is not under the mouse anymore after scaling. (Which is of course right because all units are scaled up to.

But what i want to is, that the mouseposition is the "center of the zooming action" like in google maps so the content which is under the mouse before scaling, is under the mouse afterwards as well. I made a few attemps with translating, but i can't figure out, how to do that.

Thanks in advance.

Here's my code:

 <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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It's actually a non-trivial math question, usually known as a "zoom point"

Take a look at here where another canvas user wanted to do the same thing and found a way.

<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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...