300行HTML+CSS+JS代码实现动态圣诞树

news2024/11/20 3:35:02

文章目录

  • 1. 前言
  • 2. 效果展示
  • 3. 准备
    • 🍑 下载编译器
    • 🍑 下载插件
  • 4. 源码
    • 🍑 HTML
    • 🍑 JS
    • 🍑 CSS
  • 5. 结语


1. 前言

一年一度的圣诞节和考研即将来临,那么这篇文章将用到前端三大剑客 HTML + CSS + JS 来实现动态圣诞树!

在这里插入图片描述

2. 效果展示

在手机上还可以通过左右滑动来控制雪花的方向哦!

在这里插入图片描述

3. 准备

🍑 下载编译器

这里的话推荐使用 VScode(方便!)

在这里插入图片描述

🍑 下载插件

Auto Rename Tag:改善标签后自动完善

在这里插入图片描述

Chinses语言包:把编译器语言换成中文(默认英文)

在这里插入图片描述

open in browser:让代码在网页中打开,快捷键 Alt + B

在这里插入图片描述

4. 源码

以下源码都已经准备好了,大家复制即可。

🍑 HTML

代码示例

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>CodePen - Christmas Tree and Snow</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="./style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<canvas id="canvas"></canvas>
<div class="overlay"></div>
<!-- partial -->
  <script  src="./script.js"></script>

</body>
</html>

🍑 JS

代码示例

// Particle Lib

function Particle(x, y, speed, angle) {
  this.x = x;
  this.y = y;

  this.vx = Math.cos(angle || 0) * (speed || 0);
  this.vy = Math.sin(angle || 0) * (speed || 0);
}

Particle.prototype.updatePosition = function () {
  this.x += this.vx;
  this.y += this.vy;
};

Particle.prototype.draw = function (ctx) {
  ctx.fillStyle = this.color;
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
  ctx.fill();
};

// Snowing

var numOfSnowParticles = 100;
var snowParticles = [];
var windFromLeft = false;
var windFromRight = false;

function createSnowParticles() {
  let particle = new Particle(Math.random() * screenWidth, -10, 1, 2 * Math.PI / 2 * Math.random());
  particle.originalX = particle.x;
  particle.originalY = particle.y;
  particle.radius = 1 + Math.random() * 2;
  particle.angle = 0;
  particle.speed = .05;
  particle.isDead = false;
  particle.color = "white";
  snowParticles.push(particle);
}


function drawSnowFrame() {
  for (var i = 0; i < snowParticles.length; i++) {
    let particle = snowParticles[i];

    if (!particle.isDead) {

      particle.updatePosition();

      if (!windFromLeft && !windFromRight) {
        particle.x = particle.originalX + Math.sin(particle.angle) * 10;
      } else if (windFromLeft) {
        particle.x += 2;
        particle.originalX = particle.x;
      } else if (windFromRight) {
        particle.x -= 2;
        particle.originalX = particle.x;
      }

      particle.y += .1;
      particle.angle += particle.speed;

      checkIfParticleTouchesADeadParticle(i);
      checkIfParticleHitsGround(particle);
    }
    particle.draw(context);
  }
}

function checkIfParticleHitsGround(particle) {
  if (particle.y + particle.radius > screenHeight) {
    particle.y = screenHeight - particle.radius;
    particle.isDead = true;
  }
}

function checkIfParticleTouchesADeadParticle(index) {

  for (var i = index + 1; i < snowParticles.length; i++) {

    if (snowParticles[i].isDead) {
      let dx = snowParticles[index].x - snowParticles[i].x;
      let dy = snowParticles[index].y - snowParticles[i].y;

      let distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));

      if (distance <= snowParticles[index].radius + snowParticles[i].radius) {
        snowParticles[index].isDead = true;
      }
    }
  }
}

document.addEventListener('touchstart', handleTouchStart, false);
document.addEventListener('touchmove', handleTouchMove, false);

var xDown = null;
var yDown = null;

function handleTouchStart(evt) {
  xDown = evt.touches[0].clientX;
  yDown = evt.touches[0].clientY;
};

