【HTML】简单制作一个分形动画

news2024/11/27 14:30:49

  目录

前言

开始       

HTML部分

效果图

​编辑​编辑​编辑​编辑总结


前言

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

开始       

        首先新建文件夹,创建一个文本文档,其中HTML的文件名改为[index.html],创建好后右键用文本文档打开,再把下面相对应代码填入后保存即可。

HTML部分

       这段HTML代码创建了一个动画线分形艺术作品,其核心特点和功能可以总结如下:

  1. 视觉风格:页面背景设置为黑色,提供了一个适合展示分形图形的暗色背景。分形的线条颜色从蓝色渐变到紫色,增加了视觉效果的丰富性。

  2. Canvas 绘图:使用<canvas>元素作为绘图区域,通过JavaScript中的2D上下文来绘制分形图形。

  3. 分形逻辑:定义了一个Shape构造函数来创建分形形状,每个形状由一系列的线段组成,并且每个形状可以递归地生成更小的子形状,以达到分形效果。

  4. 动画效果:通过animate函数实现动画效果,该函数会在每一帧更新分形图形的位置和大小,并递归生成新的形状。动画的持续时间和速度都是可配置的。

  5. 颜色变化:随着动画的进行,分形线条的颜色会逐渐变化,从一种颜色过渡到另一种颜色,增加了动态视觉效果。

  6. 响应式设计:代码中包含了事件监听器,使得当浏览器窗口大小改变时,canvas元素的尺寸也会相应地调整,确保分形图形能够适应不同的屏幕尺寸。

  7. 性能优化:为了避免在每一帧都清除整个画布,代码使用了globalCompositeOperation属性设置为"lighter",这样新绘制的形状会与画布上已有的内容进行叠加,从而提高了动画的性能。

整体而言,这段代码展示了如何在网页上使用HTML5的canvas元素和JavaScript来创建一个动态、响应式的分形艺术作品。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>动画线分形</title>

<style>
body {
	background-color:black; /* 设置背景颜色为黑色 */
	margin:0; /* 移除默认边距 */
	overflow:hidden; /* 隐藏滚动条 */
}
</style>
</head>
<body>

<canvas id="canvas"></canvas> <!-- 定义一个canvas元素用于绘制内容 -->

<script>
// 定义黄金比例的常量
const PHI = (1 + Math.sqrt(5)) / 2; // 1.618033988749895
// 根据浏览器调整生成的分形深度
const maxGeneration = (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) ? 5 : 6,
// 每帧的持续时间
frameDuration = 1000 / 60,
// 动画总时长
duration = 3000,
// 旋转速度
rotationSpeed = 0.3,
// 动画总帧数
totalIterations = Math.floor(duration / frameDuration),
// 最大基础尺寸
maxBaseSize = 100,
// 基础尺寸变化速度
baseSizeSpeed = 0.02;

// 获取canvas元素及其上下文
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
// 获取当前视口的宽度和高度
canvasWidth = document.documentElement.clientWidth,
canvasHeight = document.documentElement.clientHeight,
// 定义一个数组用于存储分形形状
shapes = [],
// 定义尺寸变化
sizeVariation,
// 当前迭代次数
iteration = 0,
// 动画方向
animationDirection = 1,
// 尺寸变化范围
sizeVariationRange = .15,
// 基础旋转角度
baseRotation = 0,
// 基础尺寸
baseSize = 50,
// 定义颜色变化的初始值
c1 = 43,
c1S = 1,
c2 = 205,
c2S = 1,
c3 = 255,
c3S = 1;

// 设置canvas元素的尺寸以匹配视口大小
canvas.setAttribute("width", canvasWidth);
canvas.setAttribute("height", canvasHeight);

// 定义Shape构造函数,用于创建分形形状
function Shape(gen, x, y, size, rotation) {
  this.generation = gen;
  this.size = size;
  this.rotation = -rotation;
  this.start = {
    x: x,
    y: y
  };
  // 计算形状的三个端点坐标
  this.end = {
    x_1: this.start.x + Math.cos(degToRad(this.rotation)) * this.size,
    y_1: this.start.y + Math.sin(degToRad(this.rotation)) * this.size,
    x_2: this.start.x + Math.cos(degToRad(this.rotation + 360 / 3)) * this.size,
    y_2: this.start.y + Math.sin(degToRad(this.rotation + 360 / 3)) * this.size,
    x_3:
      this.start.x +
      Math.cos(degToRad(this.rotation + 360 / 3 * 2)) * this.size,
    y_3:
      this.start.y + Math.sin(degToRad(this.rotation + 360 / 3 * 2)) * this.size
  };

  // 初始化形状,生成子形状
  this.init();
}

