HTML流光爱心

news2024/9/29 21:45:02

文章目录

序号目录
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生日蛋糕
33HTML流光爱心

写在前面

本期博主给大家推荐一个由HTML代码实现的、红蓝色线条组成的流光爱心,一起来看看吧。

完整代码

<!DOCTYPE html>
<!--<div class="menu__subheader"><br>微信公众号:雁卿雁卿呀-->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>流光爱心</title>
  <meta name="author" content="Logical Digit">
  </head>
      <!-- css部分 -->
 <style>
  body {
    background-color: #000;
    margin: 0;
    overflow: hidden;
    background-repeat: no-repeat;
}
</style>
  <body>
    <!-- 绘画爱心 -->
    <canvas id="canvas" width="1400" height="600"></canvas>
    <!-- js部分 -->
  </body>
  <script>
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Initialize the GL context
var gl = canvas.getContext('webgl');
if (!gl) {
    console.error("Unable to initialize WebGL.");
}
//Time step
var dt = 0.015;
//Time
var time = 0.0;
//************** Shader sources **************
var vertexSource = `
attribute vec2 position;
void main() {
  gl_Position = vec4(position, 0.0, 1.0);
}
`;
 
var fragmentSource = `
precision highp float;
uniform float width;
uniform float height;
vec2 resolution = vec2(width, height);
uniform float time;
#define POINT_COUNT 8
vec2 points[POINT_COUNT];
const float speed = -0.5;
const float len = 0.25;
float intensity = 0.9;
float radius = 0.015;
//https://www.shadertoy.com/view/MlKcDD
//Signed distance to a quadratic bezier
float sdBezier(vec2 pos, vec2 A, vec2 B, vec2 C){    
  vec2 a = B - A;
  vec2 b = A - 2.0*B + C;
  vec2 c = a * 2.0;
  vec2 d = A - pos;
  float kk = 1.0 / dot(b,b);
  float kx = kk * dot(a,b);
  float ky = kk * (2.0*dot(a,a)+dot(d,b)) / 3.0;
  float kz = kk * dot(d,a);      
  float res = 0.0;
  float p = ky - kx*kx;
  float p3 = p*p*p;
  float q = kx*(2.0*kx*kx - 3.0*ky) + kz;
  float h = q*q + 4.0*p3;
  if(h >= 0.0){ 
    h = sqrt(h);
    vec2 x = (vec2(h, -h) - q) / 2.0;
    vec2 uv = sign(x)*pow(abs(x), vec2(1.0/3.0));
    float t = uv.x + uv.y - kx;
    t = clamp( t, 0.0, 1.0 );
    // 1 root
    vec2 qos = d + (c + b*t)*t;
    res = length(qos);
  }else{
    float z = sqrt(-p);
    float v = acos( q/(p*z*2.0) ) / 3.0;
    float m = cos(v);
    float n = sin(v)*1.732050808;
    vec3 t = vec3(m + m, -n - m, n - m) * z - kx;
    t = clamp( t, 0.0, 1.0 );
    // 3 roots
    vec2 qos = d + (c + b*t.x)*t.x;
    float dis = dot(qos,qos);
        
    res = dis;
    qos = d + (c + b*t.y)*t.y;
    dis = dot(qos,qos);
    res = min(res,dis);
    
    qos = d + (c + b*t.z)*t.z;
    dis = dot(qos,qos);
    res = min(res,dis);
    res = sqrt( res );
  }
    
  return res;
}
//http://mathworld.wolfram.com/HeartCurve.html
vec2 getHeartPosition(float t){
  return vec2(16.0 * sin(t) * sin(t) * sin(t),
              -(13.0 * cos(t) - 5.0 * cos(2.0*t)
              - 2.0 * cos(3.0*t) - cos(4.0*t)));
}
//https://www.shadertoy.com/view/3s3GDn
float getGlow(float dist, float radius, float intensity){
  return pow(radius/dist, intensity);
}
float getSegment(float t, vec2 pos, float offset, float scale){
  for(int i = 0; i < POINT_COUNT; i++){
    points[i] = getHeartPosition(offset + float(i)*len + fract(speed * t) * 6.28);
  }
    
  vec2 c = (points[0] + points[1]) / 2.0;
  vec2 c_prev;
  float dist = 10000.0;
    
  for(int i = 0; i < POINT_COUNT-1; i++){
    //https://tinyurl.com/y2htbwkm
    c_prev = c;
    c = (points[i] + points[i+1]) / 2.0;
    dist = min(dist, sdBezier(pos, scale * c_prev, scale * points[i], scale * c));
  }
  return max(0.0, dist);
}
void main(){
  vec2 uv = gl_FragCoord.xy/resolution.xy;
  float widthHeightRatio = resolution.x/resolution.y;
  vec2 centre = vec2(0.5, 0.5);
  vec2 pos = centre - uv;
  pos.y /= widthHeightRatio;
  //Shift upwards to centre heart
  pos.y += 0.02;
  float scale = 0.000015 * height;
  
  float t = time;
    
  //Get first segment
  float dist = getSegment(t, pos, 0.0, scale);
  float glow = getGlow(dist, radius, intensity);
    
  vec3 col = vec3(0.0);
    
  //White core
  col += 10.0*vec3(smoothstep(0.003, 0.001, dist));
  //Pink glow
  col += glow * vec3(0.94,0.14,0.4);
    
  //Get second segment
  dist = getSegment(t, pos, 3.4, scale);
  glow = getGlow(dist, radius, intensity);
    
  //White core
  col += 10.0*vec3(smoothstep(0.003, 0.001, dist));
  //Blue glow
  col += glow * vec3(0.2,0.6,1.0);
        
  //Tone mapping
  col = 1.0 - exp(-col);
  //Output to screen
   gl_FragColor = vec4(col,1.0);
}
`;
 
