HTML+JavaScript+CSS:爱心代码

news2024/12/23 22:13:38

请添加图片描述

1、创建heart.js文件

// 定义画布的宽度和高度,以及画布的中心点坐标
const CANVAS_WIDTH = 640;
const CANVAS_HEIGHT = 480;
const CANVAS_CENTER_X = CANVAS_WIDTH / 2;
const CANVAS_CENTER_Y = CANVAS_HEIGHT / 2;

// 定义图像的放大因子,用于调整爱心的大小
const IMAGE_ENLARGE_FACTOR = 11;

// 定义爱心的颜色
const HEART_COLOR = "#FF69B4";

// 生成爱心上的一个点的坐标
function generateHeartCoordinate(t, shrinkRatio = IMAGE_ENLARGE_FACTOR) {
  // 使用参数t计算原始的x和y坐标
  let x = 16 * (Math.sin(t) ** 3);
  let y = -(13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));

  // 根据缩放比例调整x和y坐标
  x *= shrinkRatio;
  y *= shrinkRatio;

  // 将坐标转换到画布的中心
  x += CANVAS_CENTER_X;
  y += CANVAS_CENTER_Y;

  // 返回调整后的坐标,向下取整以确保坐标为整数
  return { x: Math.floor(x), y: Math.floor(y) };
}

// 绘制爱心的函数
function drawHeart(context, ratio, frame) {
  // 清空画布
  context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

  // 绘制爱心的光晕部分
  let heartHaloPoints = new Set();
  for (let i = 0; i < 3000 + 4000 * Math.abs(customCurve(frame / 10 * Math.PI) ** 2); i++) {
    // 生成一个随机的t值,用于计算坐标
    let t = Math.random() * 4 * Math.PI;
    // 使用generateHeartCoordinate函数计算坐标,并使用一个更大的缩放比例来使光晕更大
    let { x, y } = generateHeartCoordinate(t, 11.5);
    // 计算一个力的大小,用于调整光晕的扩散效果
    let force = -1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.6);
    // 根据力的大小调整x和y坐标
    x -= ratio * force * (x - CANVAS_CENTER_X);
    y -= ratio * force * (y - CANVAS_CENTER_Y);
    // 添加一些随机的偏移量,使光晕更加自然
    x += Math.floor(Math.random() * 29 - 14);
    y += Math.floor(Math.random() * 29 - 14);
    // 使用fillRect函数绘制一个2x2的正方形,作为光晕的一个点
    context.fillStyle = HEART_COLOR;
    context.fillRect(x, y, 2, 2);
  }

  // 绘制爱心的主体部分
  let allPoints = []; // 存储所有点的数组
  let originalPoints = new Set(); // 存储原始点的集合
  let edgeDiffusionPoints = new Set(); // 存储边缘扩散点的集合
  let centerDiffusionPoints = new Set(); // 存储中心扩散点的集合

  // 生成原始点
  for (let i = 0; i < 2000; i++) {
    let t = Math.random() * 2 * Math.PI;
    let { x, y } = generateHeartCoordinate(t);
    originalPoints.add({ x, y });
  }

  // 从原始点生成边缘扩散点
  originalPoints.forEach(({ x, y }) => {
    for (let i = 0; i < 3; i++) {
      let newX = x, newY = y;
      newX += Math.random() * 5 - 2.5;
      newY += Math.random() * 5 - 2.5;
      edgeDiffusionPoints.add({ x: newX, y: newY });
    }
  });

  // 生成中心扩散点
  for (let i = 0; i < 6000; i++) {
    let { x, y } = Array.from(originalPoints)[Math.floor(Math.random() * originalPoints.size)];
    let newX = x, newY = y;
    newX += Math.random() * 15 - 7.5;
    newY += Math.random() * 15 - 7.5;
    centerDiffusionPoints.add({ x: newX, y: newY });
  }

  // 根据力的大小调整所有点的坐标,并将它们添加到allPoints数组中
  originalPoints.forEach(({ x, y }) => {
    let newX = x, newY = y;
    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
    newX -= ratio * force * (x - CANVAS_CENTER_X);
    newY -= ratio * force * (y - CANVAS_CENTER_Y);
    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 3 + 1) });
  });

  edgeDiffusionPoints.forEach(({ x, y }) => {
    let newX = x, newY = y;
    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
    newX -= ratio * force * (x - CANVAS_CENTER_X);
    newY -= ratio * force * (y - CANVAS_CENTER_Y);
    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 2 + 1) });
  });

  centerDiffusionPoints.forEach(({ x, y }) => {
    let newX = x, newY = y;
    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
    newX -= ratio * force * (x - CANVAS_CENTER_X);
    newY -= ratio * force * (y - CANVAS_CENTER_Y);
    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 2 + 1) });
  });

  // 绘制所有点
  allPoints.forEach(({ x, y, size }) => {
    context.fillStyle = HEART_COLOR;
    context.fillRect(x, y, size, size);
  });

  // 添加文本 "stormsha" 到爱心中间
  context.font = "bold 24px Arial";
  context.fillStyle = HEART_COLOR;
  context.textAlign = "center";
  context.fillText("stormsha", CANVAS_CENTER_X, CANVAS_CENTER_Y);
}

