EVANYOU尤大个人网站主页CANVAS三角彩带效果分析学习

尤雨溪网站三角彩带效果

效果:

EVANYOU尤大个人网站主页CANVAS三角彩带效果分析学习

源码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <canvas></canvas>
</body>
<script>
var c = document.getElementsByTagName('canvas')[0],
    x = c.getContext('2d'),
    pr = window.devicePixelRatio || 1,
    /*devicePixelRatio
     *devicePixelRatio = screenPhysicalPixels/deviceIndependentPixels
     *eg.iPhone4s,Resolution:960*640
     *   screenPhysicalPixels=640px
     *   deviceIndependentPixels=320px
     *   devicePixelRatio=640/320=2
     *You need set diff-size imgs to fit the devicePixelRatio.
     */
    w = window.innerWidth,
    h = window.innerHeight,
    f = 90, // InitialDistance
    q,
    z = Math.random,
    r = 0
    u = Math.PI * 2,
    v = Math.cos

c.width = w * pr
c.height = h * pr
x.scale(pr, pr) // Synchronization with devicePixelRatio
x.globalAlpha = 0.6 // gloabalAlpha set or return the opacity-value of draw

function i() {
  x.clearRect(0, 0, w, h) // clear all rect
  q = [{x: 0, y: h * .7 + f},{x: 0, y: h * .7 - f}]
  while(q[1].x < w + f)d(q[0], q[1]); // w + f
}

function d(i ,j) {
  x.beginPath()
  x.moveTo(i.x, i.y)
  x.lineTo(j.x, j.y)
  var k = j.x + (z() * 2 - 0.25) * f,
  // x->[-0.25 * f, 1.75 * f]
  // x_average = 0.75 * 90 = 67.5
  // number_rects = 1080 / 67.5 = 16
      n = y(j.y)
  /*When k < 0:
  *The first rect will be invisable, it is in the window's left.
  *So we can see the first line on the window sometimes changes the initial position.
  */
  x.lineTo(k ,n)
  x.closePath()
  r -= u / -50
  x.fillStyle = '#' + (v(r) * 127 + 128 << 16 | v(r + u / 3) * 127 + 128 << 8 | v(r + u / 3 * 2) * 127 + 128).toString(16)
  /*ColorSelectionAlgorithm
  * v=Math.cos,u=2*Math.Pi,r = n * Math.PI/25(n=0,1,2...)
  * (R,G,B)=>Hexadecimal === (R << 16|G << 8|B).toString(16)
  * 0xFFFFFF = 16777215
  * It's equate to:
  *   R = cos(r)*127+128
  *   G = cos(r+2*PI/3)*127+128
  *   B = cos(r+4*PI/3)*127+128
  * 128 << 16 === 128 * (2 ** 16)
   */
  x.fill()
  q[0] = q[1] // old point -> new q[0]
  q[1] = {x: k, y: n} // new point(k, n) -> new q[1]
  // constant line
}

function y(p) {
  var t = p + (z() * 2 - 1.1) * f
  return (t > h || t < 0) ? y(p) : t
  // y->[-1.1, 0.9)
}
document.onclick = i
i()
</script>
<style>
html, body {
  overflow: hidden;
  margin: 0;
}
canvas {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /*pointer-events
   *DefaultValue: Auto
   *Inheritable: Yes
   *Animated: No
   *Computed: Appoint
   *Value: 
   *  auto
   *  none--element will never be the target of mouse-events
   *Ins:
   *BasicSupport:IE(11.0+)FF(3.6+)Chrome(4.0+)Safari(6.0)Opera(15.0)
   */
}
</style>
</html>

技巧点

  1. 为了适应不同物理大小及缩放比例屏幕, 保证像素一致性:
  • 画布大小 = innerWidth * devicePixelRatio
  • canvas缩放变换 x.scale(devicePixelRatio, devicePixelRatio)
  1. 颜色区间取值算法
  • 颜色递减因子 r -= Math.PI * 2 / -50, 负的360度*五十分之一, 从1->0
  • x.fillStyle = ‘#‘ + (cos(r) * 127 + 128 << 16 | cos(r + Math.PI / 3) * 127 + 128 << 8 | cos(r + Math.PI / 3 * 2) * 127 + 128).toString(16)

随便取一组:

#fd334e
#fb275d
#f61c6d
#ef137d
#e60b8d
#dc069d
#d002ac
#c401ba
#b601c8
#a703d4
#9708e0
#870ee9
#7816f1
#681ff7
#582bfc
#4937fe
#3b45fe
#2f53fd
#2362f9
#1972f4

调色是项艺术,自行追究.

  1. 三角形点算法
function y(p) {
  var t = p + (z() * 2 - 1.1) * f
  return (t > h || t < 0) ? y(p) : t
  // y->[-1.1, 0.9)
}

相关推荐