//************** Utility functions **************
 
window.addEventListener('resize', onWindowResize, false);
 
function onWindowResize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.uniform1f(widthHandle, window.innerWidth);
    gl.uniform1f(heightHandle, window.innerHeight);
}
 
 
//Compile shader and combine with source
function compileShader(shaderSource, shaderType) {
    var shader = gl.createShader(shaderType);
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        throw "Shader compile failed with: " + gl.getShaderInfoLog(shader);
    }
    return shader;
}
 
//From https://codepen.io/jlfwong/pen/GqmroZ
//Utility to complain loudly if we fail to find the attribute/uniform
function getAttribLocation(program, name) {
    var attributeLocation = gl.getAttribLocation(program, name);
    if (attributeLocation === -1) {
        throw 'Cannot find attribute ' + name + '.';
    }
    return attributeLocation;
}
 
function getUniformLocation(program, name) {
    var attributeLocation = gl.getUniformLocation(program, name);
    if (attributeLocation === -1) {
        throw 'Cannot find uniform ' + name + '.';
    }
    return attributeLocation;
}
 
//************** Create shaders **************
 
//Create vertex and fragment shaders
var vertexShader = compileShader(vertexSource, gl.VERTEX_SHADER);
var fragmentShader = compileShader(fragmentSource, gl.FRAGMENT_SHADER);
 
//Create shader programs
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
 
gl.useProgram(program);
 
//Set up rectangle covering entire canvas 
var vertexData = new Float32Array([-1.0, 1.0, // top left
    -1.0, -1.0, // bottom left
    1.0, 1.0, // top right
    1.0, -1.0, // bottom right
]);
 
//Create vertex buffer
var vertexDataBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
 
// Layout of our data in the vertex buffer
var positionHandle = getAttribLocation(program, 'position');
 
gl.enableVertexAttribArray(positionHandle);
gl.vertexAttribPointer(positionHandle,
    2, // position is a vec2 (2 values per component)
    gl.FLOAT, // each component is a float
    false, // don't normalize values
    2 * 4, // two 4 byte float components per vertex (32 bit float is 4 bytes)
    0 // how many bytes inside the buffer to start from
);
 
