【HTML】制作一个简单的线性动画

news2024/11/27 7:41:22

 目录

前言

HTML部分

CSS部分

JS部分

效果图

总结


前言

        无需多言,本文将详细介绍一段HTML代码,具体内容如下:

开始

        首先新建文件夹,创建一个文本文档,两个文件夹,其中HTML的文件名改为[index.html];CSS的文件名改为[css],里面新建一个文本文档重命名为[normalize.min.css];JS的文件名改为[js],里面新建两个文本文档,分别重命名为 [script.js] [simplex-noise.min.js],创建好后右键用文本文档打开,再把下面相对应代码填入后保存即可。

HTML部分

        这段HTML代码定义了一个基本的网页结构,包括了必要的文档类型声明、网页头部(head)和主体(body)部分。具体来说:

  1. <!DOCTYPE html>: 这是HTML5文档的声明,用于告诉浏览器这是一个HTML5文档。

  2. <html lang="en">: 根元素,定义了整个HTML文档,并设置页面的语言为英语。

  3. <head>: 包含了文档的元数据,不影响页面的可见内容,但对搜索引擎优化(SEO)和页面表现很重要。

    • <meta charset="UTF-8">: 设置字符编码为UTF-8,这是一种广泛使用的国际字符编码,可以显示几乎所有语言的字符。
    • <title>雷神Leo</title>: 设置了浏览器标签页上显示的标题,这里是“雷神Leo”。
    • <link rel="stylesheet" href="css/normalize.min.css">: 引入了一个外部CSS文件,用于样式重置和标准化不同浏览器间的默认样式差异,以确保网页的一致性。
  4. <body>: 包含了网页的所有可见内容。

    • <script src='js/simplex-noise.min.js'></script>: 引入了一个JavaScript库,用于生成简单的噪声效果,常用于创建视觉效果。
    • <script src="js/script.js"></script>: 引入了网页的主要JavaScript文件,负责处理网页的行为和交互逻辑。

        这个网页模板是一个起点,开发者可以在此基础上添加更多的HTML元素、CSS样式和JavaScript代码,以创建具有丰富功能和吸引人设计的网页。需要注意的是,实际使用时,需要确保外部文件路径正确,并编写相应的CSS和JavaScript代码来实现所需的功能。

<!DOCTYPE html> <!-- 声明文档类型为HTML5 -->
<html lang="en" ><!-- 根元素,设置语言为英语 -->
<head>
    <meta charset="UTF-8"> <!-- 设置字符编码为UTF-8,确保网页正确显示多语言字符 -->
    <title>雷神Leo</title> <!-- 网页标题,将显示在浏览器标签页上 -->
    <!-- 引入外部CSS样式表,用于网页的样式布局 -->
    <link rel="stylesheet" href="css/normalize.min.css">
</head>
<body>
    <!-- 页面的主体内容将会放在这里 -->
    <!-- 引入外部JavaScript文件,用于网页的行为和动态效果 -->
    <script src='js/simplex-noise.min.js'></script>
    <script src="js/script.js"></script>
</body>
</html>

CSS部分

        这段代码是一个CSS样式表的一部分,主要使用了Normalize.css,它是一个用于网页的CSS库,旨在创建一个更平滑的用户体验,同时保持不同浏览器和设备之间的一致性。以下是对这段代码的总结和注释:

  1. button,hr,input{overflow:visible}: 设置按钮、水平规则线(hr)和输入框的溢出内容为可见,以确保这些元素的溢出内容不会影响布局。

  2. audio,canvas,progress,video{display:inline-block}: 将音频、画布、进度条和视频等元素设置为内联块状元素,使它们既能像内联元素一样参与文本流,又能设置宽高。

  3. progress,sub,sup{vertical-align:baseline}: 设置进度条、下标和上标元素的垂直对齐方式为基线对齐,以确保它们与文本的基线对齐。

  4. html{font-family:sans-serif;line-height:1.15;...}: 设置默认的字体系列为无衬线字体,并设置行高为1.15倍,同时禁用了一些浏览器的默认文本大小调整功能。

  5. body{margin:0}: 设置页面主体的默认外边距为0,以避免浏览器的默认边距影响布局。

  6. menu,article,aside,...{display:block}: 将一些HTML5新增的语义化元素设置为块状元素,确保它们占据一整行。

  7. h1{font-size:2em;margin:.67em 0}: 设置一级标题的字体大小为2em,并设置上下外边距。

  8. figcaption,figure,main{display:block}: 设置图题、图形和主要内容区域为块状元素。

  9. hr{box-sizing:content-box;height:0}: 设置水平规则线的盒模型为内容盒模型,并将其高度设置为0。

  10. code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}: 设置代码、键盘输入、预格式化文本和样本文本的字体为等宽字体,并设置字体大小为1em。

  11. a{background-color:transparent;...}: 设置超链接的背景颜色为透明,并禁用了一些浏览器的默认文本装饰。

  12. abbr[title]{...}: 设置有标题属性的缩写词的文本装饰为下划线点状,以提供解释性的文本。

  13. b,strong{font-weight:bolder}: 设置加粗文本的字体权重更强。

  14. small{font-size:80%}: 设置小号文字的字体大小为80%。

  15. sub,sup{...}: 设置下标和上标的字体大小为75%,并设置行高为0,以及它们的相对位置。

  16. audio:not([controls]){...}: 隐藏没有控件的音频元素。

  17. img{border-style:none}: 设置图片的边框样式为无。

  18. button,input,...{...}: 设置一系列表单元素的字体系列、大小、外边距等。

  19. fieldset{border:1px solid silver...}: 设置字段集的边框样式、间距和填充。

  20. legend{...}: 设置图例的盒模型、颜色、显示方式和白空间。

  21. progress{}textarea{overflow:auto}: 为进度条和文本区域设置样式。

  22. [type=checkbox],...{...}: 设置复选框、单选按钮等表单元素的盒模型和样式。

  23. summary{display:list-item}: 设置摘要元素的显示方式为列表项。

  24. [hidden],template{display:none}: 隐藏隐藏元素和模板元素。

        最后,/*# sourceMappingURL=normalize.min.css.map */ 是一个注释,用于指示这个CSS文件的源映射文件的位置,便于开发者调试。

        这段代码的目的是为网页提供一个统一的样式基础,减少浏览器之间的默认样式差异,使得开发者可以更轻松地创建一致且易于维护的网页。