// Shape的初始化方法
Shape.prototype.init = function() {
  if (this.generation < maxGeneration) {
    var gen = this.generation + 1,
      newSize = this.size * sizeVariation,
      newRotation = this.rotation;

    // 递归创建子形状
    shapes.push(
      new Shape(gen, this.end.x_1, this.end.y_1, newSize, newRotation)
    );
    shapes.push(
      new Shape(gen, this.end.x_2, this.end.y_2, newSize, newRotation)
    );
    shapes.push(
      new Shape(gen, this.end.x_3, this.end.y_3, newSize, newRotation)
    );
  }
  // 绘制当前形状
  this.draw();
};

// 绘制形状的方法
Shape.prototype.draw = function() {
  ctx.beginPath();
  ctx.moveTo(this.start.x, this.start.y);
  // 绘制三条线段
  ctx.lineTo(this.end.x_1, this.end.y_1);
  ctx.moveTo(this.start.x, this.start.y);
  ctx.lineTo(this.end.x_2, this.end.y_2);
  ctx.moveTo(this.start.x, this.start.y);
  ctx.lineTo(this.end.x_3, this.end.y_3);
  // 设置线条颜色,透明度随迭代次数增加而降低
  ctx.strokeStyle =
    "rgba(" + c1 + "," + c2 + "," + c3 + "," + 1 / this.generation / 5 + ")";
  ctx.stroke();
  // 填充颜色(此处被注释掉)
  //ctx.fill();
};

// 动画函数,用于更新和绘制分形
function animate() {
  // 清除画布(此处被注释掉,因为我们使用其他方法实现透明效果)
  //ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  // 设置合成操作为源覆盖,以实现透明效果
  ctx.globalCompositeOperation = "source-over";
  // 用半透明的黑色填充背景,创建透明效果
  ctx.fillStyle = "rgba(0,0,0,.1)";
  ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  // 恢复合成操作为lighter,用于绘制新形状
  ctx.globalCompositeOperation = "lighter";
  // 清空形状数组
  shapes = [];
  // 创建一个新的分形形状
  shapes.push(
    new Shape(0, canvasWidth / 2, canvasHeight / 2, baseSize, baseRotation)
  );

  // 改变颜色
  changeColor();
  // 增加迭代次数
  iteration++;
  // 调整基础尺寸
  if (baseSize < maxBaseSize) baseSize += baseSizeSpeed;
  // 更新基础旋转角度
  baseRotation += rotationSpeed;
  // 调整尺寸变化
  sizeVariation = easeInOutSine(
    iteration,
    1 - sizeVariationRange * animationDirection,
    sizeVariationRange * 2 * animationDirection,
    totalIterations
  );
  // 如果迭代次数达到总帧数,则重置迭代次数并反转动画方向
  if (iteration >= totalIterations) {
    iteration = 0;
    animationDirection *= -1;
  }
  // 请求下一帧动画
  requestAnimationFrame(animate);
}

// 度转弧度函数
function degToRad(deg) {
  return Math.PI / 180 * deg;
}

// 缓动函数,用于在动画中平滑变化尺寸
function easeInOutSine(
  currentIteration,
  startValue,
  changeInValue,
  totalIterations
) {
  return (
    changeInValue /
      2 *
      (1 - Math.cos(Math.PI * currentIteration / totalIterations)) +
    startValue
  );
}

// 改变颜色的函数
function changeColor() {
  if (c1 == 0 || c1 == 255) c1S *= -1;
  if (c2 == 0 || c2 == 255) c2S *= -1;
  if (c3 == 0 || c3 == 255) c3S *= -1;
  c1 += 1 * c1S;
  c2 += 1 * c2S;
  c3 += 1 * c3S;
}

// 初始化canvas的合成操作和线条颜色
ctx.globalCompositeOperation = "lighter";
animate();

// 监听窗口大小变化事件,调整canvas尺寸
window.addEventListener("resize", function() {
  canvasWidth = document.documentElement.clientWidth;
  canvasHeight = document.documentElement.clientHeight;
  // 重新设置canvas元素的尺寸
  canvas.setAttribute("width", canvasWidth);
  canvas.setAttribute("height", canvasHeight);
  // 设置线条颜色
  ctx.strokeStyle = "rgba(66,134,240,.3)";
  // 保持合成操作为lighter
  ctx.globalCompositeOperation = "lighter";
});
</script>

</body>
</html>

效果图