//Set uniform handle
var timeHandle = getUniformLocation(program, 'time');
var widthHandle = getUniformLocation(program, 'width');
var heightHandle = getUniformLocation(program, 'height');
 
gl.uniform1f(widthHandle, window.innerWidth);
gl.uniform1f(heightHandle, window.innerHeight);
 
function draw() {
    //Update time
    time += dt;
 
    //Send uniforms to program
    gl.uniform1f(timeHandle, time);
    //Draw a triangle strip connecting vertices 0-4
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 
    requestAnimationFrame(draw);
}
 
draw();
</script>
</html>

代码分析

这段代码通过HTML、CSS和WebGL结合实现了一个“流光爱心”效果,以下是对其的详细分析。

1. HTML结构

在HTML部分,主要是一个canvas元素,它是用于绘制心形动画的区域。canvas元素通过其ID属性canvas在JavaScript中被引用,用于初始化WebGL上下文。

<canvas id="canvas" width="1400" height="600"></canvas>

在这里,宽度和高度只是初始设置,代码通过JavaScript调整canvas的大小以适应浏览器窗口。

2. CSS部分

CSS的作用是设置整个网页的背景颜色为黑色,并使画布占据整个窗口,同时禁用滚动条以确保效果全屏展示。

body {

    background-color: #000;
    margin: 0;
    overflow: hidden;
    background-repeat: no-repeat;
}

3. WebGL上下文初始化

JavaScript部分通过getContext('webgl')获取WebGL绘图上下文,这是一种用于在网页中绘制2D和3D图形的API。

var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var gl = canvas.getContext('webgl');
if (!gl) {
    console.error("Unable to initialize WebGL.");
}

这段代码确保WebGL能够正常运行,如果无法初始化WebGL,会在控制台输出错误信息。

4. 着色器程序

代码中定义了顶点着色器和片段着色器,用于处理图形的顶点和颜色计算。顶点着色器vertexSource负责定义绘制区域,而片段着色器fragmentSource则负责生成心形动画的光效。

  • 顶点着色器:这个简单的顶点着色器只定义了矩形区域,覆盖整个canvas

attribute vec2 position;
void main() {
  gl_Position = vec4(position, 0.0, 1.0);
}
  • 片段着色器:这是核心部分,计算并绘制了心形的流光效果。着色器使用了多种图形技术,如二次贝塞尔曲线距离函数来生成心形轮廓,getGlow函数实现光晕效果,getHeartPosition函数计算心形轨迹。

vec2 getHeartPosition(float t){
  return vec2(16.0 * sin(t) * sin(t) * sin(t),
              -(13.0 * cos(t) - 5.0 * cos(2.0*t)
              - 2.0 * cos(3.0*t) - cos(4.0*t)));
}

这个公式是数学中的经典“心形曲线公式”,通过调整时间参数t,可以得到心形轨迹上的点。

5. 动态渲染

draw函数中,程序使用requestAnimationFrame(draw)不断调用自己来实现帧动画,逐帧更新time变量,使得心形的流光效果随着时间变化而持续运行。

function draw() {
    time += dt;
    gl.uniform1f(timeHandle, time);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    requestAnimationFrame(draw);
}

每一帧,WebGL都会根据当前的时间time重新计算心形上每个点的位置,进而生成流光效果。

6. 响应窗口变化

代码监听了窗口大小的变化,使用onWindowResize函数动态调整画布的大小,确保动画始终适应窗口尺寸,并且心形保持居中显示。

window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.uniform1f(widthHandle, window.innerWidth);
    gl.uniform1f(heightHandle, window.innerHeight);
}

总结

这段代码通过WebGL技术生成了一个心形流光效果。核心部分在于数学公式计算出的心形轨迹和光晕效果,通过着色器来实现。WebGL的强大之处在于它能直接操控GPU,生成高效的动画效果。

