通过canvas画出爱心图案,表达你的爱意!
创始人
2024-05-29 22:31:05
0

在这里插入图片描述
通过canvas画出爱心图案,浏览器可以使用以下js代码,新建对象时,会自动呈现动画效果,代码文末可下载。

点击免费下载源码

let HeartCanvas = new HeartCanvas()

/*** 爱心* Heart Canvas*/class HeartCanvas {/*** @param hMin 颜色 h 最小值* @param hMax 颜色 h 最大值* @param countHeart 心的数量* @param sizeMin 心形最小值* @param sizeMax 心形最大值* @param bgColor 背景颜色*/constructor(hMin, hMax, countHeart = 150, sizeMin = 50, sizeMax = 350, bgColor) {this.isPlaying = true // 默认自动播放this.mouseX = 0this.mouseY = 0this.configFrame = {width : 1200,height: 300,bgColor: bgColor}this.configHeart = {timeLine: 0,                           // 时间线timeInit: new Date().getTime(),movement: 1,                           // 运动速度x: 50,                                 // 位置 xy: 50,                                 // 位置 ywidth: 200,                            // heart 大小height: 200,                           // heart 大小countHeart: countHeart || 150,         // heart 数量// 大小sizeMin: isNaN(sizeMin) ?50: sizeMin,  // 最小值sizeMax: isNaN(sizeMax) ?350: sizeMax, // 最大值// 颜色colorSaturate: 100,                    // 颜色饱和度 0-100colorLight: 60,                        // 颜色亮度 0-100hMin: isNaN(hMin) ?330: hMin,          // 色值最小hMax: isNaN(hMax) ?350: hMax,          // 色值最大minOpacity: 20,                        // 透明度最小 %maxOpacity: 100,                       // 透明度最大 %opacityGrowth: 5,                      // 透明度增长值// 出现的位置范围heartRangeMin: 0,                      // 心出现的位置,从下面算起,取值 0.0-1.0heartRangeMax: 0.3,// 加速度gravityMin: 1,                         // 加速度 mingravityMax: 9.8,                       // 加速度 maxflowDirection: 1,                      // 运动方向 1 向上 -1 向下}this.heartBuffer = [] // 心缓存this.init()window.onresize = () => {this.configFrame.height = innerHeight * 2this.configFrame.width = innerWidth * 2let heartLayer = document.getElementById('heartLayer')this.updateFrameAttribute(heartLayer)}}play(){if (this.isPlaying){} else {this.isPlaying = truethis.draw()}}stop(){this.isPlaying = false}moveDown(){this.configHeart.flowDirection = -1}moveUp(){this.configHeart.flowDirection = 1}speedUp(){}speedDown(){}destroy(){this.isPlaying = falselet heartLayer = document.getElementById('heartLayer')heartLayer.remove()console.log('动画已停止')}updateFrameAttribute(heartLayer){heartLayer.setAttribute('id', 'heartLayer')heartLayer.setAttribute('width', this.configFrame.width)heartLayer.setAttribute('height', this.configFrame.height)heartLayer.style.width = `${this.configFrame.width / 2}px`heartLayer.style.height = `${this.configFrame.height / 2}px`heartLayer.style.zIndex = '-3'heartLayer.style.userSelect = 'none'heartLayer.style.position = 'fixed'heartLayer.style.top = '0'heartLayer.style.left = '0'}init(){this.configFrame.height = innerHeight * 2this.configFrame.width = innerWidth * 2let heartLayer = document.createElement("canvas")this.updateFrameAttribute(heartLayer)document.documentElement.append(heartLayer)this.configHeart.timeLine =  0// 填充缓存形状for (let i = 0; i < this.configHeart.countHeart; i++) {let randomSize = randomInt(this.configHeart.sizeMin, this.configHeart.sizeMax)let x = randomInt(0, this.configFrame.width)let y = randomInt(this.configFrame.height * (1-this.configHeart.heartRangeMax), this.configFrame.height * (1-this.configHeart.heartRangeMin))this.heartBuffer.push({id: i,gravity: randomFloat(this.configHeart.gravityMin, this.configHeart.gravityMax),opacity: 0,opacityFinal: randomInt(this.configHeart.minOpacity, this.configHeart.maxOpacity), // 最终透明度timeInit: randomInt(1, 500), // 随机排布初始 heart 的位置x, // 位置 xy, // 位置 yoriginalX: x,originalY: y,width: randomSize,  // heart 大小height: randomSize, // heart 大小colorH: randomInt(this.configHeart.hMin, this.configHeart.hMax)})}this.draw()document.documentElement.addEventListener('mousemove', event => {this.mouseX = event.xthis.mouseY = event.y})}// 判断鼠标跟 box 的距离isMouseIsCloseToBox(box){let distance = Math.sqrt(Math.pow(Math.abs(box.position.x / 2 - this.mouseX),2) + Math.pow(Math.abs(box.position.y /2  - this.mouseY), 2))return distance < 100}draw() {// 建立自己的时间参考线,消除使用系统时间时导致的切换程序后时间紊乱的情况this.configHeart.timeLine = this.configHeart.timeLine + 1// create heartlet canvasHeart = document.getElementById('heartLayer')let contextHeart = canvasHeart.getContext('2d')contextHeart.clearRect(0, 0, this.configFrame.width, this.configFrame.height)// 背景,没有 bgColor 的时候,背景就是透明的if (this.configFrame.bgColor){contextHeart.fillStyle = this.configFrame.bgColorcontextHeart.fillRect(0,0,this.configFrame.width, this.configFrame.height)}this.heartBuffer.forEach(heart => {// 当出了画面时if (heart.y < -(heart.height)){heart.y = heart.originalYheart.timeInit = this.configHeart.timeLine // 重新定位时间节点heart.opacity = 0}// 当透明度到达最终透明度时let timeGap = this.configHeart.timeLine - heart.timeInit // 时间为正数时才计算透明度if (timeGap > 0){heart.opacity = heart.opacity * ((this.configHeart.timeLine - heart.timeInit)/100)} else { // 没到该 heart 的展示时间时,透明度为 0,不显示heart.opacity = 0}if (heart.opacity >= heart.opacityFinal){heart.opacity = heart.opacityFinal // 定位到最终的透明度}// 1/2 gt㎡  运动轨迹// let movement = 1/2 * this.configHeart.gravity * Math.pow((new Date().getTime() - heart.timeInit)/1000,2)// speed = 1/2 gtlet movement = 1/2 * heart.gravity * (this.configHeart.timeLine - heart.timeInit) / 300 * this.configHeart.flowDirectionheart.y = heart.y - movementthis.drawHeart(heart.x,heart.y,heart.width / 2,heart.height / 2,`hsl(${heart.colorH} ${this.configHeart.colorSaturate}% ${this.configHeart.colorLight}% / ${heart.opacity}%)`)heart.opacity = heart.opacity + this.configHeart.opacityGrowth})if (this.isPlaying) {window.requestAnimationFrame(() => {this.draw()})}}// 画一个心drawHeart(x, y, width, height, colorFill) {let canvasHeart = document.getElementById('heartLayer')let contextHeart = canvasHeart.getContext('2d')contextHeart.save()contextHeart.beginPath()let topCurveHeight = height * 0.3contextHeart.moveTo(x, y + topCurveHeight)// top left curvecontextHeart.bezierCurveTo(x, y,x - width / 2, y,x - width / 2, y + topCurveHeight)// bottom left curvecontextHeart.bezierCurveTo(x - width / 2, y + (height + topCurveHeight) / 2,x, y + (height + topCurveHeight) / 1.4,x, y + height)// bottom right curvecontextHeart.bezierCurveTo(x, y + (height + topCurveHeight) / 1.8,x + width / 2, y + (height + topCurveHeight) / 2,x + width / 2, y + topCurveHeight)// top right curvecontextHeart.bezierCurveTo(x + width / 2, y,x, y,x, y + topCurveHeight)contextHeart.closePath()contextHeart.fillStyle = colorFillcontextHeart.fill()contextHeart.restore()}}/*** 输出随机 1 或 -1* @returns {number}*/
function randomDirection(){let random = Math.random()if (random > 0.5){return 1} else {return -1}
}/*** 生成随机整数* @param min* @param max* @returns {number}*/
function randomInt(min, max){return Number((Math.random() * (max - min) + min).toFixed(0))
}/*** 生成随机整数* @param min* @param max* @returns {number}*/
function randomFloat(min, max){return Number(Math.random() * (max - min) + min)
}

Vue可通过以下方式导入,代码在文末可下载:

import {HeartCanvas} from "animate-heart-canvas"export default {mounted() {this.height = innerHeightthis.animateHeartCanvas = new AnimateHeartCanvas()},beforeDestroy() {this.animateHeartCanvas.destroy()}
}

API

  • @param hMin 颜色 h 最小值
  • @param hMax 颜色 h 最大值
  • @param countHeart 心的数量
  • @param sizeMin 心形最小值
  • @param sizeMax 心形最大值
  • @param bgColor 背景颜色

let HeartCanvas = new HeartCanvas(hMin, hMax, countHeart, sizeMin, sizeMax, bgColor)
// hMin hMax 对应 hue 的颜色值
// 什么参数都不写就是红色

let 五颜六色 = new HeartCanvas(0, 360) // 这个就是五颜六色的

// 其它操作
HeartCanvas.play() // 心动起来
HeartCanvas.stop() // 心不动
HeartCanvas.moveUp() // 心向上走
HeartCanvas.moveDown() // 心向下走

点击免费下载源码

相关内容

热门资讯

保时捷卡宴香氛系统安装,为您的... 为您的保时捷卡宴升级香氛系统,提升驾驶体验随着汽车科技的不断发展,越来越多的豪华汽车开始配备香氛系统...
windows查看最近一次系统... 如何在Windows系统中查看最近一次系统安装时间随着计算机技术的不断发展,操作系统已经成为我们日常...
windows操作系统86位,... 深入解析Windows操作系统的86位版本:优势与挑战随着计算机技术的不断发展,操作系统也在不断进化...
安卓系统如何安装whatAPP 安卓系统如何安装WhatsApp:一步步教程WhatsApp是一款全球流行的即时通讯应用程序,它允许...
安装音箱系统,打造完美音质体验... 打造完美音质体验——家庭音箱系统安装指南随着生活品质的提升,越来越多的家庭开始注重家庭影院的搭建。而...
windows安装到系统盘,W... Windows系统安装到系统盘的详细步骤准备工作在开始安装Windows系统之前,请确保以下准备工作...
windows查看操作系统命令... Windows操作系统命令详解在Windows操作系统中,命令行界面(Command Prompt)...
安卓机咋安装ios系统,安卓机... 安卓机如何安装iOS系统?揭秘安卓手机变身iPhone的奥秘一、理论可行性从理论上来说,安卓手机安装...
windows恢复mac系统下... Windows恢复Mac系统:下载与安装指南一、了解Mac系统恢复的必要性在Mac电脑上安装Wind...
安卓6安装ios系统,揭秘跨平... 安卓6安装iOS系统:揭秘跨平台操作系统的可能性一、安卓6安装iOS系统的可行性分析首先,我们需要明...
windows盗版系统安全吗,... Windows盗版系统安全吗?揭秘盗版软件的风险与隐患随着信息技术的飞速发展,操作系统作为电脑的核心...
windows安全模式进不去系... Windows安全模式进不去系统?教你解决方法!在Windows操作系统中,安全模式是一种特殊的启动...
Windows95进系统要多少... Windows 95进系统所需内存解析Windows 95,作为微软历史上一个重要的操作系统里程碑,...
windows安装乌班图双系统... Windows安装乌班图双系统教程随着Linux系统的普及,越来越多的用户开始尝试在Windows系...
windows查看系统版本kb... Windows系统版本KB号查看方法详解在Windows操作系统中,KB号(Knowledge Ba...
windows黑屏重装系统,轻... Windows黑屏重装系统全攻略:轻松解决系统故障在电脑使用过程中,遇到黑屏问题是一种常见的故障。黑...
windows98系统文件国漫... Windows 98系统下的国漫之旅:重温经典,感受时光流转一、Windows 98:那个时代的电脑...
windows94系统,win... Windows 94系统:一个未曾实现的操作系统传奇在微软的操作系统历史长河中,Windows 94...
安装重装联想系统,轻松应对系统... 联想电脑系统重装全攻略:轻松应对系统故障随着电脑使用时间的增长,系统故障和卡顿问题时有发生。对于联想...
windows激活系统怎么下载... Windows激活系统下载全攻略:轻松激活,畅享系统体验一、了解Windows激活的重要性Windo...