如何在动画期间缩放画布?

时间:2014-09-12 15:08:54

标签: javascript jquery animation html5-canvas

我有两个按钮,可以放大和缩小我的画布动画

<button id="zoomInButton">Zoom ++</button>
<button id="zoomOutButton">Zoom -- </button>

 <canvas id="myCanvasmatchPage" > 
        Sorry, your browser doesn't support canvas technology
</canvas>

我使用setInterval和canvas有一个动画循环(省略)。为了不使每个setInterval都进行缩放,它必须超出绘制函数循环。事实上,点击按钮时会重置ctx.scale。

$('#myCanvasmatchPage').attr({width:100,height:200}).css({width:'100px',height:'200px'});       

var canvas = document.getElementById("myCanvasmatchPage");
ctx = canvas.getContext("2d");
ctx.translate(0.5,0.5);

var nextFrame =0;
var animationData = [];

var canvasZoom = 1; //initial is scale 100%
var incrementZoom = 0.05;
$("#zoomInButton").click(function ()
   {
     canvasZoom += incrementZoom;
     ctx.scale(canvasZoom, canvasZoom);
   });
 $("#zoomOutButton").click(function ()
   {
     if (canvasZoom > 1){//i dont want to allow a less than 100% scale zoom
           canvasZoom -= incrementZoom; 
           ctx.scale(canvasZoom, canvasZoom);
    }
   });  


var draw = function(){
    //cannot set scale within animation loop! keeps resetting!
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(images['background'], 0, 0, 622, 924, 0, 0, 311, 462);

                if (nextFrame<=animationData.length){
                    //animation loop
                }else{
                    clearTimeout(draw);//get out of the loop
                    return;
                }

                nextFrame++;    
    }
    setInterval(draw,200);  

我目前使用此代码的经验是,zoomIn&#39;工作&#39;但是zoomOut没有。控制台日志记录向我展示了canvasZoom一直上下0.05(有时也是0.05000001公顷),但画布不会有负面缩放。

这让我觉得问题在于清除画布而不是缩放。

2 个答案:

答案 0 :(得分:1)

当Canvas的context2D是状态机时,你会认为比例将设置比例,这是一个很常见的错误,它会将每个变化累积在一起(测量比例X2然后缩放x2 ==比例X4)。

这个问题的常见答案是保存()你的上下文,做你的变换,做你的绘图,然后恢复()它。

所以只是给你方向(未经测试):

function Transform() {
   this.scale = 1;
   this.rotation = 0;
   this.translation = {x:0, y:0 };
   this.zoomIn = function () {
    this.scale+=0.5;
   };
   this.zoomOut = function () {
    this.scale-=0.5;
   };
   this.translate(x,y) = function (x,y)  { 
     this.translation.x+=x;  // OR +=x*currentZoom;
     this.translation.y+=y;  // OR +=y*currentZoom;
   };
   this.rotate = function (angle) {
      this.rotation+=angle;
   };
   this.applyTransform = function (ctx) {
       ctx.translate(translation.x, translation.y);  // ?? order ??
       ctx.scale(currentZoom, currentZoom);          // ?? order ??
       ctx.rotate(rotation);                   
   }
}

var imageTransform = new Transform();

function drawImage(img) { 
  ctx.save();
  ctx.translate(img.width/2, img.height/2);
  imageTransform.applyTransform(ctx);
  ctx.drawImage(img, -img.wdth/2, -img.height/2);
  ctx.restore();
}

翻译/缩放/旋转的顺序实际上取决于您的意图:您是移动相机还是移动图像?你缩放相机或图像? (只有在显示多个项目时才有相关问题。)

希望这会有所帮助。

答案 1 :(得分:0)

当我研究@GameAlchemist的更彻底的解决方案时,这将是一个解决简单转换问题的方法。感谢GameAlchemist指出(非常重要!)规模变化是累积的!

在点击功能中,保持基础的干净副本以进行缩放非常重要(此处为initialZoom)

    var initialZoom = 1;    //100% same as container (less border)
    var zoomCounter = 1;
    var incrementZoom = 0.05;
    var canvasZoom = 1;//just to declare

 $("#zoomInButton").click(function ()
   {
     canvasZoom = initialZoom + incrementZoom;
    zoomCounter = zoomCounter + incrementZoom;//so i can track compared to original and block cumulative < 100&
     ctx.scale(canvasZoom, canvasZoom);
   });
 $("#zoomOutButton").click(function ()
   {
     if (zoomCounter > 1){//i dont want to allow a less than 100% scale zoom
           canvasZoom = initialZoom - incrementZoom;
           zoomCounter = zoomCounter - incrementZoom;
           ctx.scale(canvasZoom, canvasZoom);
    }
   }); 

现在关闭看看GameAlchemist的解决方案是否允许我更轻松地进行多变换!