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

Javascript 如何在动画期间缩放画布?,javascript,jquery,animation,html5-canvas,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&g

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

<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中,它必须在draw函数循环之外。事实上,点击按钮时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);  
$('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//初始比例为100%
var incrementZoom=0.05;
$(“#缩放按钮”)。单击(函数()
{
canvasZoom+=递增缩放;
缩放(画布缩放,画布缩放);
});
$(“#缩放按钮”)。单击(函数()
{
如果(canvasZoom>1){//我不希望允许小于100%的缩放比例
画布缩放-=递增缩放;
缩放(画布缩放,画布缩放);
}
});  
var draw=function(){
//无法在动画循环内设置比例!继续重置!
clearRect(0,0,canvas.width,canvas.height);
drawImage(图像['background']、0、0、622、924、0、0、311、462);

如果(nextFrame当画布的context2D是一个状态机时,您犯了一个非常常见的错误,即认为scale将设置比例,这将累积每个更改(expl scale X2然后scale X2==scale X4)

这个问题的常见答案是保存()上下文,进行变换,绘制图形,然后还原()

因此,仅为您提供指导(未经测试):

平移/缩放/旋转的顺序实际上取决于您的意图:您是在移动相机还是在移动图像?您是在缩放相机还是在移动图像?(仅当要显示多个项目时才提出相关问题)


希望这会有所帮助。

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

在单击功能中,重要的是保留要缩放的基准的干净副本(此处为初始缩放)

var initialZoom=1;//100%与容器相同(较少边框)
var zoomCounter=1;
var incrementZoom=0.05;
var canvasZoom=1;//仅声明
$(“#缩放按钮”)。单击(函数()
{
canvasZoom=初始缩放+增量缩放;
zoomCounter=zoomCounter+incrementZoom;//因此我可以跟踪原始和块累计<100&
缩放(画布缩放,画布缩放);
});
$(“#缩放按钮”)。单击(函数()
{
如果(zoomCounter>1){//我不希望允许小于100%的缩放比例
canvasZoom=初始缩放-递增缩放;
zoomCounter=zoomCounter-递增缩放;
缩放(画布缩放,画布缩放);
}
}); 

现在开始看游戏炼金术士-s解决方案是否允许我进行更简单的多重变换!

除了缩放(旋转/平移/倾斜)之外,您还想做其他事情吗?@gamealchest,事实上是的,旋转也是移动动画“中心点”的一种方式。谢谢!我马上就要对比例进行更改。关于其他变换的优先级(非常聪明,你预见到了这种可能性),场景是你正在观看足球比赛的动画(因此需要变换多个对象)。观众将能够放大/缩小,或者保持球的中心位置,或者远离球来检查球场的不同部分。旋转将允许观看纵向或横向。我现在要看看你的答案,你最初的评论足以以一种原始的方式解决这个问题。(见下面我的答案)再次感谢。现在看看你的解决方案。我担心,正如我在问题中所说的,在动画的绘图函数中使用变换是不可取的。也许只通过单击函数引用上下文的更原始的方法更好。你认为呢?我在处理画布时简化事情的首要任务是o始终“保持干净”,这意味着只进行保存/转换/绘制/还原操作。如果我不这样做,仍然会有一些特殊情况:最简单的例子是,如果我为特殊目的使用临时画布,那么我会让它的上下文处于任何状态。两个例子说明了您的情况:1)您可能希望始终在相同的位置/大小绘制分数2)你可能想画一个游戏的小地图来显示整体动作,即使在放大的情况下。对于这些情况,我会选择多层画布…或者保持背景始终干净。目标是游戏炼金术士!左上角没有机会让守门员,特别是当他意识到他也希望画布尺寸改变时!谢谢!而这事实上,我只考虑两个可选项:第一个是我的答案,但是是OOP,所以所有属性都在一个单独的对象中,这不仅是干净的,而且还允许TWEENEN或其他功能。第二个是完全相同的,但是你会建立一个转换。用一个setTransform来更新转换。它会更快,但我担心它过于优化,第一个解决方案应该足够快。
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();
}
    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);
    }
   });