当前位置: 首页 > news >正文

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

  目录

前言

开始       

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)";// 保持合成操作为lighterctx.globalCompositeOperation = "lighter";
});
</script></body>
</html>

效果图

总结

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

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

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

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

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

相关文章:

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

目录 前言 开始 HTML部分 效果图 ​编辑​编辑​编辑​编辑总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建一个文本文档&#xff0c;其中HTML的文件名改为[index.html]&a…...

JVM修炼之路【11】- 解决内存溢出、内存泄漏 以及相关案例

前面的10篇 都是基础的知识&#xff0c;包括类加载的过程 类加载的细节&#xff0c;jvm内存模型 垃圾回收 等等&#xff0c; 这一篇我们开始实战了解一下 各种疑难杂症&#xff1a;怎么监控 怎么发现 怎么解决 内存溢出 内存泄漏 这两个概念在垃圾回收器里面已经讲过了&#…...

Java面试题:描述Java 17中的密封接口及其用途

Java 17是继Java 11和Java 16之后的又一个长期支持&#xff08;LTS&#xff09;版本&#xff0c;它于2021年9月发布。在Java 17中&#xff0c;一个重要的新特性是密封接口&#xff08;Sealed Interfaces&#xff09;&#xff0c;这是对Java接口的增强&#xff0c;它允许接口有更…...

C++11的新特性

C11是由C标准委员会指定的语言规范。相比于C98/03&#xff0c;C11则带来了数量可观的变化&#xff0c;其中包含了约140 个新特性&#xff0c;以及对C03标准中约600个缺陷的修正&#xff0c;C11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全&#xff0c;…...

【C语言__动态内存管理__复习篇6】

目录 前言 一、动态内存管理 二、动态内存函数 2.1 malloc 2.2 free 2.3 calloc 2.4 realloc 三、动态内存常见的6个使用错误 3.1 接收malloc/calloc返回的参数后未及时检查是否为NULL 3.2 越界访问动态内存空间 3.3 对非动态开辟的内存使用free释放 3.4 使用free只释放了…...

