【问题标题】:issues in Y-axis when rotating a JS object in HTML5 canvas在 HTML5 画布中旋转 JS 对象时出现 Y 轴问题
【发布时间】:2014-12-23 02:05:51
【问题描述】:

我试图让球在旋转时在线上移动缓动..我的问题是在旋转线时球的 Y 轴发生了变化。

注意

也许在我的代码中,当旋转线条时,整个画布都旋转了,但我不知道如何修复它。

演示 http://jsfiddle.net/mgazzar/o487tnb5/38/

这是画线的方式

ctx.save();
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(angle * Math.PI / 180) ;
ctx.beginPath();
ctx.moveTo(-lineLength/2,0);
ctx.lineTo(lineLength/2,0);
ctx.lineWidth=5;
ctx.strokeStyle='white';
ctx.fillStlye = "white";
    ctx.stroke();
ctx.restore();

【问题讨论】:

    标签: javascript math canvas rotation html5-canvas


    【解决方案1】:

    您还可以使用 Robert Penners 著名的缓动方程来旋转具有缓动效果的对象:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    
    var easingType='easeOutBounce';
    var PI=Math.PI;
    var x=60;
    var y=100;
    var circumference;
    var minAngle=0;
    var maxAngle=PI*4;
    var currentT=0;
    var maxT=100;
    
    var img=new Image();
    img.onload=start;
    img.src="https://dl.dropboxusercontent.com/u/139992952/multple/ball1.png";
    function start(){
      circumference=PI*img.width;
      drawBall(x,y,0);
      animate();
    }
    
    
    function animate(){
      if(currentT<maxT){requestAnimationFrame(animate);}
    
      var easedAngle=Easings[easingType](currentT,minAngle,maxAngle,maxT);
      var easedX=x+easedAngle/maxAngle*circumference*2;
      drawBall(easedX,y,easedAngle);
    
      currentT+=1;
    }
    
    function drawBall(x,y,rAngle){
      ctx.clearRect(0,0,cw,ch);
      ctx.fillRect(0,y,cw,1);
      ctx.save();
      ctx.translate(x,y);
      ctx.rotate(rAngle);
      ctx.drawImage(img,-img.width/2,-img.height/2);
      ctx.restore();
    }
    
    // Robert Penner's easing algorithms
    // t: current time, 
    // b: begInnIng value, 
    // c: change In value, 
    // d: duration
    Easings={
    
      easeLinear: function(t, b, c, d){
    
      },
    
      swing: function (t, b, c, d) {
        return jQuery.easing[jQuery.easing.def](t, b, c, d);
      },
      easeInQuad: function (t, b, c, d) {
        return c*(t/=d)*t + b;
      },
      easeOutQuad: function (t, b, c, d) {
        return -c *(t/=d)*(t-2) + b;
      },
      easeInOutQuad: function (t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t + b;
        return -c/2 * ((--t)*(t-2) - 1) + b;
      },
      easeInCubic: function (t, b, c, d) {
        return c*(t/=d)*t*t + b;
      },
      easeOutCubic: function (t, b, c, d) {
        return c*((t=t/d-1)*t*t + 1) + b;
      },
      easeInOutCubic: function (t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t + b;
        return c/2*((t-=2)*t*t + 2) + b;
      },
      easeInQuart: function (t, b, c, d) {
        return c*(t/=d)*t*t*t + b;
      },
      easeOutQuart: function (t, b, c, d) {
        return -c * ((t=t/d-1)*t*t*t - 1) + b;
      },
      easeInOutQuart: function (t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
        return -c/2 * ((t-=2)*t*t*t - 2) + b;
      },
      easeInQuint: function (t, b, c, d) {
        return c*(t/=d)*t*t*t*t + b;
      },
      easeOutQuint: function (t, b, c, d) {
        return c*((t=t/d-1)*t*t*t*t + 1) + b;
      },
      easeInOutQuint: function (t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
        return c/2*((t-=2)*t*t*t*t + 2) + b;
      },
      easeInSine: function (t, b, c, d) {
        return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
      },
      easeOutSine: function (t, b, c, d) {
        return c * Math.sin(t/d * (Math.PI/2)) + b;
      },
      easeInOutSine: function (t, b, c, d) {
        return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
      },
      easeInExpo: function (t, b, c, d) {
        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
      },
      easeOutExpo: function (t, b, c, d) {
        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
      },
      easeInOutExpo: function (t, b, c, d) {
        if (t==0) return b;
        if (t==d) return b+c;
        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
      },
      easeInCirc: function (t, b, c, d) {
        return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
      },
      easeOutCirc: function (t, b, c, d) {
        return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
      },
      easeInOutCirc: function (t, b, c, d) {
        if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
        return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
      },
      easeInElastic: function (t, b, c, d) {
        var s=1.70158;var p=0;var a=c;
        if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
        if (a < Math.abs(c)) { a=c; var s=p/4; }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
      },
      easeOutElastic: function (t, b, c, d) {
        var s=1.70158;var p=0;var a=c;
        if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
        if (a < Math.abs(c)) { a=c; var s=p/4; }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
      },
      easeInOutElastic: function (t, b, c, d) {
        var s=1.70158;var p=0;var a=c;
        if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
        if (a < Math.abs(c)) { a=c; var s=p/4; }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
        return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
      },
      easeInBack: function (t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c*(t/=d)*t*((s+1)*t - s) + b;
      },
      easeOutBack: function (t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
      },
      easeInOutBack: function (t, b, c, d, s) {
        if (s == undefined) s = 1.70158; 
        if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
        return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
      },
      easeInBounce: function (t, b, c, d) {
        return c - jQuery.easing.easeOutBounce (d-t, 0, c, d) + b;
      },
      easeOutBounce: function (t, b, c, d) {
        if ((t/=d) < (1/2.75)) {
          return c*(7.5625*t*t) + b;
        } else if (t < (2/2.75)) {
          return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
        } else if (t < (2.5/2.75)) {
          return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
        } else {
          return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
        }
      },
      easeInOutBounce: function (t, b, c, d) {
        if (t < d/2) return jQuery.easing.easeInBounce (t*2, 0, c, d) * .5 + b;
        return jQuery.easing.easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
      }
    };
    body{ background-color: ivory; padding:10px; }
    #canvas{border:1px solid red;}
    <p>Moving and Rotating with 'InQuad' easing</p>
    <canvas id="canvas" width=550 height=200></canvas><br>

    【讨论】:

    • 谢谢,有没有纯JS的简单缓动工具?
    • 相关代码都是纯javascript——我只是习惯性地使用jQuery来处理再次按钮点击。我已经从我的演示中删除了 jQuery,现在它是纯 javascript。祝你的项目好运!
    【解决方案2】:

    您的线路代码很好,问题在于您如何渲染球。在线条图中,您在ctx.rotate 之前正确运行ctx.translate(canvas.width/2,canvas.height/2),以便线条围绕画布中心旋转。但是你没有在ball2.draw 中做任何类似的事情,所以球在画布上围绕 0,0 旋转,画布的左上角。

    您可以通过在旋转画布之前执行适当的ctx.translate 来解决此问题(下面的 1)。但是你需要小心在旋转后进行反向平移 (2)。如果没有,您的球将使用 this.x,this.y 相对于画布的中心绘制,而不是根据需要相对于(旋转的)屏幕的左上角。

        // Function for drawing ball on canvas
    draw: function() {
        ctx.save();
        ctx.beginPath();
        ctx.translate(canvas.width/2,canvas.height/2);      // 1
        ctx.rotate(angle * Math.PI / 180) ;
        ctx.translate(-canvas.width/2,-canvas.height/2);    // 2
        ctx.arc(this.x, this.y, this.r, 0, Math.PI*2, false);
        ctx.fillStyle = "white";
        ctx.fill();
        ctx.restore();
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-30
      • 1970-01-01
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多