• 赚钱入口【需求资源】限时招募流量主、渠道主,站长合作;【合作模式】CPS长期分成,一次推广永久有收益。主动打款,不扣量;

画布canvas中实现平滑的动画效果

CSS/HTML rin, seun 4个月前 (06-23) 68次浏览 0个评论

<canvas>HTML中的元素和JavaScript中的Canvas API结合在一起,形成了网络上主要的光栅图形和动画之一。一个常见的画布用例是以编程方式为网站(尤其是游戏)生成图像。

在本文中,我们专门研究一下画布中的动画以及使它们看起来更平滑的技术。我们将专门研究缓和的过渡(例如“缓入”和“缓出”),这些过渡在画布中并非像CSS中那样免费提供。

让我们从静态画布开始。我已经从DOM中抓取了一张纸牌到画布上:

让我们从一个基本的动画开始:在画布上移动该纸牌。即使对于相当基本的事情,例如需要在画布上从头开始工作,因此我们也必须开始构建可以使用的功能。

首先,我们将创建函数来帮助计算X和Y坐标:

function getX(params) {
  let distance = params.xTo - params.xFrom;
  let steps = params.frames;
  let progress = params.frame;
  return distance / steps * progress;
}function getY(params) {
  let distance = params.yTo - params.yFrom;
  let steps = params.frames;
  let progress = params.frame;
  return distance / steps * progress;
}

这将帮助我们在动画图像时更新位置值。然后,我们将继续重新渲染画布,直到动画完成。为此,我们将以下代码添加到我们的addImage()方法中。

if (params.frame < params.frames) {
  params.frame = params.frame + 1;
  window.requestAnimationFrame(drawCanvas);
  window.requestAnimationFrame(addImage.bind(null, params))
}

现在我们有了动画!每次我们都稳定地增加1个单位,我们称之为线性动画。

您可以看到形状如何以线性方式从A点移动到B点,并保持点之间相同的一致速度。它具有功能,但缺乏现实性。开始和停止令人讨厌。

我们想要的是物体加速(缓入)和减速(缓和),因此它模仿了现实世界中物体在摩擦和重力作用下会做什么。

JavaScript动画平滑函数

我们将通过“立方”缓入和缓出过渡来实现这一目标。我们已经修改了罗伯特·彭纳(Robert Penner)的 Flash easing functions中找到的方程式之一,以适合我们在此处要执行的操作。

function getEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) {
    return (distance/2)*(Math.pow(currentProgress, 3)) + start;
  }
  currentProgress -= 2;
  return distance/2*(Math.pow(currentProgress, 3)+ 2) + start;
}

将其插入到我们的代码中(这很容易实现),我们得到的结果要平滑得多。请注意,卡片是如何朝着空间的中心加速,然后在到达末端时减速。

使用JavaScript实现平滑的效果

我们可以通过二次或正弦缓和得到较慢的加速度。

function getQuadraticEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress <= 1) {
    return (distance/2)*currentProgress*currentProgress + start;
  }
  currentProgress--;
  return -1*(distance/2) * (currentProgress*(currentProgress-2) - 1) + start;
}
function sineEaseInOut(currentProgress, start, distance, steps) {
  return -distance/2 * (Math.cos(Math.PI*currentProgress/steps) - 1) + start;
};

为了获得更快的加速度,请轻松地进行五次或指数化处理:

function getQuinticEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) {
    return (distance/2)*(Math.pow(currentProgress, 5)) + start;
  }
  currentProgress -= 2;
  return distance/2*(Math.pow(currentProgress, 5) + 2) + start;
}
function expEaseInOut(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) return distance/2 * Math.pow( 2, 10 * (currentProgress - 1) ) + start;
 currentProgress--;
  return distance/2 * ( -Math.pow( 2, -10 * currentProgress) + 2 ) + start;
};

使用GSAP更复杂的动画

滚动自己的缓动功能可能很有趣,但是如果您想要更多的功能和灵活性怎么办?您可以继续编写自定义代码,也可以考虑使用功能更强大的库。让我们转向GSAP。

使用GSAP可以轻松实现动画。以该示例为例,该卡最后会弹起。请注意,GSAP库包含在演示中。

关键功能是moveCard

function moveCard() {
  gsap.to(position, {
    duration: 2,
    ease: "bounce.out",
    x: position.xMax, 
    y: position.yMax, 
    onUpdate: function() {
      draw();
    },
    onComplete: function() {
      position.x = position.origX;
      position.y = position.origY;
    }
  });
}

gsap.to方法是所有魔术发生。在两秒钟的持续时间内,position对象会更新,并且每次更新都会调用onUpdate来触发画布重绘。

组装在一起

仍不确定在缓动时应在画布中使用哪种动画样式和方法?这是一支笔,显示了不同的缓动动画,包括GSAP中提供的动画。

查看我的纸牌纸牌游戏  ,观看非GSAP动画的实时演示。在这种情况下,我添加了动画,以便游戏中的纸牌在堆之间移动时可以轻松移动和轻松移动。

除了创建运动之外,还可以将缓动函数应用于具有“ 从”和“  到”状态的任何其他属性,例如不透明度,旋转和缩放的更改。希望您能找到许多使用缓动功能的方法,以使您的应用程序或游戏看起来更流畅。

喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址