Zoom my drawing on the background [duplicate]

2019-09-21 17:39发布

问题:

This question already has an answer here:

  • HTML5 canvas zoom where mouse coordinates 1 answer

I make program like a paint with HTML5 canvas and javascript. Drawing takes place on the background image. How to zoom my drawing on the background together.

Before zoom it:

After zoom it (need this result):

Note: zoom should be where clicked with the mouse on the background image

回答1:

I've done this before!

First of all, I set a zoom level attribute on my canvas.

Main.canvas.zoomX = 1;
Main.canvas.zoomY = 1;

I also retain the original size of the canvas for reference.

Main.canvas.originW = Main.canvas.width;
Main.canvas.originH = Main.canvas.height;

I also retain the original left and top of the canvas for reference.

Main.canvas.gLeftStart = 0;
Main.canvas.gTopStart = 0;

I then set a zoom percentage. The zoom level will be adjusted by this amount every time that the zoom event occurs.

Main.canvas.zoomPerc = 0.05;

Next, I set an event listener on my canvas to watch for mousewheel.

Main.canvas.addEventListener('wheel', zoom, true);

Now, I'm going to write a quick function to retrieve the zoom, then I'll explain it.

function zoom(evt)
{
   var x;
   var y;

   Main.canvas.xLayerS = (evt.layerX + (Main.canvas.gLeftStart * -1)) / (Main.canvas.originW * Main.canvas.zoomX);
   Main.canvas.yLayerS = (evt.layerY + (Main.canvas.gTopStart * -1)) / (Main.canvas.originH * Main.canvas.zoomY);

   Main.canvas.leftPerc = Main.canvas.gLeftStart / (Main.canvas.originW * Main.canvas.zoomX);
   Main.canvas.topPerc = Main.canvas.gTopStart / (Main.canvas.originH * Main.canvas.zoomY);

   if(evt.deltaY > 1)
   {
     Main.canvas.zoomX *= 1 +  Main.canvas.zoomPerc;
     Main.canvas.zoomY *= 1 +  Main.canvas.zoomPerc;
   }
   else
   {
     Main.canvas.zoomX *= 1 -  Main.canvas.zoomPerc;
     Main.canvas.zoomY *= 1 -  Main.canvas.zoomPerc;
   }

   var iiDS;
   var cmd;

   Main.canvas.xLayer = Main.canvas.xLayerS * (Main.canvas.originW * Main.canvas.zoomX);
   Main.canvas.yLayer = Main.canvas.yLayerS * (Main.canvas.originH * Main.canvas.zoomY);

   Main.context.clearRect(0, 0, Main.canvas.width, Main.canvas.height);
   Main.context.beginPath();

   Main.canvas.gLeftStart = (evt.layerX -  Main.canvas.xLayer);
   Main.canvas.gTopStart = (evt.layerY -  Main.canvas.yLayer);

   for(iiDS = 0; iiDS < Main.dataPoints.length; iiDS++)
   {
      if(iiDS === 0)
      {
         cmd = 'moveTo';
      }
      else
      {
        cmd = 'lineTo';
      }

      Main.dataPoints[iiDS].xPerc = Main.dataPoints[iiDS].x / Main.range.x;
      Main.dataPoints[iiDS].yPerc = Main.dataPoints[iiDS].y / Main.range.y;

      x = Main.canvas.gLeftStart + (Main.dataPoints[iiDS].xPerc *  (Main.canvas.originW * Main.canvas.zoomX));
      y = Main.canvas.gTopStart + (Main.dataPoints[iiDS].yPerc *  (Main.canvas.originH * Main.canvas.zoomY));

      Main.context[cmd](x, y);
   }

   Main.context.stroke();
}

Now that your canvas has been re-sized, you will need to redraw whatever was in it. Remember, any time that you re-size a canvas, you clear the canvas. If your canvas was holding an image, then that's simple, redraw that image at that size. If you canvas was holding data points (like a chart) then I would suggest that you make your data points have percentage like (probably a word for that) positions along your chart, not pixel positions.

More importantly though, I do not suggest that you ever re-size and re-position your canvas on zoom. Your page can get jumbled up and sloppy that way. Instead, use the percentages for size (like I showed you) and use the values for left and top positioning as starting points in your drawing. If a data point was a certain percentage of a way across a chart, it can be drawn at any size. Plus, you can draw outside of your canvas, it just won't be visible. Your canvas would then be more like a view-port.

You can do some really impressive charting this way, which a lot of companies pay a lot of money for. Have fun!



回答2:

Did you try Context2d.scale(x, y)? You could do the following

 var canvas = document.getElementById('myCanvas');
 var context = canvas.getContext('2d');

 context.scale(2, 2);

 paintBackGround(context);
 paintForeGround(context);

scale(factorWidth, factorHeight) Scales all coordinates in the canvas by the factors, so it will scale the background and the drawing. The example would double the size. You don't have to scale your coordinates by yourself, just let canvas do that for you. Here is an example : http://www.html5canvastutorials.com/advanced/html5-canvas-transform-scale-tutorial/

The only problem here: you need to scale before you draw, so you need a model that contains the original drawing in original unscaled coordinates, that can be drawn after scaling (paintForeGround() in my example)

Scale() is part of so called Transformations. You can Translate (move along a vector) rotate and scale the content of a canvas by using buildin functions of canvas. Just take a look at the html5canvastutorials. This works with matrix-mutliplications in the background, but it is really simple to use.