在HTML5画布中旋转JS对象时Y轴出现问题



我试图让球在直线上移动,同时旋转并放松。。我的问题是,当旋转直线时,球的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();

您还可以使用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>

您的行代码很好,问题在于如何渲染球。在线条绘制中,应在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();
    }

相关内容

最新更新