button,hr,input{overflow:visible}audio,canvas,progress,video{display:inline-block}progress,sub,sup{vertical-align:baseline}html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} menu,article,aside,details,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{}button,select{text-transform:none}[type=submit], [type=reset],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}/*# sourceMappingURL=normalize.min.css.map */

JS部分

[script.js]

        这段代码定义了几个类,用于生成随机数、颜色、处理向量运算、碰撞检测、计时、动画定时以及绘制分形图形。

  1. Utils 类提供了一些静态方法,用于生成随机数、随机颜色值和渐变颜色。还包括一个计算当前帧率(FPS)的方法。

  2. Vector2d 类表示二维向量,提供了一系列方法来执行向量运算,如缩放、加法、减法、取反、归一化、旋转和转换为字符串表示。

  3. Collision 类用于处理对象之间的碰撞检测和碰撞反弹。它提供了一个 collideAll 方法来检查所有对象对之间的碰撞,并调用 bounce 方法来处理碰撞反弹。

  4. Stopwatch 类用于计时,提供了开始、停止、获取经过时间、检查是否正在运行和重置计时器的方法。

  5. AnimationTimer 类用于动画定时,它可以创建一个基于时间的动画效果,支持不同的缓动函数,如Ease-In、Ease-Out、Ease-In-Out、Elastic和Bounce。还包括一个线性缓动函数和一个方法来检查动画是否完成。

  6. Angle 类用于表示角度,可以增加或减少角度值,并将角度值转换为弧度。

  7. Canvas 类用于创建和管理分形图形的绘制。它提供了初始化、渲染、绘制帧率和响应窗口大小变化的方法。

  8. PointObj 类表示一个二维点,包含 x 和 y 坐标。

  9. FractalRoot 类用于生成分形的根节点,它初始化分形的结构并绘制形状。

  10. Branch 类表示分形中的一个分支,它负责计算分支的中间点、结构点,并绘制分支。

        最后,代码中的自执行函数用于初始化 Canvas 类,并设置窗口大小变化的事件监听器,以确保画布随着浏览器窗口的变化而调整大小。整个代码展示了一个分形动画的生成和渲染过程,包括碰撞检测和帧率显示。

class Utils {

  static randomNumber(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

  static randomColorRGB() {
    return (
      "rgb(" +
      this.randomNumber(0, 255) +
      ", " +
      this.randomNumber(0, 255) +
      ", " +
      this.randomNumber(0, 255) +
      ")"
    );
  }

  static randomColorHSL(hue, saturation, lightness) {
    return (
      "hsl(" +
      hue +
      ", " +
      saturation +
      "%, " +
      lightness +
      "%)"
    );
  }

  static gradientColor(ctx, cr, cg, cb, ca, x, y, r) {
    const col = cr + "," + cg + "," + cb;
    const g = ctx.createRadialGradient(x, y, 0, x, y, r);
    g.addColorStop(0, "rgba(" + col + ", " + (ca * 1) + ")");
    g.addColorStop(0.5, "rgba(" + col + ", " + (ca * 0.5) + ")");
    g.addColorStop(1, "rgba(" + col + ", " + (ca * 0) + ")");
    return g;
  }

  static calcFPS() {
    const now = (+new Date());
    const fps = 1000 / (now - lastTime);
    lastTime = now;
    return fps.toFixed();
  }
}

class Vector2d {
  constructor(x, y) {
    this.vx = x;
    this.vy = y;
  }

  scale(scale) {
    this.vx *= scale;
    this.vy *= scale;
  }

  add(vec2) {
    this.vx += vec2.vx;
    this.vy += vec2.vy
  }

  sub(vec2) {
    this.vx -= vec2.vx;
    this.vy -= vec2.vy;
  }

  negate() {
    this.vx = -this.vx;
    this.vy = -this.vy;
  }

  length() {
    return Math.sqrt(this.vx * this.vx + this.vy * this.vy);
  }

  lengthSquared() {
    return this.vx * this.vx + this.vy * this.vy;
  }

  normalize() {
    let len = Math.sqrt(this.vx * this.vx + this.vy * this.vy);
    if (len) {
      this.vx /= len;
      this.vy /= len;
    }
    return len;
  }

  rotate(angle) {
    let vx = this.vx;
    let vy = this.vy;
    let cosVal = Math.cos(angle);
    let sinVal = Math.sin(angle);
    this.vx = vx * cosVal - vy * sinVal;
    this.vy = vx * sinVal + vy * cosVal;
  }