写在后面

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

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

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

相关文章

剩余电流继电器在轨道交通地铁车站的应用

0应用背景 城市轨道交通设备复杂、量大、分布广&#xff0c;在长期持续运行的过程中&#xff0c;存在潜在的火灾风险隐患。在国内外发生的地铁火灾事件中&#xff0c;电气原因引发的火灾占比最高&#xff0c;高达37%&#xff0c;其中&#xff0c;漏电流是重要因素。地铁车站电…

【网络】手动部署内网穿透(超详细教程)

一、环境搭建 本篇文章讲的是 服务器frp转发数据的方式 frp 下载&#xff1a;https://github.com/fatedier/frp/releases/tag/v0.58.1 如果无法访问githup&#xff0c;在如下连接下载一个加速器 Watt Toolkit 官网&#xff1a;https://steampp.net/ 下载完成以后&#xff0…

京东商品详情数据接口功能介绍?API接口介绍

京东商品详情数据接口是京东开放平台提供的一组应用程序编程接口&#xff08;API&#xff09;&#xff0c;允许开发者通过编程方式获取京东商城上特定商品的详细信息。这些接口为商家、第三方开发者以及消费者提供了丰富的数据支持&#xff0c;有助于提升电商平台的运营效率、用…

ODA(Open Design Alliance)试用小记-ODA提供源码下载就完全可控了吗?

1.概述 ODA(Open Design Alliance)库架构如下&#xff1a; 产品体系如下&#xff1a; ODA的产品体系越来越壮大&#xff0c;包括主流BIM格式SDK、Viewer、Cloud、数据交换等&#xff0c;每个模块需要单独购买&#xff0c;并提供“源码服务”。 2.是否可控&#xff1f; 值得…

Tensorflow2.0

Tensorflow2.0 有深度学习基础的建议直接看class3 class1 介绍 人工智能3学派 行为主义:基于控制论&#xff0c;构建感知-动作控制系统。(控制论&#xff0c;如平衡、行走、避障等自适应控制系统) 符号主义:基于算数逻辑表达式&#xff0c;求解问题时先把问题描述为表达式…

机器学习周报(9.23-9.29)

文章目录 摘要Abstract1 自监督学习&#xff08;Self-Supervised Learning&#xff09;1.1 BERT1.1.1 Masking Input1.1.2 Next Sentence Prediction1.1.3 BERT的使用方式 1.2 Why does BERT work?1.3 Multi-lingual BERT 2 pytorch中tensor相关函数学习使用2.1 张量拼接与拆分…

【Linux】磁盘分区挂载网络配置进程【更详细,带实操】

Linux全套讲解系列&#xff0c;参考视频-B站韩顺平&#xff0c;本文的讲解更为详细 目录 一、磁盘分区挂载 1、磁盘分区机制 2、增加磁盘应用实例 3、磁盘情况查询 4、磁盘实用指令 二、网络配置 1、NAT网络原理图 2、网络配置指令 3、网络配置实例 4、主机名和host…

二、初步编写drf API

2.1基于django #settings.py urlpatterns [path(admin/, admin.site.urls),path(auth,views.auth) #创建一个路由 ]#views.py from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt# Create your views here.c…

一条sql在MySQL中是怎么执行的

目录 一、MySQL总体架构二、各层的作用1、连接层2、应用层3、存储引擎层 一、MySQL总体架构 作为常问八股文&#xff0c;相信不少小伙伴当年都被问到过这个问题&#xff0c;回答这个问题我们首先得知道MySQL服务器基本架构&#xff0c;主要分为连接层&#xff0c;应用层和存储…

【PyTorch】循环神经网络

循环神经网络是什么 Recurrent Neural Networks RNN&#xff1a;循环神经网络 处理不定长输入的模型常用于NLP及时间序列任务&#xff08;输入数据具有前后关系&#xff09; RNN网络结构 参考资料 Recurrent Neural Networks Tutorial, Part 1 – Introduction to RNNs Und…