总结

        这段HTML代码实现了一个动态的分形艺术动画,它在网页上展示了一个基于数学分形原理的视觉图案。页面背景设置为黑色,以突出显示绘制在<canvas>元素上的分形图形。这些图形通过递归的方式生成,每个基本形状会根据预设的参数产生更小的副本,从而形成复杂的分形结构。

        动画的核心是通过JavaScript编写的,其中定义了一个Shape类,负责创建和绘制单个分形形状。每个Shape对象包含生成的代数、大小、旋转角度和端点坐标。在初始化过程中,如果当前形状的代数小于最大代数限制,它将生成三个新的子形状,这些子形状的大小会根据一个变化范围进行调整,从而产生分形的递归效果。

        动画的绘制是通过animate函数实现的,该函数会在每一帧更新所有形状的位置和大小,并根据需要递归生成新的形状。动画使用了requestAnimationFrame来平滑地进行,确保了流畅的视觉效果。为了增加视觉效果,动画中的形状颜色会随时间变化,从蓝色过渡到紫色,并在每次迭代中调整透明度,以产生深度感。

        此外,代码还考虑了不同设备的屏幕尺寸,通过监听窗口大小变化事件来动态调整<canvas>元素的尺寸,确保动画在不同设备上都能正确显示。为了提高性能,动画在绘制新形状时不会清除整个画布,而是使用"lighter"合成操作模式,让新绘制的形状与画布上已有的内容叠加,从而减少了不必要的重绘操作。

        简单来说就是通过结合HTML5的<canvas>元素和JavaScript编程,创造了一个视觉上吸引人、响应式且性能优化的分形动画作品。

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

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

相关文章

Python中csr_matrix的两种初始化方法

本文以csr_matrix为例来说明sparse矩阵的使用方法&#xff0c;其他类型的sparse矩阵可以参考https://docs.scipy.org/doc/scipy/reference/sparse.html csr_matrix是Compressed Sparse Row matrix的缩写组合&#xff0c;下面介绍其两种初始化方法 csr_matrix((data, (row_ind…

京东云16核64G云服务器租用优惠价格500元1个月、5168元一年,35M带宽

京东云16核64G云服务器租用优惠价格500元1个月、5168元一年&#xff0c;35M带宽&#xff0c;配置为&#xff1a;16C64G-450G SSD系统盘-35M带宽-8000G月流量 华北-北京&#xff0c;京东云活动页面 yunfuwuqiba.com/go/jd 活动链接打开如下图&#xff1a; 京东云16核64G云服务器…

Python-VBA函数之旅-bool函数

目录 1、bool函数 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、相关文章&#xff1a; 个人主页&#xff1a;非风V非雨-CSDN博客 bool函数(Boolean Function)用于将给定的值转换为布尔值(True或False)。常见的应用场景有&#xff1a; 1、条件判断&#xff1a;bool()…

vulhub之ActiveMQ篇

ActiveMQ的web控制台分三个应用&#xff0c;admin、api和fileserver&#xff0c;其中admin是管理员页面&#xff0c;api是接口&#xff0c;fileserver是储存文件的接口&#xff1b;admin和api都需要登录后才能使用&#xff0c;fileserver无需登录。fileserver是一个RESTful API…

冻干可以天天给成年猫吃吗?5大好口碑不翻车专家直入!

近年来&#xff0c;冻干猫粮因其高品质而备受喜爱&#xff0c;吸引了无数猫主人的目光&#xff0c;像我这样的资深养猫人早已开始选择冻干喂养。新手养猫就弄不明白了&#xff0c;什么是冻干猫粮呢&#xff1f;冻干可以天天给成年猫吃吗&#xff1f; 一、什么是冻干 简单来说&…

【微服务】------微服务架构技术栈

目前微服务早已火遍大江南北&#xff0c;对于开发来说&#xff0c;我们时刻关注着技术的迭代更新&#xff0c;而项目采用什么技术栈选型落地是开发、产品都需要关注的事情&#xff0c;该篇博客主要分享一些目前普遍公司都在用的技术栈&#xff0c;快来分享一下你当前所在用的技…

2024 Flutter iOS 隐私清单上线,5 月 1 号最后期限,你收到 「ITMS-91053」 了吗?

2023 年底的时候&#xff0c;我就发过了 《Flutter 上了 Apple 第三方重大列表&#xff0c;2024 春季 iOS 的隐私清单究竟是什么&#xff1f;》 相关内容&#xff0c;如果你还对隐私清单等相关要求不了解&#xff0c;建议先看看前文。 如果你已经有相关了解&#xff0c;并且近…

【LAMMPS学习】七、加速性能(4)加速器包

7. 加速性能 7.1.基准测试 7.2.测试性能 7.3.通用技巧 7.4.加速器包 LAMMPS 中添加了各种pair_style、fixes、compute 和其他命令的加速版本&#xff0c;其运行速度通常比标准非加速版本更快。有些需要您的系统上存在适当的硬件&#xff0c;例如GPU 或 Intel Xeon Phi 协处…