  toString() {
    return '(' + this.vx.toFixed(3) + ',' + this.vy.toFixed(3) + ')';
  }
}

class Collision {
  constructor(targetArr) {
    this.arr = targetArr;
  }

  collideAll() {
    let vec = new Vector2d(0, 0);
    let dist;
    let obj1;
    let obj2;
    let c;
    let i;
    for (c = 0; c < this.arr.length; c++) {
      obj1 = this.arr[c];
      for (i = c + 1; i < this.arr.length; i++) {
        obj2 = this.arr[i];
        vec.vx = obj2.x - obj1.x;
        vec.vy = obj2.y - obj1.y;
        dist = vec.length();
        if (dist < obj1.r + obj2.r) {
          vec.normalize();
          vec.scale(obj1.r + obj2.r - dist);
          vec.negate();
          obj1.x += vec.vx;
          obj1.y += vec.vy;
          this.bounce(obj1, obj2);
        }
      }
    }
  }

  bounce(obj1, obj2) {
    let colnAngle = Math.atan2(obj1.y - obj2.y, obj1.x - obj2.x);
    let length1 = obj1.v.length();
    let length2 = obj2.v.length();
    let dirAngle1 = Math.atan2(obj1.v.vy, obj1.v.vx);
    let dirAngle2 = Math.atan2(obj2.v.vy, obj2.v.vx);
    let newVX1 = length1 * Math.cos(dirAngle1 - colnAngle);
    let newVX2 = length2 * Math.cos(dirAngle2 - colnAngle);
    obj1.v.vy = length1 * Math.sin(dirAngle1 - colnAngle);
    obj2.v.vy = length2 * Math.sin(dirAngle2 - colnAngle);
    obj1.v.vx = ((obj1.r - obj2.r) * newVX1 + (2 * obj2.r) * newVX2) / (obj1.r + obj2.r);
    obj2.v.vx = ((obj2.r - obj1.r) * newVX2 + (2 * obj1.r) * newVX1) / (obj1.r + obj2.r);
    obj1.v.rotate(colnAngle);
    obj2.v.rotate(colnAngle);
  }
}

class Stopwatch {
  constructor(time) {
    this.startTime = 0;
    this.running = false;
    this.elapsed = undefined;
  }

  start() {
    this.startTime = +new Date();
    this.elapsedTime = null;
    this.running = true;
  }

  stop() {
    this.elapsed = (+new Date()) - this.startTime;
    this.running = false;
  }

  getElapsedTime() {
    if (this.running) {
      return (+new Date()) - this.startTime;
    } else {
      return this.elapsed;
    }
  }

  isRunning() {
    return this.running;
  }

  reset() {
    this.elapsed = 0;
  }
}

class AnimationTimer {
  constructor(duration, timeWarp) {
    if (duration !== undefined) this.duration = duration;
    if (timeWarp !== undefined) this.timeWarp = timeWarp;
    this.stopwatch = new Stopwatch();
  }

  start() {
    this.stopwatch.start();
  }

  stop() {
    this.stopwatch.stop();
  }

  getElapsedTime() {
    const elapsedTime = this.stopwatch.getElapsedTime();
    const percentComplete = elapsedTime / this.duration;
    if (!this.stopwatch.running) return undefined;
    if (this.timeWarp === undefined) return elapsedTime;
    return elapsedTime * (this.timeWarp(percentComplete) / percentComplete);
  }

  isRunning() {
    return this.stopwatch.running;
  }

  isOver() {
    return this.stopwatch.getElapsedTime() > this.duration;
  }

  makeEaseIn(strength) {
    return function(percentComplete) {
      return Math.pow(percentComplete, strength * 2);
    }
  }

  makeEaseOut(strength) {
    return function(percentComplete) {
      return 1 - Math.pow(1 - percentComplete, strength * 2);
    }
  }

  makeEaseInOut() {
    return function(percentComplete) {
      return percentComplete - Math.sin(percentComplete * 2 * Math.PI) / (2 * Math.PI);
    }
  }

  makeElastic(passes) {
    passes = passes || default_elastic_passes;
    return function(percentComplete) {
      return ((1 - Math.cos(percentComplete * Math.PI * passes)) * (1 - percentComplete)) + percentComplete;
    }
  }

  makeBounce(bounces) {
    const fn = this.makeElastic(bounces);
    return function(percentComplete) {
      percentComplete = fn(percentComplete);
      return percentComplete <= 1 ? percentComplete : 2 - percentComplete;
    }
  }

  makeLinear() {
    return function(percentComplete) {
      return percentComplete;
    }
  }
}

class Angle {
  constructor(angle) {
    this.a = angle;
    this.rad = this.a * Math.PI / 180;
  }

  incDec(num) {
    this.a += num;
    this.rad = this.a * Math.PI / 180;
    return this.rad;
  }
}

let canvas;

let lastTime = 0;

const simplex = new SimplexNoise();

class Canvas {
  constructor(bool) {

    this.canvas = document.createElement("canvas");

    if (bool === true) {
      this.canvas.style.position = 'relative';
      this.canvas.style.display = 'block';
      this.canvas.style.backgroundColor = 'black';
      this.canvas.style.top = '0';
      this.canvas.style.left = '0';
      document.getElementsByTagName("body")[0].appendChild(this.canvas);
    }
    this.ctx = this.canvas.getContext("2d");
    this.width = this.canvas.width = window.innerWidth;
    this.height = this.canvas.height = window.innerHeight;

    this.mouseX = null;
    this.mouseY = null;
    this.mouseZ = null;

    this.number_of_shapes = 5;
    this.shapes_array = [];
  }
  