function handleTouchMove(evt) {
  if (!xDown || !yDown) {
    return;
  }

  var xUp = evt.touches[0].clientX;
  var yUp = evt.touches[0].clientY;

  var xDiff = xDown - xUp;
  var yDiff = yDown - yUp;

  if (Math.abs(xDiff) > Math.abs(yDiff)) {
    if (xDiff > 0) {
      windFromRight = true;
      windFromLeft = false;
    } else {
      windFromLeft = true;
      windFromRight = false;
    }
  } else {
    windFromLeft = windFromRight = false;
  }

  xDown = null;
  yDown = null;
};

// Tree 

var treeParticles = [];
var treeColors = ['#199642', '#E44822', '#40B8E2', '#F7D231'];

function drawTreeFrame() {
  for (var i = 0; i < treeParticles.length; i++) {
    treeParticles[i].draw(context);
    treeParticles[i].radius = 1 + Math.random() * 3;
  }

  if (treeParticles.length > 0) {
    drawStar(centerX, screenHeight * .2, 5, 20, 10);
  }
}

function getPixelData(imageData, x, y) {
  let basePosition = (screenWidth * y + x) * 4;
  return {
    r: imageData.data[basePosition],
    g: imageData.data[basePosition + 1],
    b: imageData.data[basePosition + 2],
    a: imageData.data[basePosition + 3] };

}

function drawStar(cx, cy, spikes, outerRadius, innerRadius) {
  var rot = Math.PI / 2 * 3;
  var x = cx;
  var y = cy;
  var step = Math.PI / spikes;

  context.beginPath();
  context.moveTo(cx, cy - outerRadius);
  for (i = 0; i < spikes; i++) {
    x = cx + Math.cos(rot) * outerRadius;
    y = cy + Math.sin(rot) * outerRadius;
    context.lineTo(x, y);
    rot += step;

    x = cx + Math.cos(rot) * innerRadius;
    y = cy + Math.sin(rot) * innerRadius;
    context.lineTo(x, y);
    rot += step;
  }
  context.lineTo(cx, cy - outerRadius);
  context.closePath();
  context.lineWidth = 5;
  context.strokeStyle = 'yellow';
  context.stroke();
  context.fillStyle = 'lightyellow';
  context.fill();
}

function initTree(text) {
  context.clearRect(0, 0, screenWidth, screenHeight);

  context.moveTo(centerX, screenHeight * .2);
  context.lineTo(centerX - 100, centerY + 100);
  context.lineTo(centerX + 100, centerY + 100);
  context.fill();

  var imageData = context.getImageData(0, 0, screenWidth, screenHeight);

  context.clearRect(0, 0, screenWidth, screenHeight);

  treeParticles.length = 0;

  for (var i = 0; i < screenWidth; i += 10) {
    for (j = 0; j < screenHeight; j += 10) {

      let pixelData = getPixelData(imageData, i, j);

      if (pixelData.a > 0) {
        let particle = new Particle(i, j);
        particle.color = treeColors[Math.floor(Math.random() * 5)];
        particle.radius = 1 + Math.random() * 3;
        treeParticles.push(particle);
      }
    }
  }
}


//let canvas = document.querySelector('#canvas');
let context = canvas.getContext('2d');
let screenWidth = canvas.width = window.innerWidth;
let screenHeight = canvas.height = window.innerHeight;

var centerX = screenWidth * .5;
var centerY = screenHeight * .5;

drawFrame();
function drawFrame() {
  context.clearRect(0, 0, screenWidth, screenHeight);

  context.fillStyle = "black";
  context.fillRect(0, 0, screenWidth, screenHeight);

  context.fillStyle = "white";
  context.font = "bold 50px Kaushan Script";
  context.textAlign = "center";
  context.fillText("Merry Christmas", centerX, screenHeight * .8);

  drawTreeFrame();
  drawSnowFrame();
  requestAnimationFrame(drawFrame);
}

initTree('hello world');
setInterval(() => {
  createSnowParticles();
}, 100);

🍑 CSS

代码示例

@import url("https://fonts.googleapis.com/css?family=Great+Vibes|Kaushan+Script");
body {
  margin: 0;
}

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 10;
  color: white;
  width: 100%;
  text-align: center;
  padding: 5px;
  font-family: "Avenir", "Helvetica";
}

