HTML旋转爱心

系列文章

序号目录
1HTML满屏跳动的爱心(可写字)
2HTML五彩缤纷的爱心
3HTML满屏漂浮爱心
4HTML情人节快乐
5HTML蓝色爱心射线
6HTML跳动的爱心(简易版)
7HTML粒子爱心
8HTML蓝色动态爱心
9HTML跳动的爱心(双心版)
10HTML橙色动态粒子爱心
11HTML旋转爱心
12HTML爱情树
13HTML3D相册
14HTML旋转相册
15HTML基础烟花秀
16HTML炫酷烟花秀
17HTML粉色烟花秀
18HTML新春烟花
19HTML龙年大吉
20HTML音乐圣诞树
21HTML大雪纷飞
22HTML想见你
23HTML元素周期表
24HTML飞舞的花瓣
25HTML星空特效
26HTML黑客帝国字母雨
27HTML哆啦A梦
28HTML流星雨
29HTML沙漏爱心
30HTML爱心字母雨
31HTML爱心流星雨
32HTML生日蛋糕
33HTML3D旋转相册
34HTML流光爱心
35HTML满屏飘字
36HTML飞舞爱心
37HTML雪花圣诞树

目录

系列文章

写在前面

完整代码

代码分析

写在后面


写在前面

HTML语言实现旋转爱心的完整代码。

完整代码