// 定义一个自定义的曲线函数,用于调整爱心的跳动效果
function customCurve(p) {
  return 2 * (2 * Math.sin(4 * p)) / (2 * Math.PI);
}

// 当文档加载完成时,开始动画
document.addEventListener("DOMContentLoaded", () => {
  // 获取画布和2d上下文
  const canvas = document.getElementById("heartCanvas");
  const context = canvas.getContext("2d");

  // 定义一些变量,用于控制动画
  let ratio = 0; // 力的大小比例
  let frame = 0; // 当前帧数

  // 动画函数
  function animate() {
    // 根据当前帧数计算力的大小比例
    ratio = 10 * customCurve(frame / 10 * Math.PI);
    // 调用drawHeart函数绘制爱心
    drawHeart(context, ratio, frame);
    // 增加帧数
    frame++;
    // 请求下一帧的动画
    requestAnimationFrame(animate);
  }

  // 开始动画
  animate();
});

这段代码实现了一个跳动的爱心动画。首先,它定义了一些常量,如画布的尺寸和爱心的颜色。然后,它定义了一个generateHeartCoordinate函数,用于生成爱心上的一个点的坐标。

接下来,它定义了一个drawHeart函数,用于绘制爱心。这个函数首先清空画布,然后绘制爱心的光晕部分,再绘制爱心的主体部分。最后,它添加了一些文本到爱心中间。

在文档加载完成后,代码会获取画布和2d上下文,并定义一些变量,如力的大小比例和当前帧数。然后,它会调用animate函数开始动画。

这个函数会根据当前帧数计算力的大小比例,然后调用drawHeart函数绘制爱心,并请求下一帧的动画。通过不断调用animate函数,就可以实现爱心的跳动效果。

2、创建love.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> <!-- 指定文档使用UTF-8字符编码 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 设置视口,以适应不同设备屏幕大小 -->
    <title>Beating Heart</title> <!-- 文档标题 -->
    <style>
        /* 样式表定义 */
        body {
            background-color: black; /* 设置页面背景颜色为黑色 */
            margin: 0; /* 去除页面默认边距 */
            overflow: hidden; /* 隐藏超出画布的内容 */
        }
        canvas {
            display: block; /* 将画布作为块级元素显示 */
            margin: auto; /* 使画布在页面中居中 */
        }
        .text {
            position: absolute; /* 将文本绝对定位 */
            top: 50%; /* 使文本距离页面顶部50% */
            left: 50%; /* 使文本距离页面左侧50% */
            transform: translate(-50%, -50%); /* 将文本向左、向上平移自身宽度和高度的一半,实现在页面中居中 */
            color: #FF69B4; /* 设置文本颜色为浅粉色 */
            font-family: '宋体'; /* 设置文本字体为宋体 */
            font-size: 18px; /* 设置文本大小为18像素 */
            text-align: center; /* 使文本内容居中 */
        }
    </style>
</head>
<body>
    <!-- 页面内容定义 -->
    <canvas id="heartCanvas" width="640" height="480"></canvas> <!-- 创建一个宽640像素、高480像素的画布,并设置其ID为heartCanvas -->
    <div class="text" style="top: 5%;">点燃我 温暖你</div> <!-- 创建一个文本元素,内容为“点燃我 温暖你”,并设置其样式类为text,距离页面顶部5% -->
    <script src="heart.js"></script> <!-- 引入heart.js脚本文件 -->
