用html写一个有趣的动态背景

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>一个有趣的动态背景</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
<canvas id="canvas"></canvas>

<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.0/gsap.min.js'></script><script src="./script.js"></script>
</body>
</html>
console.clear();
console.log('');

const config = {
  src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/open-peeps-sheet.png',
  rows: 15,
  cols: 7 };


// 公用

const randomRange = (min, max) => min + Math.random() * (max - min);

const randomIndex = array => randomRange(0, array.length) | 0;

const removeFromArray = (array, i) => array.splice(i, 1)[0];

const removeItemFromArray = (array, item) => removeFromArray(array, array.indexOf(item));

const removeRandomFromArray = array => removeFromArray(array, randomIndex(array));

const getRandomFromArray = (array) =>
array[randomIndex(array) | 0];



const resetPeep = ({ stage, peep }) => {
  const direction = Math.random() > 0.5 ? 1 : -1;

  // 使用 ease 函数将随机值倾斜到较低的值
  const offsetY = 100 - 250 * gsap.parseEase('power2.in')(Math.random());
  const startY = stage.height - peep.height + offsetY;
  let startX;
  let endX;

  if (direction === 1) {
    startX = -peep.width;
    endX = stage.width;
    peep.scaleX = 1;
  } else {
    startX = stage.width + peep.width;
    endX = 0;
    peep.scaleX = -1;
  }

  peep.x = startX;
  peep.y = startY;
  peep.anchorY = startY;

  return {
    startX,
    startY,
    endX };

};

const normalWalk = ({ peep, props }) => {
  const {
    startX,
    startY,
    endX } =
  props;

  const xDuration = 10;
  const yDuration = 0.25;

  const tl = gsap.timeline();
  tl.timeScale(randomRange(0.5, 1.5));
  tl.to(peep, {
    duration: xDuration,
    x: endX,
    ease: 'none' },
  0);
  tl.to(peep, {
    duration: yDuration,
    repeat: xDuration / yDuration,
    yoyo: true,
    y: startY - 10 },
  0);

  return tl;
};

const walks = [
normalWalk];



class Peep {
  constructor({
    image,
    rect })
  {
    this.image = image;
    this.setRect(rect);

    this.x = 0;
    this.y = 0;
    this.anchorY = 0;
    this.scaleX = 1;
    this.walk = null;
  }

  setRect(rect) {
    this.rect = rect;
    this.width = rect[2];
    this.height = rect[3];

    this.drawArgs = [
    this.image,
    ...rect,
    0, 0, this.width, this.height];

  }

  render(ctx) {
    ctx.save();
    ctx.translate(this.x, this.y);
    ctx.scale(this.scaleX, 1);
    ctx.drawImage(...this.drawArgs);
    ctx.restore();
  }}


const img = document.createElement('img');
img.onload = init;
img.src = config.src;

const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

const stage = {
  width: 0,
  height: 0 };


const allPeeps = [];
const availablePeeps = [];
const crowd = [];

function init() {
  createPeeps();

  // 调整大小-填充阶段
  resize();

  gsap.ticker.add(render);
  window.addEventListener('resize', resize);
}

function createPeeps() {
  const {
    rows,
    cols } =
  config;
  const {
    naturalWidth: width,
    naturalHeight: height } =
  img;
  const total = rows * cols;
  const rectWidth = width / rows;
  const rectHeight = height / cols;

  for (let i = 0; i < total; i++) {
    allPeeps.push(new Peep({
      image: img,
      rect: [
      i % rows * rectWidth,
      (i / rows | 0) * rectHeight,
      rectWidth,
      rectHeight] }));


  }
}

function resize() {
  stage.width = canvas.clientWidth;
  stage.height = canvas.clientHeight;
  canvas.width = stage.width * devicePixelRatio;
  canvas.height = stage.height * devicePixelRatio;

  crowd.forEach(peep => {
    peep.walk.kill();
  });

  crowd.length = 0;
  availablePeeps.length = 0;
  availablePeeps.push(...allPeeps);

  initCrowd();
}

function initCrowd() {
  while (availablePeeps.length) {
    // 设置随机的两个进程
    addPeepToCrowd().walk.progress(Math.random());
  }
}

function addPeepToCrowd() {
  const peep = removeRandomFromArray(availablePeeps);
  const walk = getRandomFromArray(walks)({
    peep,
    props: resetPeep({
      peep,
      stage }) }).

  eventCallback('onComplete', () => {
    removePeepFromCrowd(peep);
    addPeepToCrowd();
  });

  peep.walk = walk;

  crowd.push(peep);
  crowd.sort((a, b) => a.anchorY - b.anchorY);

  return peep;
}

function removePeepFromCrowd(peep) {
  removeItemFromArray(crowd, peep);
  availablePeeps.push(peep);
}

function render() {
  canvas.width = canvas.width;
  ctx.save();
  ctx.scale(devicePixelRatio, devicePixelRatio);

  crowd.forEach(peep => {
    peep.render(ctx);
  });

  ctx.restore();
}

html, body {
    height: 100%;
  }
  body {
    margin: 0;
  }
  
  #canvas {
    width: 100%;
    height: 100%;
  }

相关推荐

  1. html知识】html一个简单个人网页

    2024-04-21 09:30:01       78 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 09:30:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 09:30:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 09:30:01       87 阅读
  4. Python语言-面向对象

    2024-04-21 09:30:01       96 阅读

热门阅读

  1. ChatGPT畅想:论文写作新境界

    2024-04-21 09:30:01       34 阅读
  2. Github 2024-04-20 Rust开源项目日报 Top10

    2024-04-21 09:30:01       37 阅读
  3. [git] 使用git和github工作思路和经验

    2024-04-21 09:30:01       34 阅读
  4. Linux安装Kubernetes(k8s)详细教程

    2024-04-21 09:30:01       37 阅读
  5. vue3-setup与vue2的data共存

    2024-04-21 09:30:01       120 阅读
  6. 实景景区亲自儿童剧本杀小程序开发搭建

    2024-04-21 09:30:01       171 阅读
  7. NLP地点位置抽取python库实现

    2024-04-21 09:30:01       107 阅读
  8. SHELL脚本编程----netstat练习3-输出每个IP的连接数

    2024-04-21 09:30:01       74 阅读
  9. 正则表达式

    2024-04-21 09:30:01       39 阅读
  10. 大模型日报2024-04-17

    2024-04-21 09:30:01       62 阅读