<!DOCTYPE html>
<html lang="en"><head><title>Love</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><style>body {font-family: Monospace;background-color: #f0f0f0;margin: 0px;overflow: hidden;}</style>
</head><body><script src="js/nb.js"></script><script src="js/Projector.js"></script><script src="js/CanvasRenderer.js"></script><script src="js/tween.min.js"></script><script src="js/Sparks.js"></script><!-- load the font file from canvas-text --><script src="js/helvetiker_regular.typeface.js"></script><script>var container;var camera, scene, renderer;var group, text, plane;var targetRotation = 0;var targetRotationOnMouseDown = 0;var mouseX = 0;var mouseXOnMouseDown = 0;var windowHalfX = window.innerWidth / 2;var windowHalfY = window.innerHeight / 2;var heartShape, particleCloud, sparksEmitter, emitterPos;var _rotation = 0;var timeOnShapePath = 0;init();animate();function init() {container = document.createElement('div');document.body.appendChild(container);//相机camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);camera.position.set(0, 150, 800);//场景scene = new THREE.Scene();group = new THREE.Group();scene.add(group);// Get text from hashvar string = "Love";var hash = document.location.hash.substr(1);if (hash.length !== 0) {string = hash;}var text3d = new THREE.TextGeometry(string, {size: 80,height: 20,curveSegments: 2,font: "helvetiker"});text3d.computeBoundingBox();var centerOffset = -0.35 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);var textMaterial = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff, overdraw: 0.5 });text = new THREE.Mesh(text3d, textMaterial);// Potentially, we can extract the vertices or faces of the text to generate particles too.// Geo > Vertices > Positiontext.position.x = centerOffset;text.position.y = 100;text.position.z = 0;text.rotation.x = 0;text.rotation.y = Math.PI * 2;group.add(text);particleCloud = new THREE.Object3D(); // Just a groupparticleCloud.y = 800;group.add(particleCloud);// Create Particle Systems// Heartvar x = 0, y = 0;heartShape = new THREE.Shape();heartShape.moveTo(x + 25, y + 25);heartShape.bezierCurveTo(x + 25, y + 25, x + 20, y, x, y);heartShape.bezierCurveTo(x - 30, y, x - 30, y + 35, x - 30, y + 35);heartShape.bezierCurveTo(x - 30, y + 55, x - 10, y + 77, x + 25, y + 95);heartShape.bezierCurveTo(x + 60, y + 77, x + 80, y + 55, x + 80, y + 35);heartShape.bezierCurveTo(x + 80, y + 35, x + 80, y, x + 50, y);heartShape.bezierCurveTo(x + 35, y, x + 25, y + 25, x + 25, y + 25);var hue = 0;var hearts = function (context) {context.globalAlpha = 0.5;var x = 0, y = 0;context.scale(0.05, -0.05); // Scale so canvas render can redraw within boundscontext.beginPath();// From http://blog.burlock.org/html5/130-pathscontext.bezierCurveTo(x + 2.5, y + 2.5, x + 2.0, y, x, y);context.bezierCurveTo(x - 3.0, y, x - 3.0, y + 3.5, x - 3.0, y + 3.5);context.bezierCurveTo(x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5);context.bezierCurveTo(x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5);context.bezierCurveTo(x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y);context.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);context.fill();context.lineWidth = 0.5; //0.05context.stroke();}var setTargetParticle = function () {var material = new THREE.SpriteCanvasMaterial({program: hearts});material.color.setHSL(hue, 1, 0.75);hue += 0.001;if (hue > 1)hue -= 1;particle = new THREE.Sprite(material);particle.scale.x = particle.scale.y = Math.random() * 40 + 40;particleCloud.add(particle);return particle;};var onParticleCreated = function (p) {p.target.position.copy(p.position);};var onParticleDead = function (particle) {particle.target.visible = false;particleCloud.remove(particle.target);};sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(160));emitterpos = new THREE.Vector3();sparksEmitter.addInitializer(new SPARKS.Position(new SPARKS.PointZone(emitterpos)));sparksEmitter.addInitializer(new SPARKS.Lifetime(0, 2));sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0, -50, 10))));// TOTRY Set velocity to move away from centroidsparksEmitter.addAction(new SPARKS.Age());//sparksEmitter.addAction(new SPARKS.Accelerate(0.2));sparksEmitter.addAction(new SPARKS.Move());sparksEmitter.addAction(new SPARKS.RandomDrift(50, 50, 2000));sparksEmitter.addCallback("created", onParticleCreated);sparksEmitter.addCallback("dead", onParticleDead);sparksEmitter.addCallback("updated", function (particle) {particle.target.position.copy(particle.position);});sparksEmitter.start();// End Particlesrenderer = new THREE.CanvasRenderer();renderer.setClearColor(0xf0f0f0);renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);container.appendChild(renderer.domElement);document.addEventListener('mousedown', onDocumentMouseDown, false);document.addEventListener('touchstart', onDocumentTouchStart, false);document.addEventListener('touchmove', onDocumentTouchMove, false);//window.addEventListener('resize', onWindowResize, false);}function onWindowResize() {windowHalfX = window.innerWidth / 2;windowHalfY = window.innerHeight / 2;camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}//document.addEventListener('mousemove', onDocumentMouseMove, false);function onDocumentMouseDown(event) {event.preventDefault();mouseXOnMouseDown = event.clientX - windowHalfX;targetRotationOnMouseDown = targetRotation;if (sparksEmitter.isRunning()) {sparksEmitter.stop();} else {sparksEmitter.start();}}function onDocumentMouseMove(event) {mouseX = event.clientX - windowHalfX;targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;}function onDocumentTouchStart(event) {if (event.touches.length == 1) {event.preventDefault();mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;targetRotationOnMouseDown = targetRotation;}}function onDocumentTouchMove(event) {if (event.touches.length == 1) {event.preventDefault();mouseX = event.touches[0].pageX - windowHalfX;targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;}}//function animate() {//更新场景requestAnimationFrame(animate);render();}function render() {timeOnShapePath += 0.0337;if (timeOnShapePath > 1)timeOnShapePath -= 1;// TODO Create a PointOnShape Action/Zone in the particle enginevar pointOnShape = heartShape.getPointAt(timeOnShapePath);emitterpos.x = pointOnShape.x * 5 - 100;emitterpos.y = -pointOnShape.y * 5 + 400;// Pretty cool effect if you enable this// particleCloud.rotation.y += 0.05;group.rotation.y += (targetRotation - group.rotation.y) * 0.05;renderer.render(scene, camera);}</script></body></html>

代码分析

这段代码使用了 Three.js 和 Sparks.js 进行 3D 渲染和粒子特效创建,其核心功能是生成一个动态心形粒子效果,并结合“Love”文本渲染,实现互动的 3D 场景。以下是详细的分解与分析:


HTML 结构

  1. 页面头部:

    • 使用了 <meta> 设置编码为 UTF-8,支持视口适配移动设备。

    • 引入内联样式表,设置 body 背景色和无滚动属性。

  2. 核心 JavaScript 文件:

    • nb.jsProjector.jsCanvasRenderer.js: 提供 Three.js 的扩展功能和基础渲染器(CanvasRenderer 用于非 WebGL 的情况下)。

    • tween.min.js: 动画库,提供平滑过渡的时间控制。

    • Sparks.js: 粒子系统的实现,定义了粒子的生命周期、位置和行为。

    • helvetiker_regular.typeface.js: 引入 Three.js 字体文件,用于生成 3D 文本。


JavaScript 核心逻辑

1. 初始化场景

通过 init() 函数初始化 Three.js 场景,包括以下部分:

  • 相机(camera): 使用 PerspectiveCamera 设置透视投影,相机位置 (0, 150, 800)

  • 场景(scene): 通过 Scene() 创建场景对象,添加子对象 group(用于管理场景内的物体)。

  • 文本渲染: 利用 TextGeometry 和字体 helvetiker 创建 “Love” 文本,并设置:
    • 尺寸:80。

    • 厚度:20。

    • 颜色随机。 文本被添加到 group,并设定其位置 (x: centerOffset, y: 100, z: 0)


2. 粒子系统

代码中定义了一个粒子云 particleCloud,粒子的行为和特效通过 Sparks.js 实现:

  • 心形路径(heartShape): 使用 Three.Shape() 定义一个心形路径,结合 bezierCurveTo() 创建心形曲线。

  • 粒子行为:
    • 每个粒子通过 SpriteCanvasMaterial 渲染,附加一个绘制心形的 program

    • 粒子大小随机,范围在 40 至 80。

    • 粒子被添加到 particleCloud

  • 粒子发射器(sparksEmitter):
    • 使用 SPARKS.SteadyCounter 控制每秒 160 粒子。

    • 初始化器包括:
      • 位置:Position 定义初始点为心形路径点。

      • 生命期:Lifetime 设置粒子存活时间为 0 至 2 秒。

      • 速度:Velocity 定义粒子向下漂移 (0, -50, 10)

    • 行为动作:
      • Age:控制粒子的生命周期。

      • Move:移动粒子。

      • RandomDrift:随机漂移,增强动态效果。

    • 注册回调:
      • created: 每创建一个粒子时更新位置。

      • dead: 粒子死亡后移除。


3. 用户交互

支持鼠标和触摸交互:

  • 鼠标事件:
    • mousedown: 点击后切换粒子发射器的运行状态(开启/停止)。

    • mousemove: 控制粒子云的旋转角度。

  • 触摸事件:
    • touchstart 和 touchmove 控制移动设备上的旋转交互。

通过 targetRotation 和 group.rotation.y 实现平滑旋转。


4. 动画更新

animate() 函数使用 requestAnimationFrame() 实现持续更新:

  • 时间路径控制timeOnShapePath 变量控制粒子沿心形路径运动,结合 heartShape.getPointAt() 获取路径上的点坐标。

  • 粒子更新: 每一帧调整粒子的位置,使其形成动态效果。

  • 渲染: 调用 renderer.render() 更新整个场景。


核心亮点

  1. 动态心形路径粒子: 粒子在心形路径上运动,路径通过贝塞尔曲线精确定义。

  2. 三维交互: 利用鼠标、触摸事件调整视角,增强体验感。

  3. 文本渲染: 将 3D 文本和粒子效果结合,提升视觉吸引力。


小结

该代码通过 Three.js 和 Sparks.js 实现了一个视觉效果丰富、互动性强的 3D 粒子场景,展示了动态文本和心形粒子的结合。适合用于情感表达、节日贺卡或动态网页展示场景。

写在后面

我是一只有趣的兔子,感谢你的喜欢!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

查看 tomcat信息 jconsole.exe

Where is the jconsole.exe? location: JDK/bin/jconsole.exe

设计模式10:观察者模式(订阅-发布)

系列总链接&#xff1a;《大话设计模式》学习记录_net 大话设计-CSDN博客 参考&#xff1a;简说设计模式——工厂方法模式 - JAdam - 博客园 参考&#xff1a;简单工厂模式(Simple Factory Pattern) - 回忆酿的甜 - 博客园 一&#xff1a;概述 观察者模式&#xff0…

AIGC 时代的文学:变革与坚守

目录 一.AIGC 带来的文学变革 1.创作方式的改变 2.阅读体验的升级 3.文学市场的重塑 二.文学在 AIGC 时代的坚守 1.人类情感的表达 2.文学的艺术性 3.文学的社会责任 三.AIGC 与人类作家的共生之路 1.相互学习 2.合作创作 3.共同发展 另&#xff1a; 总结 随着人…

Wwise 使用MIDI文件、采样音频

第一种&#xff1a;当采样音频只有一个文件的时候 1.拖入MIDI文件到Interactive Music Hierarchy层级 2.拖入采样音频到Actor-Mixer Hierarchy层级 3.勾选MIDI显示出面板&#xff0c;设置Root Note与采样音频音高相同&#xff0c;这里是C#5 4.播放测试&#xff0c;成功&…

【计算机网络】实验9: 路由信息协议RIP

实验9 路由信息协议RIP 一、实验目的 本实验的主要目的是深入理解RIP&#xff08;路由信息协议&#xff09;的工作原理&#xff0c;以便掌握其在网络中的应用。通过对RIP的学习&#xff0c;我们将探讨该协议如何实现路由选择和信息传播&#xff0c;从而确保数据包能够在网络中…

python源码实例游戏开发小程序办公自动化网络爬虫项目开发源码(250+个项目、26.6GB)

文章目录 源代码下载地址项目介绍预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 python源码实例游戏开发小程序办公自动化网络爬虫项目开发源码(250个项目、26.6GB) 预览 项目备注 1、该资源内项目代码都经过测试运行成功&#xff0c;功能ok的情…

深入理解AVL树:结构、旋转及C++实现

1. AVL树的概念 什么是AVL树&#xff1f; AVL树是一种自平衡的二叉搜索树&#xff0c;其发明者是Adelson-Velsky和Landis&#xff0c;因此得名“AVL”。AVL树是首个自平衡二叉搜索树&#xff0c;通过对树的平衡因子进行控制&#xff0c;确保任何节点的左右子树高度差最多为1&…

spark-sql配置教程

1.前期准备 &#xff08;1&#xff09;首先要把hadoop集群&#xff0c;hive和spark等配置好 hadoop集群&#xff0c;hive的配置可以看看这个博主写的博客 大数据_蓝净云的博客-CSDN博客 或者看看黑马程序员的视频 黑马程序员大数据入门到实战教程&#xff0c;大数据开发必…

Git分布式版本控制工具 Git基本概念、Git工作流程、Git常用命令、Git远程仓库、IDEA操作Git

目录 ​​​​​​ 1.Git基本概念 1.1 概述 1.1.1 开发中的实际场景 1.1.2 版本控制器的方式 1.1.2.1 集中式版本控制工具(SVN) 1.1.2.2 分布式版本控制工具(Git) 2.概述git工作流程 3.Git常用命令 3.1 Git环境配置 3.1.1 下载与安装 3.1.2 基本配置 3.1.3 为常用指令配置别名&…

“停车费“ 在英语中常见的表达方式,柯桥职场英语生活口语商务英语学习

“停车费”用英语怎么说&#xff1f; "停车费" 在英语中有多种表达方式&#xff0c;最常见的是&#xff1a; Parking fee: 这是最直接的翻译&#xff0c;用于各种停车场、路边停车等情况。 Parking c15857575#376harge: 与 parking fee 意思相近&#xff0c;但有时更…

第31天:安全开发-JS应用WebPack打包器第三方库JQuery安装使用安全检测

时间轴&#xff1a; 演示案例&#xff1a; 打包器-WebPack-使用&安全 第三方库-JQuery-使用&安全 打包器-WebPack-使用&安全 参考&#xff1a;https://mp.weixin.qq.com/s/J3bpy-SsCnQ1lBov1L98WA Webpack 是一个模块打包器。在 Webpack 中会将前端的所有资源…

Redis使用场景-缓存-缓存雪崩

前言 之前在针对实习面试的博文中讲到Redis在实际开发中的生产问题&#xff0c;其中缓存穿透、击穿、雪崩在面试中问的最频繁&#xff0c;本文加了图解&#xff0c;希望帮助你更直观的了解缓存雪崩&#x1f600; &#xff08;放出之前写的针对实习面试的关于Redis生产问题的博…

【SARL】单智能体强化学习(Single-Agent Reinforcement Learning)《纲要》

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

高通---Camera调试流程及常见问题分析

文章目录 一、概述二、Camera配置的整体流程三、Camera的代码架构图四、Camera数据流的传递五、camera debug FAQ 一、概述 在调试camera过程中&#xff0c;经常会遇到各种状况&#xff0c;本篇文章对camera调试的流程进行梳理。对常见问题的提供一些解题思路。 二、Camera配…

JAVA |日常开发中Servlet详解

JAVA &#xff5c;日常开发中Servlet详解 前言一、Servlet 概述1.1 定义1.2 历史背景 二、Servlet 的生命周期2.1 加载和实例化2.2 初始化&#xff08;init 方法&#xff09;2.3 服务&#xff08;service 方法&#xff09;2.4 销毁&#xff08;destroy 方法&#xff09; 三、Se…

网络(TCP)

目录 TCP socket API 详解 套接字有哪些类型&#xff1f;socket有哪些类型&#xff1f; 图解TCP四次握手断开连接 图解TCP数据报结构以及三次握手&#xff08;非常详细&#xff09; socket缓冲区以及阻塞模式详解 再谈UDP和TCP bind(): 我们的程序中对myaddr参数是这样…

JavaScript 键盘控制移动

如果你想通过 JavaScript 实现键盘控制对象&#xff08;比如一个方块&#xff09;的移动&#xff0c;下面是一个简单的示例&#xff0c;展示如何监听键盘事件并根据按下的键来移动一个元素。 HTML 和 CSS&#xff1a; <!DOCTYPE html> <html lang"en">…

图解SSL/TLS 建立加密通道的过程

众所周知&#xff0c;HTTPS 是 HTTP 安全版&#xff0c;HTTP 的数据以明文形式传输&#xff0c;而 HTTPS 使用 SSL/TLS 协议对数据进行加密&#xff0c;确保数据在传输过程中的安全。 那么&#xff0c;HTTPS 是如何做到数据加密的呢&#xff1f;这就需要了解 SSL/TLS 协议了。 …

自动化立体仓库项目任务调度系统中任务流程可视化实现

在运维自动化平台中,任务系统无疑是最核心的组成部分之一。它承担着所有打包编译、项目上线、日常维护等运维任务的执行。通过任务系统,我们能够灵活地构建满足不同需求的自定义任务流。早期的任务流后端采用了类似列表的存储结构,根据任务流内子任务的排序依次执行,尽管通…

【算法】【优选算法】位运算(下)

目录 一、&#xff1a;⾯试题 01.01.判定字符是否唯⼀1.1 位图1.2 hash思路1.3 暴力枚举 二、268.丢失的数字2.1 位运算&#xff0c;异或2.2 数学求和 三、371.两整数之和四、137.只出现⼀次的数字 II五、⾯试题 17.19.消失的两个数字 一、&#xff1a;⾯试题 01.01.判定字符是…