实现twiter首页过渡loading效果

373 阅读2分钟

实现效果

类似顶部loading效果

思路

刚开始我的想法是:每个模块都有一个特定的动画,只需要控制每个模块的动画延迟时间。
后来发现这个实现起来有问题:背景色的linear-gradient不支持transition过渡效果。
我又换了一种思路,将过渡模块和上面的遮蔽层分开,空心圆框作为一层,下面的过渡作为一层,这样可以通过移动下方过渡左右位置来实现过渡效果。
这时候又发现,要想实现这个效果,必须要一个最上层背景色为白色,中心圆为透明色的块。但是css又无法实现,因为没办法把一个块中心一个圆抠出来。
这样就只能用canvas实现这个遮蔽层了。

实现

在这里观看效果

css代码:

// 主容器
.grid {
  display: flex;
  width: 600px;
  height: 100px;
  background: #FFFFFF;
  overflow: hidden;
  position: relative;
}
// 过渡层
.grid::before {
  content: "";
  display: block;
  width: 1480px;
  height: 100px;
  background: linear-gradient(to right, rgba(0, 0, 0, .05), rgba(0, 0, 0, .05) 40%, rgba(0, 0, 0, .1) 50%, rgba(0, 0, 0, .05) 60%, rgba(0, 0, 0, .05));
  position: absolute;
  left: -860px;
  z-index: 1;
}
.move::before {
  left: 0;
  transition: 1.6s left linear;
}
// 遮蔽层
canvas {
  z-index: 2;
}

html代码:

<div id="grid" class="grid">
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
</div>

JS代码:

可以自定义圆直径w、左右边距x、上下边距y

class CanvasBox {
  constructor(data = {}) {
    this.w = data.w || 80
    this.x = data.x || 10
    this.y = data.y || 10
  }

  setCanvas(canvas) {
    canvas.width = this.w + this.x * 2
    canvas.height = this.w + this.y * 2
    console.log(canvas.width, canvas.height)
    var ctx = canvas.getContext("2d")
    ctx.fillStyle="#ffffff";
    ctx.fillRect(0, 0, canvas.width, this.y)
    ctx.fillRect(0, this.y + this.w, canvas.width, this.y)
    ctx.fillRect(0, this.y, this.x, this.w)
    ctx.fillRect(this.x + this.w, this.y, this.x, this.w)
    ctx.beginPath()
    ctx.moveTo(this.x, canvas.height / 2)
    ctx.lineTo(this.x, this.y + this.w)
    ctx.lineTo(this.x + this.w, this.y + this.w)
    ctx.lineTo(this.x + this.w, this.y)
    ctx.lineTo(this.x, this.y)
    ctx.lineTo(this.x, canvas.height / 2)
    ctx.arc(canvas.width / 2, canvas.height / 2, this.w / 2, 0, Math.PI * 2)
    ctx.fill()
  }
}

var canvasList = document.querySelectorAll("canvas")
for (let i = 0; i < canvasList.length; i++) {
  const element = canvasList[i]
  new CanvasBox().setCanvas(element)
}

setInterval(function() {
  document.getElementById('grid').className = "grid"
  setTimeout(function() {
    document.getElementById('grid').className = "grid move"
  }, 0)
}, 2000)