  init() {
    for (let i = 0; i < this.number_of_shapes; i++) {
      const f = new FractalRoot(this.ctx, this.width / 2, this.height / 2, i);
      this.shapes_array.push(f);
    }
  }

  render() {
    if (Math.random() < 0.001) this.ctx.clearRect(0, 0, this.width, this.height);
    for (let i = 0; i < this.shapes_array.length; i++) {
      this.shapes_array[i].drawShape();
    }

    window.requestAnimationFrame(() => {
      this.render();
    });
  }

  drawFPS() {
    const ctx = this.ctx;
    ctx.save();
    ctx.fillStyle = 'white';
    ctx.font = '16px sans-serif';
    ctx.textAlign = 'right';
    ctx.textBaseline = 'bottom';
    ctx.fillText(Utils.calcFPS() + ' FPS', this.width, this.height);
    ctx.restore();
  }
  
  resize() {
    this.shapes_array = [];
    this.width = this.canvas.width = window.innerWidth;
    this.height = this.canvas.height = window.innerHeight;
    this.init();
  }
}

class PointObj {
  constructor(ex, ey) {
    this.x = ex;
    this.y = ey;
  }
}

class FractalRoot {
  constructor(ctx, x, y, i) {
    this.random = Math.random();
    this.ctx = ctx;
    this.x = x;
    this.y = y;
    this.i = i;
    this.a = 0;
    this.r = 100;
    this.ri = this.r;
    this.maxLevels = 4;
    this.structFactor = null;
    this.rootBranch = null;
    this.numSlides = 5;
    this.pointArr = new Array(this.numSlides);
    this.angleStep = 360 / this.numSlides;
    this.init();
  }
  
  init(time, noise) {
    let count = 0;
    for (let i = 0; i < 360; i += this.angleStep) {
      let x = this.x + (this.r * Math.cos((this.a + i) * Math.PI / 180));
      let y = this.y + (this.r * Math.sin((this.a + i) * Math.PI / 180));
      this.pointArr[count] = new PointObj(x, y);
      count++;
    }
    this.rootBranch = new Branch(
      this.ctx,
      0,
      0,
      this.pointArr,
      this.structFactor,
      this.maxLevels,
      time,
      noise
    );
  }
  
  drawShape() {
    const time = Date.now() / 5000 * this.random;
    const noise = simplex.noise3D(this.x, this.y, time);
    this.structFactor = Math.sin(time) * noise * 3;
    this.r = Math.sin(time) * noise * this.ri + 100;
    this.init(time, noise);
    this.rootBranch.drawMe();
    this.a += noise;
  }
}

class Branch {
  constructor(ctx, lev, n, points, factor, max, time, noise) {
    this.ctx = ctx;
    this.level = lev;
    this.num = n;
    this.outerPoints = points;
    this.structFactor = factor;
    this.maxLevels = max;
    this.time = time;
    this.noise = noise;
    this.myBranches = [];
    this.midPoints = this.calcMidPoints();
    this.projPoints = this.calcStructPoints();
    if (this.level + 1 < this.maxLevels) {
      let childBranch = new Branch(
        this.ctx,
        this.level + 1,
        0,
        this.projPoints,
        this.structFactor,
        this.maxLevels,
        this.time,
        this.noise
      );
      this.myBranches.push(childBranch);
      for (let i = 0; i < this.outerPoints.length; i++) {
        let n = i - 1;
        if (n < 0) {
          n += this.outerPoints.length;
        }
        let newPoints = [
          this.projPoints[i],
          this.midPoints[i],
          this.outerPoints[i],
          this.midPoints[n],
          this.projPoints[n]
        ];
        let childBranch = new Branch(
          this.ctx,
          this.level + 1,
          i + 1,
          newPoints,
          this.structFactor,
          this.maxLevels,
          this.time,
          this.noise
        );
        this.myBranches.push(childBranch);
      }
    }
  }
  
  drawMe() {
    const ctx = this.ctx;
    ctx.save();
    ctx.lineWidth = 0.1;

    ctx.strokeStyle = 'hsl(' + 360 * (this.noise * 2) + ', 80% ,60%)';

    ctx.beginPath();
    ctx.moveTo(this.outerPoints[0].x,this.outerPoints[0].y);
    for (let i = 1; i < this.outerPoints.length; i++) {
      ctx.lineTo(this.outerPoints[i].x, this.outerPoints[i].y);
    }
    ctx.closePath();
    ctx.stroke();
    ctx.restore();
    for (let i = 0; i < this.myBranches.length; i++) {
      this.myBranches[i].drawMe();
    }
  }
  
  calcMidPoints() {
    let mpArray = [];
    for (let i = 0; i < this.outerPoints.length; i++) {
      let n = i + 1;
      if (n === this.outerPoints.length) {
        n = 0;
      }
      let thisMp = this.calcMidPoint(this.outerPoints[i], this.outerPoints[n]);
      mpArray[i] = thisMp;
    }
    return mpArray;
  }
  