5. 结语

属于 2022 的时间,不知不觉进入了倒计时!

准备多时的 “马拉松”,即将抵达终点!

时光不负有心人,星光不负赶路人。

祝大家圣诞快乐,也愿各位考研人一战成硕!!!

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

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

相关文章

Java面试题(六)多线程经典编程题

经典的多线程编程题猜数字游戏键盘输入练习3个线程轮流打印ABC多窗口买票猜数字游戏 题目说明&#xff1a;有2个线程&#xff0c;第一个线程A随机一个100内的数&#xff0c;第2个线程B来猜&#xff0c;B每次猜一个数后A会判断&#xff0c;如果猜对了程序结束&#xff0c;如果猜…

工具在接口测试中发挥什么样的作用?

接口测试究竟是什么&#xff1f;为什么要用接口测试&#xff1f;它有哪些工具呢&#xff1f;这一连串的问题敲击着我们&#xff0c;请带着这些问题&#xff0c;在本文中寻找答案&#xff0c;我将为您打开接口测试的大门。 1 初探接口测试 接口测试是什么。它检查数据的交换&…

从《我要投资》,看藏在“对立面”里的创业正解

文|智能相对论 作者|青月 六位07届的快乐男声选手在象山体验养鹅&#xff0c;意外出圈&#xff1b;随后播出的09届超女的怀旧综艺却热度一般&#xff0c;可见只有单纯的情怀消费并不能保证节目的口碑&#xff0c;只有建立在准确的节目定位与恰当的价值输出基础上&#xff0c;…

面试必备:从常见的存储引擎到混淆的锁分类,请上车

今天我们来总结一下MyISAM和InnoDB引擎下锁的种类及使用方法。 MySQL的四大常见存储引擎 谈到MyISAM和InnoDB了我们先来了解一下什么是存储引擎吧。MySQL中的数据用各种不同的技术存储在文件&#xff08;或者内存&#xff09;中&#xff0c;这些技术中的每一种技术都使用不同…

m基于贝叶斯理论的超分辨率重构算法matlab仿真,对比Tikhonov重构算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 超分辨率(Super-Resolution)通过硬件或软件的方法提高原有图像的分辨率&#xff0c;通过一系列低分辨率的图像来得到一幅高分辨率的图像过程就是超分辨率重建。超分辨率成像&#xff08;SR-imagi…

一个内核oops问题的分析及解决

最近在调试设备时&#xff0c;遇到了一个偶发的开机死机问题。通过查看输出日志&#xff0c;发现内核报告了oops错误&#xff0c;如下所示&#xff08;中间省略了部分日志&#xff0c;以......代替&#xff09;&#xff1a; Unable to handle kernel NULL pointer dereference…

YOLOV7学习记录之训练过程

在前面学习YOLOV7的过程中&#xff0c;我们已经学习了其网络结构&#xff0c;然而实际上YOLOV7项目的难点并不在于其网络模型而是在于其损失函数的设计&#xff0c;即如何才能训练出来合适的bbox。 神经网络模型都有训练和测试&#xff08;推理&#xff09;过程&#xff0c;在Y…

QT JS交互、调用JS、传值

本文详细的介绍了QT JS交互、调用JS、传值的各种操作&#xff0c;包括QT向JS传递String字符串、包括QT向JS传递Int数字、包括QT向JS传递List数组&#xff0c;同时也接收JS向QT返回的List数组、JS向QT返回的Json、JS向QT返回的数字、JS向QT返回的字符串。 本文作者原创&#xff…

Vue基础8之Vue组件化编程、非单文件组件与单文件组件

Vue基础8Vue组件化编程对组件的理解一些概念的理解非单文件组件基本使用几个注意点组件的嵌套VueComponent一个重要的内置关系先导篇&#xff1a;原型对象正文&#xff08;可以理解为类的继承&#xff09;单文件组件Vue组件化编程 对组件的理解 传统方式&#xff1a; 使用组…

计算机网络-交换方式