C语言 | Leetcode C语言题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; typedef struct {char key[32];int val;UT_hash_handle hh; } HashItem;int* findSubstring(char * s, char ** words, int wordsSize, int* returnSize){ int m wordsSize, n strlen(words[0]), ls strlen(s);int *res (int *)mall…...

大数据dolphinscheduler 本地容器化安装

Minio 容器安装 docker run -p 9000:9000 -p 9090:9090 --name minio -d -e "MINIO_ACCESS_KEYminioadmin" -e "MINIO_SECRET_KEYminioadmin" -v D:\SF\DOCKER\minio\data:/data -v D:\SF\DOCKER\minio\config:/root/.minio minio/minio server /da…...

简单的车牌号识别

目录 处理流程与界面各接口编写时遇到的一些问题上传图片识别结果标签显示中文 处理流程与界面 首先点击“上传图片”按钮&#xff0c;可以选择文件夹中含有汽车车牌的图片&#xff0c;并显示在“图片框”中。 点击“检测车牌”按钮&#xff0c;会先对“图片框”中即含有汽车车…...

openGauss学习笔记-261 openGauss性能调优-使用Plan Hint进行调优-将部分Error降级为Warning的Hint

文章目录 openGauss学习笔记-261 openGauss性能调优-使用Plan Hint进行调优-将部分Error降级为Warning的Hint261.1 功能描述261.2 语法格式261.3 示例261.3.1 忽略非空约束261.3.2 忽略唯一约束261.3.3 忽略分区表无法匹配到合法分区261.3.4 更新/插入值向目标列类型转换失败 o…...

CSS水波纹效果

效果图&#xff1a; 1.创建一个div <div class"point1" click"handlePoint(1)"></div> 2.设置样式 .point1{width: 1rem;height: 1rem;background: #2ce92f;position: absolute;border-radius: 50%;z-index: 999;cursor: pointer;} 3.设置伪…...

迭代器模式:优雅地遍历数据集合

在软件设计中&#xff0c;迭代器模式是一种常见且有用的设计模式&#xff0c;它允许顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露该对象的内部表示。这种模式在需要对集合进行遍历操作而又不想暴露集合内部结构的场景下非常有用。 一、迭代器模式的使用条件 访问集…...

c++总结笔记(一)

计算机可以将程序转化为二进制指令&#xff08;即机器码&#xff09;&#xff0c;并由CPU执行&#xff0c;CPU会按照指令的顺序依次执行每个指令。 C语言特点&#xff1a; 简洁高效可移植模块化标准化 C语言的标准 C89(C90)标准C99标准C11标准 导入 使用include导入包含…...

[python][gradio]chatbot控件用法

chatbot模块是Gradio中的一个组件&#xff0c;用于展示聊天机器人的输出&#xff0c;包括用户提交的消息和机器人的回复。它支持一些Markdown语法&#xff0c;包括粗体、斜体、代码和图片等。Chatbot模块的输入不接受用户输入&#xff0c;而是通过函数返回的列表来设置聊天内容…...

Sublime Text下载,安装,安装插件管理器,下载汉化插件

SublimeTest官网 © Sublime Text中文网 下载安装 一路点击安装即可 安装插件管理器 管理器官网安装 - 包控制 (packagecontrol.io) 手动安装将3 位置点击网址下载 再打开SublimeTest 点击 选择第一个Browse Packages..... 将会跳转到文件夹中 进入上一个文件夹 在进入…...

c++ ,stl经常出现的<>尖括号其实就是模板类的实例化

通过比如vector<int> 实际上是调用了类似模板template<T t>class vector{...}实例化了一个使用int的vector类来进行定义&#xff0c;我们可以尝试简单的做一个自己的array类 template<typename T1 ,int d2> class array1 {private:T1 *p;int size;public:ar…...

goproxy 简单介绍 及一键安装脚本

goproxy 官网 https://goproxy.cn/ GoProxy 是一项用于 Go 模块的高性能代理服务&#xff0c;旨在为 Go 开发人员提供更快速、更可靠的模块下载体验。它提供以下主要功能&#xff1a; 全球分布式代理服务器: GoProxy 在全球多个地区部署了代理服务器&#xff0c;例如拉斯维加…...

Day13-Python基础学习之数据分析案例

数据分析案例 data_define.py # 数据定义的类 class Record:def __init__(self, date, order_id, money, province):self.date dateself.order_id order_idself.money moneyself.province province ​def __str__(self):return f"{self.date}, {self.order_id}, {se…...

研究生,该学单片机还是plc。?

PLC门槛相对较低&#xff0c;但是在深入学习和应用时&#xff0c;仍然有很高的技术要求。我这里有一套单片机入门教程&#xff0c;不仅包含了详细的视频 讲解&#xff0c;项目实战。如果你渴望学习单片机&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&am…...

【Java】导出Mysql表表结构与注释数据字典

需求&#xff1a; 把mysql中所有表的字段名、数据类型、长度、注释整理成csv&#xff0c;做成数据字典。 import java.io.IOException; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import ja…...

第07-2章 TCP/IP模型

7.7 TCP/IP模型详解 7.7.1 简介 应用层的PDU>APDU&#xff08;Application PDU&#xff09; 表示层的PDU>PPDU&#xff08;Presentation PDU&#xff09; 会话层的PDU>SPDU&#xff08;Session PDU&#xff09; 7.7.2 TCP/IP协议体系 &#xff08;1&#xff09;TCP…...

Qwen1.5-0.5B-Chat电商应用:商品咨询机器人搭建教程

Qwen1.5-0.5B-Chat电商应用&#xff1a;商品咨询机器人搭建教程 1. 引言&#xff1a;为什么需要一个轻量级商品咨询机器人&#xff1f; 想象一下&#xff0c;你经营着一家网店&#xff0c;每天有成百上千的顾客涌入。他们的问题五花八门&#xff1a;“这件衣服有L码吗&#x…...

Node.js 轻量级数据库 NeDB 实战指南:从入门到精通

1. 为什么你需要了解NeDB 如果你正在寻找一个轻量级的Node.js数据库解决方案&#xff0c;NeDB绝对值得你花时间研究。作为一个嵌入式数据库&#xff0c;它不需要单独运行数据库服务&#xff0c;数据可以直接存储在内存或磁盘文件中。我在多个小型项目中使用过NeDB&#xff0c;最…...

ARM Neon加速NTT实战:如何在Cortex-A72上优化Kyber和Saber的加密性能

ARM Neon加速NTT实战&#xff1a;Cortex-A72上的Kyber与Saber性能优化 在移动安全领域&#xff0c;后量子密码算法的硬件加速已成为行业焦点。Cortex-A72作为ARM中端处理器的代表&#xff0c;其Neon指令集为NTT&#xff08;数论变换&#xff09;提供了显著的并行计算能力。本文…...

3步打造你的专属阅读系统:开源工具如何重构数字阅读体验

3步打造你的专属阅读系统&#xff1a;开源工具如何重构数字阅读体验 【免费下载链接】legado-Harmony 开源阅读鸿蒙版仓库 项目地址: https://gitcode.com/gh_mirrors/le/legado-Harmony 你是否曾遇到这样的困扰&#xff1a;阅读APP充斥广告弹窗、书源受限无法找到心仪内…...

A-59F 多功能语音处理模组:覆盖全场景人群,让每一次语音都清晰无噪

在门禁对讲、会议扩音、车载通话、导游喊话、监护设备、智能工牌等各类语音设备中&#xff0c;啸叫刺耳、环境嘈杂、回音不断、拾音模糊、通话断续是所有人共同的痛点。一款真正解决问题的核心硬件 ——A-59F 多功能语音处理模组&#xff0c;它集成扩音防啸叫、AI ENC 降噪、AE…...

3个高级技巧:用ScintillaNET构建专业级文本编辑器的实战指南

3个高级技巧&#xff1a;用ScintillaNET构建专业级文本编辑器的实战指南 【免费下载链接】ScintillaNET A Windows Forms control, wrapper, and bindings for the Scintilla text editor. 项目地址: https://gitcode.com/gh_mirrors/sc/ScintillaNET 在当今的软件开发领…...

深入浅出:图解程序控制、中断和DMA的工作原理与性能差异

深入浅出&#xff1a;图解程序控制、中断和DMA的工作原理与性能差异 想象你在一家餐厅点餐&#xff1a;第一种方式是服务员每隔30秒就来问你"好了吗"&#xff1b;第二种是你按服务铃&#xff0c;服务员立刻过来&#xff1b;第三种是厨房直接把菜送到你桌上——这正是…...

RCLAMP0542T.TCT‌静电保护TVS 二极管阵列 SEMTECH 电子元器件IC 芯片

RCLAMP0542T.TCT‌ 是由 ‌SEMTECH‌ 公司推出的一款超低电容、双通道ESD&#xff08;静电放电&#xff09;保护 TVS 二极管阵列&#xff0c;具备0.45pF 超低电容、5A 浪涌承受能力和超小型 SLP1610P4T 封装&#xff0c;专为高速数据接口设计&#xff0c;广泛应用于通信设备、消…...

搭建专属汽车电子测试 AI 助手

专栏&#xff1a;《AI 汽车电子测试实战》第 15 篇 作者&#xff1a;一线汽车电子测试工程师 适合人群&#xff1a;想搭建私有 AI 助手的测试团队、关注数据安全的工程师开篇&#xff1a;为什么需要专属 AI 助手&#xff1f; 这是我上个月在某车企的 AI 部署项目中的真实经历。…...

OpenClaw定时任务:利用GLM-4.7-Flash实现智能日程管理

OpenClaw定时任务&#xff1a;利用GLM-4.7-Flash实现智能日程管理 1. 为什么需要智能化的定时任务 记得上个月我连续错过了三个重要会议&#xff0c;原因很简单——手动设置的日历提醒被其他通知淹没了。这种经历让我开始寻找更智能的解决方案。传统定时工具只能机械地执行预…...