  calcMidPoint(end1, end2) {
    let mx, my;
    if (end1.x > end2.x) {
      mx = end2.x + ((end1.x - end2.x) / 2);
    } else {
      mx = end1.x + ((end2.x - end1.x) / 2);
    }
    if (end1.y > end2.y) {
      my = end2.y + ((end1.y - end2.y) / 2);
    } else {
      my = end1.y + ((end2.y - end1.y) / 2);
    }
    return new PointObj(mx, my);
  }
  
  calcStructPoints() {
    let structArray = new Array(this.midPoints.length);
    for (let i = 0; i < this.midPoints.length; i++) {
      let n = i + 3;
      if (n >= this.midPoints.length) {
        n -= this.midPoints.length;
      }
      let thisSP = this.calcProjPoint(this.midPoints[i], this.outerPoints[n]);
      structArray[i] = thisSP;
    }
    return structArray;
  }
  
  calcProjPoint(mp, op) {
    let px, py, adj, opp;
    if (op.x > mp.x) {
      opp = op.x - mp.x;
    } else {
      opp = mp.x - op.x;
    }
    if (op.y > mp.y) {
      adj = op.y - mp.y;
    } else {
      adj = mp.y - op.y;
    }
    if (op.x > mp.x) {
      px = mp.x + (opp * this.structFactor);
    } else {
      px = mp.x - (opp * this.structFactor);
    }
    if (op.y > mp.y) {
      py = mp.y + (adj * this.structFactor);
    } else {
      py = mp.y - (adj * this.structFactor);
    }
    return new PointObj(px, py);
  }
}

(() => {
  'use strict';
  window.addEventListener('load', () => {
    canvas = new Canvas(true);
    canvas.init();
    canvas.render();

    window.addEventListener("resize", () => {
      canvas.resize();
    }, false);
  }, false);
})();

[simplex-noise.min.js]

        这段代码定义了一个名为 SimplexNoise 的 JavaScript 类,用于生成多维的简单噪声(Simplex Noise)。简单噪声是一种用于生成自然外观的纹理或形状的数学函数,常用于计算机图形学、游戏开发和数据可视化等领域。

        以下是对代码中各个部分的总结:

  1. 初始化和配置

    • 定义了一系列的常量(如 retao),这些常量用于后续的噪声计算。
    • i 函数是一个工厂方法,用于创建 SimplexNoise 实例。它接受一个参数,该参数可以是一个函数或者一个数字。如果参数是一个函数,它会调用该函数来生成随机数;如果参数是数字,它会使用这个数字来初始化噪声生成器的随机数种子。
  2. Permutation Table(置换表)

    • n 函数用于生成置换表,这是一个包含随机排列的字节数组。置换表用于在噪声计算中引入随机性。
    • i.prototype 对象包含了噪声生成的核心方法和数据,如 grad3 和 grad4 梯度数组,以及 noise2Dnoise3D 和 noise4D 方法,用于计算二维、三维和四维的简单噪声。
  3. 噪声计算方法

    • noise2D 方法接受两个参数 t 和 a,分别代表二维空间中的 x 和 y 坐标,返回一个介于 -1 和 1 之间的噪声值。
    • noise3D 方法接受三个参数 re 和 a,分别代表三维空间中的 xy 和 z 坐标,同样返回一个介于 -1 和 1 之间的噪声值。
    • noise4D 方法接受四个参数 ret 和 i,分别代表四维空间中的四个坐标轴,返回一个噪声值。
  4. 兼容性和模块导出

    • 代码的最后部分检查了 defineexports 和 window 对象是否存在,以确定如何导出 SimplexNoise 类。如果使用 AMD(异步模块定义)规范,则通过 define 函数导出;如果使用 CommonJS 规范(如 Node.js 环境),则通过 module.exports 导出;如果运行在浏览器环境中,则将 SimplexNoise 添加到 window 对象上。