</body>
</html>

3、总结

heart.jslove.html 文件放在同一个文件夹下,用浏览器打开 love.html 文件即可看到效果

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

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

相关文章

【译】组复制和 Percona XtraDB 集群: 常见操作概述

原文地址&#xff1a;Group Replication and Percona XtraDB Cluster: Overview of Common Operations 在这篇博文中&#xff0c;我将概述使用 MySQL Group Replication 8.0.19&#xff08;又称 GR&#xff09;和 Percona XtraDB Cluster 8 (PXC)&#xff08;基于 Galera&…

Wireshark 4.2.5:发现 QUIC 和 VXLAN 协议的新功能

Wireshark 是一种先进且广泛使用的网络协议分析仪&#xff0c;最近发布了新版本 4.2.5&#xff0c;它提供了许多新功能和改进。 Wireshark 4.2.5 发行说明 什么是 Wireshark&#xff1f; Wireshark 是世界上最流行的网络协议分析器。它用于故障排除、分析、开发和教育。 Wiresh…

汇编:函数以及函数参数传递

汇编语言中的函数&#xff08;或过程&#xff09;是指一段可以被调用和执行的代码块&#xff1b;它们用于组织和重用代码&#xff0c;并使程序结构更加清晰&#xff1b;由于汇编语言没有高层次语言的语法糖&#xff0c;编写和调用函数涉及直接的堆栈操作和寄存器管理&#xff1…

《中国企业报》集团数字产业发展研究院介绍

《中国企业报》集团数字产业发展研究院&#xff08;以下简称“中企数研院”&#xff09;&#xff0c;隶属于《中国企业报》集团管理。“中企数研院”致力于“数字经济产业化发展战略”大背景下&#xff0c;以“县域数字经济”、“企业数字化转型”及“数字人民币”推广等发展方…

Vue3实战笔记(35)—集成炫酷的粒子特效

文章目录 前言一、vue3使用tsparticles二、使用步骤总结 前言 学习一个有趣炫酷的玩意开心一下。 tsparticles&#xff0c;可以方便的实现各种粒子特效。支持的语言框架也是相当的丰富. 官网&#xff1a;https://particles.js.org/ 一、vue3使用tsparticles 先来个vue3使用…

大语言模型的工程技巧(四)——梯度检查点

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文将讨论如何利用梯度检查点算法来减少模型在训练时候&#xff08;更准确地说是运行反向传播算法时&#xff09;的内存开支。…

【Spring Cloud】全面解析服务容错中间件 Sentinel 持久化两种模式

文章目录 推送模式本地文件持久化&#xff08;拉模式&#xff09;配置yml编写处理类添加配置演示 配置中心持久化&#xff08;推模式&#xff09;修改nacos在sentinel中生效引入依赖配置文件 修改sentinel在nacos中生效下载源码更改代码演示 总结 推送模式 Sentinel 规则的推送…

网络安全快速入门(十五) linux用户管理

14.1 前言 前面我们已经大概了解了Linux的网络链接&#xff0c;今天我们来看看Linux用户管理的一些基础操作&#xff0c;话不多说&#xff0c;我们来开始吧&#xff01;&#xff01; 14.2 用户的基础知识 我们先了解一些有关linux用户的一些基础知识&#xff0c;我们从Linux用…

告别传统,拥抱未来——上门回收小程序引领变革

随着科技的飞速发展&#xff0c;我们生活的方方面面都在经历着前所未有的变革。在环保和可持续发展的背景下&#xff0c;传统的废品回收方式已经难以满足现代社会的需求。而上门回收小程序的出现&#xff0c;正以其便捷、高效的特点&#xff0c;引领着废品回收行业的变革。 一、…

Threejs路径规划_基于A*算法案例完整版

上节利用了A*实现了基础的路径规划&#xff0c;这节把整个功能完善好&#xff0c;A*算法一方面是基于当前点找到可以到达的点&#xff0c;计算从出发点到此点&#xff0c;以及此点到目的地的总成本&#xff0c;比较出最小的那个&#xff0c;再用最小成本的点继续找到它可以到达…