数据库的负载均衡,高可用实验

一 高可用负载均衡集群数据库实验 1.实验拓扑图 2.实验准备(同一LAN区段)&#xff08;ntp DNS&#xff09; 客户端&#xff1a;IP&#xff1a;192.168.1.5 下载&#xff1a;MariaDB 负载均衡器&#xff1a;IP&#xff1a;192.168.1.1 下载&#xff1a;keepalived ipvsadm I…

适用于 PC-3000 Portable III 的新型 SAS 适配器, 让数据恢复踏足更广!

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复同行&#xff0c;提供数据恢复实验室建设方案&#xff0c;包含数据恢复硬件设…

开源代码分享(19)-配电网孤岛优化划分方法

参考文献&#xff1a; DING Tao, LIN Yanling, LI Gengfeng, et al. A new model for resilient distribution systems by microgrids formation[J]. IEEE Transactions on Power Systems, 2017, 32(5): 4145-4147. 1.基本原理 通过分布式电源&#xff08;DGs&#xff09;形…

车载平板丨车载数据终端丨车载平板电脑丨农机使用

车载加固终端通常是为了在车辆行驶过程中保证通讯信号稳定和数据传输安全而设计的设备。在农机上使用车载加固终端&#xff0c;可以提高农机在野外作业时的通讯和数据传输质量&#xff0c;增强对农机的控制能力和运行安全性。以下是使用车载加固终端在农机上实现通讯加固的步骤…

Thingsboard PE智慧运维仪表板实例(二)【智慧排口截污实例】

ThingsBoard 的仪表板是一个用于可视化和监控物联网数据的重要组件。 它具有以下特点: 1. 可定制性:用户可以根据自己的需求创建各种类型的图表、表格和指标。 2. 数据可视化:以直观的方式展示设备数据,帮助用户快速了解系统状态。 3. 实时更新:实时反映设备的最新数据…

二叉树的前序遍历、中序遍历、后序遍历

二叉树的前序遍历、中序遍历、后序遍历 一、递归算法的三个要素二、144. 二叉树的前序遍历三、94. 二叉树的中序遍历四、145. 二叉树的后序遍历 一、递归算法的三个要素 1、确定递归函数的参数和返回值&#xff1a; 确定哪些参数是递归的过程中需要处理的&#xff0c;那么就在…

报错:AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘

报错内容&#xff1a;AttributeError: module PIL.Image has no attribute ANTIALIAS 问题所在&#xff1a; 使用PIL读取图像后对其进行Resize时由于PIL 版本问题出现AttributeError: module PIL.Image has no attribute ANTIALIAS 具体的代码如下 resized_img img.resize(ta…

交换机与队列的介绍

1.流程 首先先介绍一个简单的一个消息推送到接收的流程&#xff0c;提供一个简单的图 黄色的圈圈就是我们的消息推送服务&#xff0c;将消息推送到 中间方框里面也就是 rabbitMq的服务器&#xff0c;然后经过服务器里面的交换机、队列等各种关系&#xff08;后面会详细讲&…

【python】python的选择语句的三个题目

1.乘坐飞机时&#xff0c;有些航班没有行李额度&#xff0c;当乘客的行李小于等于20公斤时&#xff0c;按每公斤1.68元收费&#xff1b;大于20公斤时&#xff0c;按每公斤1.98元收费&#xff0c;编写程序计算收费情况&#xff08;保留两位小数&#xff09; air_bagfloat(input…

制药领域的技术革命:Profinet转CanOpen网关大放异彩

在科技飞速发展的今天&#xff0c;制药行业正采用更先进的配置方式&#xff0c;以提升生产效率。对于制药行业来说&#xff0c;生产环节中涉及到的各种设备、系统和流程需要高效协同&#xff0c;而这正是Profinet转CanOpen网关所能提供的价值所在。Profinet转CanOpen网关作为一…

X服务器远程连接问题解决:Bad displayname ““‘或Missing X server or $DISPLAY

X服务器远程连接问题 报错1 ImportError: this platform is not supported: (failed to acquire X connection: Bad displayname "", DisplayNameError()) Try one of the following resolutions: * Please make surethat you have an X server running, and that …

反射(Reflection) --Java学习笔记

反射 反射就是:加载类&#xff0c;并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等) 反射学什么? 学习获取类的信息、操作它们 反射第一步:加载类&#xff0c;获取类的字节码:Class对象获取类的构造器:Constructor对象获取类的成员变量:Field对象获取类的成…