        总的来说,这段代码提供了一个完整的简单噪声生成器实现,可以用于各种需要自然随机性的场景。通过提供不同维度的噪声计算方法,它为开发者提供了灵活性,可以根据具体需求选择合适的噪声维度。

!function(){"use strict";var r=.5*(Math.sqrt(3)-1),e=(3-Math.sqrt(3))/6,t=1/6,a=(Math.sqrt(5)-1)/4,o=(5-Math.sqrt(5))/20;function i(r){var e;e="function"==typeof r?r:r?function(){var r=0,e=0,t=0,a=1,o=(i=4022871197,function(r){r=r.toString();for(var e=0;e<r.length;e++){var t=.02519603282416938*(i+=r.charCodeAt(e));t-=i=t>>>0,i=(t*=i)>>>0,i+=4294967296*(t-=i)}return 2.3283064365386963e-10*(i>>>0)});var i;r=o(" "),e=o(" "),t=o(" ");for(var n=0;n<arguments.length;n++)(r-=o(arguments[n]))<0&&(r+=1),(e-=o(arguments[n]))<0&&(e+=1),(t-=o(arguments[n]))<0&&(t+=1);return o=null,function(){var o=2091639*r+2.3283064365386963e-10*a;return r=e,e=t,t=o-(a=0|o)}}(r):Math.random,this.p=n(e),this.perm=new Uint8Array(512),this.permMod12=new Uint8Array(512);for(var t=0;t<512;t++)this.perm[t]=this.p[255&t],this.permMod12[t]=this.perm[t]%12}function n(r){var e,t=new Uint8Array(256);for(e=0;e<256;e++)t[e]=e;for(e=0;e<255;e++){var a=e+~~(r()*(256-e)),o=t[e];t[e]=t[a],t[a]=o}return t}i.prototype={grad3:new Float32Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),grad4:new Float32Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]),noise2D:function(t,a){var o,i,n=this.permMod12,f=this.perm,s=this.grad3,v=0,h=0,l=0,u=(t+a)*r,d=Math.floor(t+u),p=Math.floor(a+u),M=(d+p)*e,m=t-(d-M),c=a-(p-M);m>c?(o=1,i=0):(o=0,i=1);var y=m-o+e,w=c-i+e,g=m-1+2*e,A=c-1+2*e,x=255&d,q=255&p,D=.5-m*m-c*c;if(D>=0){var S=3*n[x+f[q]];v=(D*=D)*D*(s[S]*m+s[S+1]*c)}var U=.5-y*y-w*w;if(U>=0){var b=3*n[x+o+f[q+i]];h=(U*=U)*U*(s[b]*y+s[b+1]*w)}var F=.5-g*g-A*A;if(F>=0){var N=3*n[x+1+f[q+1]];l=(F*=F)*F*(s[N]*g+s[N+1]*A)}return 70*(v+h+l)},noise3D:function(r,e,a){var o,i,n,f,s,v,h,l,u,d,p=this.permMod12,M=this.perm,m=this.grad3,c=(r+e+a)*(1/3),y=Math.floor(r+c),w=Math.floor(e+c),g=Math.floor(a+c),A=(y+w+g)*t,x=r-(y-A),q=e-(w-A),D=a-(g-A);x>=q?q>=D?(s=1,v=0,h=0,l=1,u=1,d=0):x>=D?(s=1,v=0,h=0,l=1,u=0,d=1):(s=0,v=0,h=1,l=1,u=0,d=1):q<D?(s=0,v=0,h=1,l=0,u=1,d=1):x<D?(s=0,v=1,h=0,l=0,u=1,d=1):(s=0,v=1,h=0,l=1,u=1,d=0);var S=x-s+t,U=q-v+t,b=D-h+t,F=x-l+2*t,N=q-u+2*t,C=D-d+2*t,P=x-1+.5,T=q-1+.5,_=D-1+.5,j=255&y,k=255&w,z=255&g,B=.6-x*x-q*q-D*D;if(B<0)o=0;else{var E=3*p[j+M[k+M[z]]];o=(B*=B)*B*(m[E]*x+m[E+1]*q+m[E+2]*D)}var G=.6-S*S-U*U-b*b;if(G<0)i=0;else{var H=3*p[j+s+M[k+v+M[z+h]]];i=(G*=G)*G*(m[H]*S+m[H+1]*U+m[H+2]*b)}var I=.6-F*F-N*N-C*C;if(I<0)n=0;else{var J=3*p[j+l+M[k+u+M[z+d]]];n=(I*=I)*I*(m[J]*F+m[J+1]*N+m[J+2]*C)}var K=.6-P*P-T*T-_*_;if(K<0)f=0;else{var L=3*p[j+1+M[k+1+M[z+1]]];f=(K*=K)*K*(m[L]*P+m[L+1]*T+m[L+2]*_)}return 32*(o+i+n+f)},noise4D:function(r,e,t,i){var n,f,s,v,h,l,u,d,p,M,m,c,y,w,g,A,x,q=this.perm,D=this.grad4,S=(r+e+t+i)*a,U=Math.floor(r+S),b=Math.floor(e+S),F=Math.floor(t+S),N=Math.floor(i+S),C=(U+b+F+N)*o,P=r-(U-C),T=e-(b-C),_=t-(F-C),j=i-(N-C),k=0,z=0,B=0,E=0;P>T?k++:z++,P>_?k++:B++,P>j?k++:E++,T>_?z++:B++,T>j?z++:E++,_>j?B++:E++;var G=P-(l=k>=3?1:0)+o,H=T-(u=z>=3?1:0)+o,I=_-(d=B>=3?1:0)+o,J=j-(p=E>=3?1:0)+o,K=P-(M=k>=2?1:0)+2*o,L=T-(m=z>=2?1:0)+2*o,O=_-(c=B>=2?1:0)+2*o,Q=j-(y=E>=2?1:0)+2*o,R=P-(w=k>=1?1:0)+3*o,V=T-(g=z>=1?1:0)+3*o,W=_-(A=B>=1?1:0)+3*o,X=j-(x=E>=1?1:0)+3*o,Y=P-1+4*o,Z=T-1+4*o,$=_-1+4*o,rr=j-1+4*o,er=255&U,tr=255&b,ar=255&F,or=255&N,ir=.6-P*P-T*T-_*_-j*j;if(ir<0)n=0;else{var nr=q[er+q[tr+q[ar+q[or]]]]%32*4;n=(ir*=ir)*ir*(D[nr]*P+D[nr+1]*T+D[nr+2]*_+D[nr+3]*j)}var fr=.6-G*G-H*H-I*I-J*J;if(fr<0)f=0;else{var sr=q[er+l+q[tr+u+q[ar+d+q[or+p]]]]%32*4;f=(fr*=fr)*fr*(D[sr]*G+D[sr+1]*H+D[sr+2]*I+D[sr+3]*J)}var vr=.6-K*K-L*L-O*O-Q*Q;if(vr<0)s=0;else{var hr=q[er+M+q[tr+m+q[ar+c+q[or+y]]]]%32*4;s=(vr*=vr)*vr*(D[hr]*K+D[hr+1]*L+D[hr+2]*O+D[hr+3]*Q)}var lr=.6-R*R-V*V-W*W-X*X;if(lr<0)v=0;else{var ur=q[er+w+q[tr+g+q[ar+A+q[or+x]]]]%32*4;v=(lr*=lr)*lr*(D[ur]*R+D[ur+1]*V+D[ur+2]*W+D[ur+3]*X)}var dr=.6-Y*Y-Z*Z-$*$-rr*rr;if(dr<0)h=0;else{var pr=q[er+1+q[tr+1+q[ar+1+q[or+1]]]]%32*4;h=(dr*=dr)*dr*(D[pr]*Y+D[pr+1]*Z+D[pr+2]*$+D[pr+3]*rr)}return 27*(n+f+s+v+h)}},i._buildPermutationTable=n,"undefined"!=typeof define&&define.amd&&define(function(){return i}),"undefined"!=typeof exports?exports.SimplexNoise=i:"undefined"!=typeof window&&(window.SimplexNoise=i),"undefined"!=typeof module&&(module.exports=i)}();