LabVIEW与串口通讯在运行一段时间后出现数据接收中断的问题

这些问题可能与硬件、软件或通信协议有关。以下是详细的原因分析和可能的解决方案&#xff1a; 一、硬件原因 串口线缆或接口问题&#xff1a; 由于长时间使用&#xff0c;串口线缆可能出现接触不良或损坏。接口松动也可能导致通讯中断。 解决方案&#xff1a;检查并更换串口…

Sentinel重要的前置知识

文章目录 1、雪崩问题及解决方案1.1、雪崩问题1.2、超时处理1.3、仓壁模式1.4、断路器1.5、限流1.6、总结 2、服务保护技术对比3、Sentinel介绍和安装3.1、初识Sentinel3.2、安装Sentinel 4、微服务整合Sentinel ​&#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在…

Java进阶-SpringCloud使用BeanUtil工具类简化对象之间的属性复制和操作

在Java编程中&#xff0c;BeanUtil工具类是一种强大且便捷的工具&#xff0c;用于简化对象之间的属性复制和操作。本文将介绍BeanUtil的基本功能&#xff0c;通过详细的代码示例展示其应用&#xff0c;并与其他类似工具进行对比。本文还将探讨BeanUtil在实际开发中的优势和使用…

QML英文拟态键盘,英文数字符号输入法

文章目录 QML 英文拟态键盘思维导图更多细节欢迎私信效果图&#xff1a;核心代码&#xff1a;KeyboardLetter.qml&#xff0c;**CustomerKeyboard.qml**&#xff0c;Example.qmlCustomerKeyboard.qmlButton.qmlButtonBase.qmlButtonStateImage.qmlDialogBase.qmlExample.qmlIma…

必示科技参与智能运维国家标准预研线下编写会议并做主题分享

近日&#xff0c;《信息技术服务 智能运维 第3部分&#xff1a;算法治理》&#xff08;拟定名&#xff09;国家标准预研阶段第一次编写工作会议在杭州举行。本次会议由浙商证券承办。 此次编写有来自银行、证券、保险、通信、高校研究机构、互联网以及技术方等29家单位&#xf…

ESP32 实现获取天气情况

按照小安派AiPi-Eyes天气站思路&#xff0c;在ESP32 S3上实现获取天气情况。 一、在ESP32 S3实现 1、main.c 建立2个TASK void app_main(void) {//lvgl初始化xTaskCreate(guiTask, "guiTask", 1024 * 6, NULL, 5, NULL);//wifi初始化、socket、json处理taskcustom_…

ue5 中ps使用记录贴

一、快捷键记录 放大图形 ctrlalt空格 放大图形 缩小视口 ctrl空格 ctrlD 取消选区 ctrlt缩小文字 w魔棒工具 选择魔棒的时候把容差打开的多一点 二、案例 移动文字 在相应的图层选择 移动文字 修改图片里的颜色 在通道里拷贝红色通道&#xff0c;复制红色通道粘贴给正常图…

Softing工业将亮相2024年阿赫玛展会——提供过程自动化的连接解决方案

您可于2024年6月10日至14日前往美因河畔法兰克福11.0号馆&#xff0c;Softing将在C25展位展出&#xff0c;欢迎莅临&#xff01; 作为工业应用中数据交换领域公认的专家&#xff0c;Softing工业致力于帮助各行各业的客户部署网络自动化和优化生产流程。 使用Softing产品&…

kind: Telemetry

访问日志 访问日志提供了一种从单个工作负载实例的角度监控和理解行为的方法。 Istio 能够以一组可配置的格式为服务流量生成访问日志&#xff0c; 使操作员可以完全控制日志记录的方式、内容、时间和地点。 有关更多信息&#xff0c;请参阅获取 Envoy 的访问日志。 https:/…

TAS5711带EQ和DRC支持2.1声道的20W立体声8V-26V数字输入开环D类数字功放音频放大器

前言 数字功放很难搞&#xff0c;寄存器很多&#xff0c;要配置正确才有声音&#xff0c;要想声音好&#xff0c;要好好调整。 TAS5711出道很多年了&#xff0c;现在仍然在不少功放、音箱中能看到。 TAS5711特征 音频输入/输出 从 18V 电源向 8Q 负载提供 20W 功率 宽 PVDD…