目录电路交换&#xff08;Circuit Switching&#xff09;分组交换&#xff08;Packet Switching&#xff09;报文交换&#xff08;Message Switching&#xff09;电路交换、报文交换、分组交换的对比电路交换&#xff08;Circuit Switching&#xff09; 在电话问世后不久&#…

扫雷游戏的设计(百分百还原电脑操作)

目录 &#x1f332;了解扫雷游戏的作用原理并梳理思路 &#x1f332;扫雷游戏前期部分完善 &#x1f337;文件的创建 &#x1f337;创建菜单&#xff0c;完善主函数 &#x1f333;代码呈现&#xff1a; &#x1f332;扫雷游戏主题内容 &#x1f334;第一步初始化棋盘 &#x1…

Gradle中如何修改Springboot引入的依赖版本

扫描漏洞升级 不知道各位是否遇到过以下问题&#xff1a; 当下层项目将spring引入的某个依赖版本升级之后&#xff0c;上层项目只要指定了Springboot版本&#xff0c;那么还是会将这个版本改回去&#xff1f; 比如&#xff1a;现在有两个Springboot项目A、B&#xff0c;B项目…

Git安装和配置

GitGitee 官网安装配置教程&#xff1a;https://gitee.com/help/articles/4104本文是以官网教程为基础而展开的实践笔记。初学者可以以本文为引入&#xff0c;但建议最终以官方文档为最终深入学习的参考。一、 下载和安装Git 1、官网下载&#xff1a;https://git-scm.com 如果对…

HTML5基础

HTML5 文章目录HTML5概述开发工具浏览器开发软件DemoHTML5语法HTML5标签HTML5标签属性HTML5文档注释HTML5文档结构头部内容主体内容DemoHTML5常见标签常见块级标签标题标签水平线标签段落标签换行标签引用标签预格式标签无序列表标签有序列表标签定义列表标签分区标签常见行级标…

【Java寒假打卡】Java基础-继承

【Java寒假打卡】Java基础-继承一、继承的好处和弊端二、继承的成员变量访问特点三、重写方法四、方法重写的注意事项五、权限修饰符六、构造方法一、继承的好处和弊端 继承的好处 提高了代码的复用性 提高了代码的维护性 让类和类之间产生了关系 是多态的前提 继承的弊端 …

Flink-使用filter和SideOutPut进行分流操作

文章目录1.什么是分流&#xff1f;2. 过滤器(filter)3. 使用侧输出流&#xff08;SideOutput&#xff09;&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e; 更多资源链接&#xff0c;欢迎访问作者gitee仓库&#xff1a;https://gitee.com/fanggaolei/learni…

四、网络层(七)网络层设备

目录 7.1 路由器的组成和功能 7.2 路由表与路由转发 7.1 路由器的组成和功能 路由器是一种具有多个输入/输出端口的专用计算机&#xff0c;其任务是连接不同的网络&#xff08;可以是异构的&#xff09;并完成路由转发。在多个逻辑网络&#xff08;即多个广播域&#xff…

Vulnhub靶机:HACKADEMIC_ RTB1

目录介绍信息收集主机发现主机信息探测网站探测Sql注入挂马提权介绍 系列&#xff1a;Hackademic&#xff08;此系列共2台&#xff09; 发布日期&#xff1a;2011年9月6日 难度&#xff1a;初级 运行环境&#xff1a;VMware Workstation 目标&#xff1a;取得 root 权限 flag…

5W2H分析法

什么是5W2H 5W2H分析法又叫七何分析法&#xff0c;是二战中美国陆军兵器修理部首创。简单、方便&#xff0c;易于理解、使用&#xff0c;富有启发意义&#xff0c;广泛用于企业管理和技术活动&#xff0c;对于决策和执行性的活动措施也非常有帮助&#xff0c;也有助于弥补考虑…

【UE4 第一人称射击游戏】07-添加“AK47”武器

素材资料地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1epyD62jpOZg-o4NjWEjiyg 密码&#xff1a;jlhr 效果&#xff1a; 步骤&#xff1a; 1.打开“WalkRun_BS”&#xff0c;将内插时间改为1 2.创建一个文件夹&#xff0c;命名为“Weapons” 进入“Weapons”…