效果图

总结

  1. HTML

    • 定义了一个网页的基本结构,包括DOCTYPE声明、html、head和body标签。
    • 在head部分,设置了页面字符集为UTF-8,并定义了网页标题。
    • 引入了一个外部CSS文件normalize.min.css用于样式重置,以及两个JavaScript文件simplex-noise.min.jsscript.js,这些文件将用于网页的样式和行为。
  2. CSS

    • 包含了一系列的CSS规则,用于重置和标准化HTML元素的默认样式,以确保在不同浏览器中具有一致的表现。
    • 涉及的样式包括按钮、表单元素、媒体元素等的显示方式、字体、外边距、内边距和边框样式。
    • 还包括了一些针对HTML5新语义元素的样式设置,如articleasidefooter等。
  3. JavaScript

    • 定义了一系列的类和方法,用于生成随机数、颜色、渐变色、计算帧率(FPS)、处理向量运算、碰撞检测、计时和动画定时。
    • Utils类提供了生成随机数和颜色的方法,以及创建渐变色和计算FPS的功能。
    • Vector2d类表示二维向量,提供了一系列向量运算的方法,如缩放、加法、减法、取反、归一化和旋转。
    • Collision类处理对象之间的碰撞检测和碰撞反弹。
    • Stopwatch类用于计时,提供了开始、停止、获取经过时间、检查是否正在运行和重置计时器的方法。
    • AnimationTimer类用于动画定时,支持不同的缓动函数,如Ease-In、Ease-Out、Ease-In-Out、Elastic和Bounce。
    • Angle类用于表示角度,可以增加或减少角度值,并将其转换为弧度。
    • Canvas类用于创建和管理分形图形的绘制,提供了初始化、渲染、绘制帧率和响应窗口大小变化的方法。
    • PointObjFractalRoot类用于生成分形图形的结构和绘制。
    • Branch类表示分形中的一个分支,负责计算分支的中间点、结构点,并绘制分支。
    • 最后,自执行函数用于初始化Canvas类,并设置窗口大小变化的事件监听器。
    • 另外,还有一个SimplexNoise类,用于生成多维的简单噪声,这在计算机图形学中非常有用,可以用于创建自然纹理或形状。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1587423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TFT显示屏驱动

REVIEW 已经学习过VGA 时序与实现-CSDN博客 VGA 多分辨率-CSDN博客 今天就来让TFT屏显示一下 小梅哥视频&#xff1a;24 RGB TFT显示屏原理与驱动实现_哔哩哔哩_bilibili 1. 设置显示屏参数与时钟 注意到VGA_parameter.v中&#xff0c;不懂得分辨率对应于不同的频率&#xff…

Vue3学习04 组件通信

Vue3学习04 组件通信 组件通信props 父 ↔ 子自定义事件 子 > 父mitt 任意组件间通信v-model 父↔子$attrs 祖↔孙$refs、$parent案例的完整代码ref注意点 provide、inject 祖↔孙piniaslot① 默认插槽② 具名插槽③ 作用域插槽 组件通信 Vue3组件通信和Vue2的区别&#xf…

K8S之Controller

我们在回顾下pod的启动流程&#xff1a; 用户通过kubectl&#xff0c;向api-server 发起请求api-server接受请求&#xff0c;并将数据写入etcdkube-scheduler通过watch检测到未绑定node 的pod&#xff0c;调度pod到某一node上&#xff0c;并通知给api-server&#xff0c;api-se…

Centos7 k8s 集群 - Rook Ceph 安装

环境准备 基础环境 系统名称操作系统CPU内存硬盘Kubernete 版本Docker版本IPmasterCentos74c4gsdb 20G1.17.023.0.1192.168.1.128node01Centos74c4gsdb 20G1.17.023.0.1192.168.1.129node02Centos74c4gsdb 20G1.17.023.0.1192.168.1.130node03Centos74c4gsdb 20G1.17.023.0.1…

计算两个时间段的差值

计算两个时间段的差值 运行效果&#xff1a; 代码实现&#xff1a; #include<stdio.h>typedef struct {int h; // 时int m; // 分int s; // 秒 }Time;void fun(Time T[2], Time& diff) {int sum_s[2] { 0 }; for (int i 0; i < 1; i) { // 统一为秒数sum_s[…

NI-LabView的DAQ缺少或丢失的解决办法(亲测有效)