古代帝王与啤酒的不解之缘

在历史的长河中&#xff0c;古代帝王们的生活总是充满神秘与传奇。他们掌握着无上的权力&#xff0c;享受着世间的荣华富贵。而在这些帝王的日常生活中&#xff0c;有一种饮品始终伴随着他们&#xff0c;那便是精酿啤酒。今天&#xff0c;我们就来探寻古代帝王与啤酒之间的不解…

渗透测试实战—教育攻防演练信息收集

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

【Python】数据可视化之热力图

热力图&#xff08;Heatmap&#xff09;是一种通过颜色深浅来展示数据分布、密度和强度等信息的可视化图表。它通过对色块着色来反映数据特征&#xff0c;使用户能够直观地理解数据模式&#xff0c;发现规律&#xff0c;并作出决策。 目录 基本原理 sns.heatmap 代码实现 基…

「OC」探索 KVC 的基础与应用

「OC」KVC的初步学习 文章目录 「OC」KVC的初步学习前言介绍KVC的相关方法key和keyPath的区别KVC的工作原理KVO的setValue:forKey原理KVO的ValueforKey原理 在集合之中KVC的用法1. mutableArrayValueForKey: 和 mutableArrayValueForKeyPath:2. mutableSetValueForKey: 和 muta…

【源码+文档+调试讲解】无人超市系统python

摘 要 随着科技的不断进步&#xff0c;无人超市成为了零售行业的新兴趋势。无人超市管理系统是支撑这一新型商业模式的关键软件基础设施。该系统采用python技术和MySQL数据库技术以及Django框架进行开发。通过高度自动化和智能化的方式&#xff0c;允许消费者在没有收银员的情…

WordPress LearnPress插件 SQL注入复现(CVE-2024-8522)

0x01 产品描述&#xff1a; LearnPress 是一款功能强大的 WordPress LMS&#xff08;学习管理系统&#xff09;插件&#xff0c;适用于创建和销售在线课程。凭借其直观的界面和丰富的功能&#xff0c;无论您是否具备编程背景&#xff0c;都能轻松搭建起在线教育网站。学会如何使…

【若依RuoYi-Vue | 项目实战】帝可得后台管理系统(三)

文章目录 一、商品管理1、需求说明2、生成基础代码&#xff08;1&#xff09;创建目录菜单&#xff08;2&#xff09;配置代码生成信息&#xff08;3&#xff09;下载代码并导入项目 3、商品类型改造&#xff08;1&#xff09;基础页面 4、商品管理改造&#xff08;1&#xff0…

【YOLO目标检测车牌数据集】共10000张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式&#xff1a;YOLO格式 图片数量&#xff1a;10000&#xff08;2000张绿牌、8000张蓝牌&#xff09; 标注数量(txt文件个数)&#xff1a;10000 标注类别数&#xff1a;1 标注类别名称&#xff1a;licence 数据集下载&#xff1a;车牌数据…

docker 部署 Seatunnel 和 Seatunnel Web

docker 部署 Seatunnel 和 Seatunnel Web 说明&#xff1a; 部署方式前置条件&#xff0c;已经在宿主机上运行成功运行文件采用挂载宿主机目录的方式部署SeaTunnel Engine 采用的是混合模式集群 编写Dockerfile并打包镜像 Seatunnel FROM openjdk:8 WORKDIR /opt/seatunne…

在github上,如何只下载选中的文件?

GitHub官方不直接支持下载子目录&#xff0c;但可以使用特定的第三方工具或脚本来实现这一需求。 总而言之一句话&#xff1a;需要下载插件&#xff01;&#xff01;&#xff01;具体实操步骤如下&#xff1a; 1.打开谷歌浏览器右上角的管理扩展程序&#xff1a; 2.搜索GitZi…