一个灵活的,可配置的波浪动画插件

栏目: Html5 · 发布时间: 6年前

内容简介:春节放假前的第二天上午,看到设计稿上的图(如下),于是发生了下面的对话-我:把这个图传一下吧。-UI:好的,你是要 gif 吧。

春节放假前的第二天上午,看到设计稿上的图(如下),于是发生了下面的对话

一个灵活的,可配置的波浪动画插件

-我:把这个图传一下吧。

-UI:好的,你是要 gif 吧。

-我:啥?这个是个动画?

-UI:啥?这不是动画?

-我:打扰了。

于是在剩下的一天里,我撸出了这个 波浪动画

开始准备

  1. 想想需求

首先我们能想到的是,波浪的数量一定是可定制的,其次是颜色,速度,透明度,高度等等。这些可定制的参数应当在函数实例化时传入。所以我们先定制一个接口(包括了后来在编写时我认为需要的)。

interface Options {
  number: number
  smooth: number
  velocity: number
  height: number
  colors: Array<{ hex: string, rgba: string }>
  opacity: number
  border: {
    show: boolean,
    width: number,
    color: string[]
  }
  position: 'top' | 'bottom' | 'left' | 'right'
}
复制代码

不了解 typescript 的同学可以意会, key 指的传入变量的名称, value 为变量的类型规范

  1. 设计接口

我们先预先想下可能发生的场景:

  1. 动画需要指令化的开始或暂停
  2. 可以通过方法实时设置或更改参数,并反映在动画上
  3. 在动画的容器缩放时,画布应当能重新设置

所以我们暂时值规定四个类型为 public 接口 animatepausesetOptionsreset

interface Core {
  animate: () => void
  pause: () => void
  setOptions: (options: Object) => void
  reset: () => void
}
复制代码

开始写动画

准备工作基本完成,现在开始编写核心动画。

  1. 准备一个 canvas

基本操作,不多介绍。

<body>
  <canvas id="canvas"></canvas>
</body>
复制代码
const canvas = document.getElementById('canvas')  
const ctx = canvas.getContext('2d')
canvas.width = document.body.offsetWidth  
canvas.height = document.body.offsetHeight
复制代码
  1. 先画一池水

画一个矩形,然后填充颜色。

ctx.fillStyle = "rgba(255,118,87,.6)"
ctx.beginPath()
ctx.moveTo(0, canvas.height/2)
ctx.lineTo(canvas.width, canvas.height/2)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height/2)
ctx.closePath()
ctx.fill()
复制代码
一个灵活的,可配置的波浪动画插件
  1. 让水动起来

要让水池的水呈周期性的上涨和跌落,很容易想到借助正弦或者余弦函数来完成,在每一帧的渲染中将 step 增加 1 度,规定 50 为变化值,利用正弦函数将变化量作用于左右两个顶点上即可。

let step = 0
  
  function loop(){
    // 清空canvas
    ctx.clearRect(0,0,canvas.width,canvas.height)
    ctx.clearRect(0,0,canvas.width,canvas.height)
    ctx.fillStyle = "rgba(255,118,87,.6)"
    step++
    
    const angle = step * Math.PI / 180
    const deltaHeight   = Math.sin(angle) * 50
    
    ctx.beginPath()
    ctx.moveTo(0, canvas.height/2+deltaHeight)
    ctx.lineTo(canvas.width, canvas.height/2+deltaHeight)
    ctx.lineTo(canvas.width, canvas.height)
    ctx.lineTo(0, canvas.height)
    ctx.lineTo(0, canvas.height/2+deltaHeight)
    ctx.closePath()
    ctx.fill()

    requestAnimationFrame(loop)
  }
  
  loop()
复制代码
一个灵活的,可配置的波浪动画插件
  1. 让水晃起来

使左右顶点不同步即可让水面晃动起来,所以我们将左顶点的取值使用余弦函数即可。

let step = 0

  function loop() {
    //清空canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.fillStyle = "rgba(255,118,87,.6)"
    step++
    
    const angle = step * Math.PI / 180
    const deltaHeight = Math.sin(angle) * 50
    const deltaHeightRight = Math.cos(angle) * 50
    
    ctx.beginPath()
    ctx.moveTo(0, canvas.height / 2 + deltaHeight)
    ctx.lineTo(canvas.width, canvas.height / 2 + deltaHeightRight)
    ctx.lineTo(canvas.width, canvas.height)
    ctx.lineTo(0, canvas.height)
    ctx.lineTo(0, canvas.height / 2 + deltaHeight)
    ctx.closePath()
    ctx.fill()

    requestAnimationFrame(loop)
  }

  loop()
复制代码
一个灵活的,可配置的波浪动画插件
  1. 制造波浪

借助贝塞尔曲线将矩形的一边变为波浪。

一个灵活的,可配置的波浪动画插件

在 canvas 绘制中,我们借助 bezierCurveTo(cpX1, cpY1, cpX2, cpY2, x, y) 方法绘制贝塞尔曲线,由上图可见(歪脖 45 度查看更直观),两个控制点的横坐标应当设为矩形宽的中点,纵坐标跟随峰值变化即可。

let step = 0

  function loop() {
    //清空canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.fillStyle = "rgba(255,118,87,.6)"
    step++
    
    const angle = step * Math.PI / 180
    const deltaHeight = Math.sin(angle) * 50
    const deltaHeightRight = Math.cos(angle) * 50
    
    ctx.beginPath()
    ctx.moveTo(0, canvas.height/2+deltaHeight)
    ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight-50, canvas.width / 2, canvas.height/2+deltaHeightRight-50, canvas.width, canvas.height/2+deltaHeightRight)
    ctx.lineTo(canvas.width, canvas.height)
    ctx.lineTo(0, canvas.height)
    ctx.lineTo(0, canvas.height/2+deltaHeight)
    ctx.closePath()
    ctx.fill()

    requestAnimationFrame(loop)
  }

  loop()
复制代码
一个灵活的,可配置的波浪动画插件
  1. 多个波浪

将上面的波浪写成 for 循环多次渲染即可。

let step = 0
  const lines = 3

  function loop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    step++
    for (let i = 0; i < lines; i++) {
      ctx.fillStyle = 'rgba(255,118,87,.3)'
      var angle = (step + i * 180 / lines) * Math.PI / 180
      var deltaHeight = Math.sin(angle) * 50
      var deltaHeightRight = Math.cos(angle) * 50
      ctx.beginPath()
      ctx.moveTo(0, canvas.height / 2 + deltaHeight)
      ctx.bezierCurveTo(canvas.width / 2, canvas.height / 2 + deltaHeight - 50, canvas.width / 2, canvas.height / 2 + deltaHeightRight - 50, canvas.width, canvas.height / 2 + deltaHeightRight)
      ctx.lineTo(canvas.width, canvas.height)
      ctx.lineTo(0, canvas.height)
      ctx.lineTo(0, canvas.height / 2 + deltaHeight)
      ctx.closePath()
      ctx.fill()
    }

    requestAnimationFrame(loop)
  }

  loop()
复制代码
一个灵活的,可配置的波浪动画插件

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Designing for Emotion

Designing for Emotion

Aarron Walter / Happy Cog / 2011-10-18 / USD 18.00

Make your users fall in love with your site via the precepts packed into this brief, charming book by MailChimp user experience design lead Aarron Walter. From classic psychology to case studies, high......一起来看看 《Designing for Emotion》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试