利用HTML5 Canvas实现一碗面条特效



7 26 9



特效描述:利用HTML5 Canvas实现一碗面条特效,利用HTML5 Canvas实现一碗面条特效

代码结构

1. HTML代码

<center><canvas id="can"></canvas></center>
<script type="text/javascript">
// Initiate Canvas
let can = document.getElementById('can'),
    ctx = can.getContext('2d'),
    cRad = 250;
can.width = cRad * 2;
can.height = cRad * 2;
ctx.translate(cRad, cRad);
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
// Mouse listeners
let mouse = {
  x: -cRad,
  y: -cRad
};
can.onmousemove = (e) => {
  mouse.x = e.clientX - cRad;
  mouse.y = e.clientY - cRad;
};
// World variables
let noodles = [];
const bowlRad = cRad - 50,
      mouseRad = 20;
// Object: Node - single Noodle joint
function Node(initX, initY, rad) {
  this.p = {x: initX, y: initY};
  this.v = {x: 0, y: 0};
  this.f = {x: 0, y: 0};
  this.r = rad;
  this.friction = 0.15;
}
Node.prototype.applyForce = function(dx, dy) {
  this.f.x += dx;
  this.f.y += dy;
}
Node.prototype.step = function() {
  // Stay in Bowl
  let centerDis = Math.sqrt((this.p.x * this.p.x) + (this.p.y * this.p.y));
  if (centerDis > bowlRad) {
    let ang = Math.atan2(this.p.y, this.p.x);
    this.applyForce(
      (bowlRad - centerDis) * Math.cos(ang),
      (bowlRad - centerDis) * Math.sin(ang)
    );
  }
  // Mouse interaction
  let mouseDis = Math.sqrt(Math.pow(mouse.x - this.p.x, 2) + Math.pow(mouse.y - this.p.y, 2));
  if (mouseDis < this.r + mouseRad) {
    let ang = Math.atan2(this.p.y - mouse.y, this.p.x - mouse.x);
    this.applyForce(
      Math.sqrt(this.r + mouseRad / mouseDis) * Math.cos(ang),
      Math.sqrt(this.r + mouseRad / mouseDis) * Math.sin(ang)
    );
  }
  // Apply Movement
  this.applyForce(this.v.x * -this.friction, this.v.y * -this.friction);
  this.v.x += this.f.x;
  this.v.y += this.f.y;
  this.p.x += this.v.x;
  this.p.y += this.v.y;
  this.f = {x: 0, y: 0};
}
// Object: Noodle - a string of connected nodes
function Noodle(initX, initY, length, thickness) {
  this.nodes = [];
  this.elastic = 0.4;
  this.thickness = thickness;
  // Random colour
  let lightness = (50 + Math.round(Math.random() * 40));
  this.color = 'hsl(48, 93%, ' + lightness + '%)';
  this.colorOutline = 'hsl(48, 93%, ' + (lightness - 20) + '%)';
  // Initiate nodes, slightly out of line
  let nodeNum = length / thickness,
      offsetY = 0;
  for(let i = 0; i < nodeNum; i++) {
    this.nodes.push(new Node(
      initX + (i * thickness),
      initY + offsetY,
      thickness / 2
    ));
    offsetY += (Math.random() * thickness * 2) - thickness;
  }
  noodles.push(this);
}
// Draw noodle as curve connecting nodes
Noodle.prototype.draw = function() {
  ctx.beginPath();
    ctx.moveTo(this.nodes[0].p.x, this.nodes[0].p.y);
    let n = 1;
    for (; n < this.nodes.length - 2; n++) {
      let xc = (this.nodes[n].p.x + this.nodes[n + 1].p.x) / 2,
          yc = (this.nodes[n].p.y + this.nodes[n + 1].p.y) / 2;
      ctx.quadraticCurveTo(this.nodes[n].p.x, this.nodes[n].p.y, xc, yc);
    }
    ctx.quadraticCurveTo(
      this.nodes[n].p.x,
      this.nodes[n].p.y,
      this.nodes[n + 1].p.x,
      this.nodes[n + 1].p.y
    );
    ctx.strokeStyle = this.colorOutline;
    ctx.lineWidth = this.thickness + 2;
  ctx.stroke();
    ctx.strokeStyle = this.color;
    ctx.lineWidth = this.thickness;
  ctx.stroke();
}
// Apply restoration force to all nodes to keep them in line
Noodle.prototype.step = function() {
  for(let i = 0; i < this.nodes.length; i++) {
    let n = this.nodes[i];
    if (i > 0) {
      // Find closest distance between previous node
      let nPrev = this.nodes[i - 1],
          ang = Math.atan2(nPrev.p.y - n.p.y, nPrev.p.x - n.p.x),
          nearN = {
            x: n.p.x + (Math.cos(ang) * n.r),
            y: n.p.y + (Math.sin(ang) * n.r)
          },
          nearNp = {
            x: nPrev.p.x + (Math.cos(ang + Math.PI) * n.r),
            y: nPrev.p.y + (Math.sin(ang + Math.PI) * n.r)
          };
      n.applyForce(
        (nearNp.x - nearN.x) * this.elastic,
        (nearNp.y - nearN.y) * this.elastic
      );
      nPrev.applyForce(
        (nearN.x - nearNp.x) * this.elastic,
        (nearN.y - nearNp.y) * this.elastic
      );
    }
    n.step();
  }
}
// World loop
function step() {
  ctx.clearRect(-cRad, -cRad, cRad * 2, cRad * 2);
  noodles.forEach(n => n.step());
  // Draw Bowl
  ctx.beginPath();
    ctx.arc(0, 0, bowlRad + 25, 0, Math.PI * 2);
    ctx.fillStyle = '#e2d3ad';
  ctx.fill();
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 32;
  ctx.stroke();
    ctx.strokeStyle = '#ddd';
    ctx.lineWidth = 30;
  ctx.stroke();
  // Draw Noodles
  noodles.forEach(n => n.draw());
  window.requestAnimationFrame(step);
}
// Initiate Noodles
for(let i = 0; i < 150; i++) {
  let initX = Math.round(-bowlRad + (Math.random() * bowlRad)),
      initY = Math.round(-bowlRad + (Math.random() * bowlRad * 2)),
      length = 100 + (Math.random() * 250),
      thick = Math.round(10 + (Math.random() * 15));
  new Noodle(initX, initY, length, thick);
}
// Initiate World
step();
</script>
<div style="text-align:center;margin:50px 0; font:normal 14px/24px 'MicroSoft YaHei';color:#ffffff">
</div>



用户评论
大牛,别默默的看了,快登录帮我点评一下吧!:)      登录 | 注册


热门标签: 加载动画 h5弹窗动画 html5弹窗动画 h5动画 h5背景动画 h5场景动画 h53D动画 h5界面动画 html5动画 h5按钮动画 html5按钮动画 h5图片动画 h5图标动画 html5图片动画 html5图标动画
×
×

注册

官方QQ群

扫描上面二维码加微信群

官方QQ群

jQuery/js讨论群
群号:642649996
Css3+Html5讨论群
群号:322131262

加群请备注:从官网了解到