DAQmx在Labview中不显示或缺失 问题&#xff1a;在NI Packasge Manager安装完DAQ后在labview中不显示控件解决办法 问题&#xff1a;在NI Packasge Manager安装完DAQ后在labview中不显示控件 在打开测量I/O时&#xff0c;见不到 DAQmx&#xff0c;或者在Express中见不到DAQ助手…

绝地求生:PUBG×杜卡迪联名上线!参与投稿评论赢取精美好礼

PUBG杜卡迪联名活动游戏内现已正式上线&#xff01;我们诚邀与您一起在开拓未知战场和书写新历史的过程中&#xff0c;与杜卡迪一同实现您的极速梦想&#xff01; 在本次的杜卡迪工坊中&#xff0c;更是包含了具备标志性红色在内的6种颜色供您自由选择&#xff0c;一起自由驰骋…

微软电子密码账户严重漏洞???

微软电子密码严重漏洞&#xff1f;&#xff1f;&#xff1f; 如图有网络安全的大佬知道这是怎么回事吗&#xff1f;&#xff1f;&#xff1f;我的猜想 如图 当我登录bilibili网页的时候&#xff0c;我发现微软账号电子钱包保存的密码突然出现了许多我没有拥有的账号&#xff0…

【vue】ref 和 reactive 对比

ref&#xff1a;存储单个数据&#xff0c;如数值&#xff0c;字符串reactive&#xff1a;存储复杂数据&#xff0c;如对象&#xff0c;数组 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"vie…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Android Studio开发学习(七)———RelativeLayout(相对布局)

在上期中我们对LinearLayout进行了详细的解析&#xff0c;LinearLayout也是我们用的比较多的一个布局,更多的时候更钟情于它的 weight(权重) 属性&#xff0c;等比例划分&#xff0c;对屏幕适配还是 帮助蛮大的;但是使用LinearLayout的时候也有一个问题&#xff0c;就是当界面比…

keepalived2.2.8+drbd9+nfs高可用存储部署

目录 一.本文基于上一篇文章keepalived环境来做的&#xff0c;主机信息如下 二.为两台虚拟机准备添加一块新硬盘设备 三.安装drbd9 1.使用扩展源的rpm包来下载 2.创建资源并挂载到新增的硬盘 3.主设备升级身份 4.主备两个设备手动切换身份演示 四.安装配置nfs 五.安装…

从 SQLite 3.4.2 迁移到 3.5.0(二十)

返回&#xff1a;SQLite—系列文章目录 上一篇:SQLite---调试提示&#xff08;十九&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 ​ SQLite 版本 3.5.0 &#xff08;2007-09-04&#xff09; 引入了一个新的操作系统接口层&#xff0c; 与所有先前版本的 SQLi…

IDEA2023 开发环境配置

目录 1. 关闭IDEA自动更新1.2 IDEA 新版样式切换 2. Maven配置2.1本地仓库优先加载2.2 maven.config配置文件中 3. 全局配置JDK4. 配置文件编码:UTF-85. 开启自动编译&#xff08;全局配置&#xff09;6. 开启自动导包7. 开启鼠标悬浮&#xff08;提示文档信息&#xff09;8. 设…

jenkins 启动linux节点时 控制台中文显示问号乱码

新增一个jenkins节点时&#xff0c;遇到了控制台中文输出问号的问题。 网上各种配置jenkins的全局变量&#xff0c;都不行。 最终是 节点列表 ->对应节点 -> 启动方式 -> 高级 添加JVM选项 -Dfile.encodingUTF-8

HarmonyOS实战开发-WebSocket的使用。

介绍 本示例展示了WebSocket的使用&#xff0c;包括客户端与服务端的连接和断开以及客户端数据的接收和发送。 WebSocket连接&#xff1a;使用WebSocket建立服务器与客户端的双向连接&#xff0c;需要先通过createWebSocket方法创建WebSocket对象&#xff0c;然后通过connect…

2、JVM内存模型深度解析

JVM整体结构及内存模型 根据 JVM 规范&#xff0c;JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。 JVM分为五大模块&#xff1a; 类装载器子系统 、 运行时数据区 、 执行引擎 、 本地方法接口 和 垃圾收集模块 。 方法区Java8之后的变化 移除了 Pe…

每日一题---OJ题: 链表的回文结构

片头 嗨! 小伙伴们,大家好! 今天我们来一起学习这道OJ题--- 链表的回文结构 嗯...这道题好像不是很难,我们来分析分析 举个例子: 我们可以看到,上图中的两个链表都是回文结构: 即链表的回文结构是指一个链表中的结点值从前往后读和从后往前读都是一样的结构。也就是说&#xf…

蓝桥杯 — —灵能传输

灵能传输 友情链接&#xff1a;灵能传输 题目&#xff1a; 输入样例&#xff1a; 3 3 5 -2 3 4 0 0 0 0 3 1 2 3输出样例&#xff1a; 3 0 3思路&#xff1a; 题目大意&#xff1a;给出一个数组&#xff0c;每次选择数组中的一个数&#xff08;要求不能是第一个数与最后一个…

Rust语言入门第二篇-Cargo教程

文章目录 Rust语言入门第二篇-Cargo教程一&#xff0c;Cargo 是什么二&#xff0c;Cargo教程Cargo.toml文件src/main.rs 文件构建并运行Cargo项目 Rust语言入门第二篇-Cargo教程 本节提供对cargo命令行工具的快速了解。我们演示了它为我们生成新包的能力&#xff0c;它在包内编…