React 实现爱心花园动画

主页:

import React, { useEffect, useRef, useState } from 'react';
import '@/assets/css/Love.less';
import { Garden } from '@/utils/GardenClasses';// 组件属性接口
interface LoveAnimationProps {startDate?: Date; // 可选的开始日期messages?: {      // 可自定义的文本消息initial?: string;   // 初始文字love?: string;      // 告白文字signature?: string; // 落款};
}// 默认开始日期:2010年11月2日20点
const DEFAULT_START_DATE = new Date(2010, 10, 2, 20, 0, 0);// 默认文本配置
const DEFAULT_MESSAGES = {initial: "亲爱的,这是我们相爱在一起的时光。",love: "爱你直到永永远远。",signature: "-爱你的人"
};const LoveAnimation: React.FC<LoveAnimationProps> = ({startDate = DEFAULT_START_DATE,messages = DEFAULT_MESSAGES
}) => {// ========== Refs定义 ==========const canvasRef = useRef<HTMLCanvasElement>(null);      // 画布引用const gardenRef = useRef<Garden | null>(null);          // 花园实例引用const loveHeartRef = useRef<HTMLDivElement>(null);      // 心形容器const contentRef = useRef<HTMLDivElement>(null);        // 内容容器const codeRef = useRef<HTMLDivElement>(null);           // 代码区域const wordsRef = useRef<HTMLDivElement>(null);          // 文字区域const messagesRef = useRef<HTMLDivElement>(null);       // 消息区域const loveURef = useRef<HTMLDivElement>(null);          // 告白区域const elapseClockRef = useRef<HTMLDivElement>(null);    // 计时器const errorMsgRef = useRef<HTMLDivElement>(null);       // 错误信息// ========== 状态定义 ==========const [showMessages, setShowMessages] = useState(false); // 是否显示消息const [showLoveU, setShowLoveU] = useState(false);      // 是否显示告白const [codeContent, setCodeContent] = useState('');     // 代码内容const [showCursor, setShowCursor] = useState(false);    // 是否显示光标const [clearVal, setClearVal] = useState(true);         // 清除标志const clearValRef = useRef(clearVal);                   // 清除标志的ref// 动画定时器存储const animationRefs = useRef<{ intervals: NodeJS.Timeout[]; // 间隔定时器timeouts: NodeJS.Timeout[];  // 延时定时器}>({ intervals: [], timeouts: [] });// 完整的代码内容(带HTML格式)const fullCodeContent = `<br />/**<br />*2013—02-14,<br />*2013-02-28.<br />*/<br />Boy name = <span class="keyword">Mr</span> ***<br />Girl name = <span class="keyword">Mrs</span> ***<br /><span class="comments">// Fall in love river.</span><br />The boy love the girl;<br /><span class="comments">// They love each other.</span><br />The girl loved the boy;<br /><span class="comments">// AS time goes on.</span><br />The boy can not be separated the girl;<br /><span class="comments">// At the same time.</span><br />The girl can not be separated the boy;<br /><span class="comments">// Both wind and snow all over the sky.</span><br /><span class="comments">// Whether on foot or 5 kilometers.</span><br /><span class="keyword">The boy</span> very <span class="keyword">happy</span>;<br /><span class="keyword">The girl</span> is also very <span class="keyword">happy</span>;<br /><span class="comments">// Whether it is right now</span><br /><span class="comments">// Still in the distant future.</span><br />The boy has but one dream;<br /><span class="comments">// The boy wants the girl could well have been happy.</span><br />I want to say:<br />Baby, I love you forever;`;// ========== 主要副作用 ==========useEffect(() => {if (!canvasRef.current || !loveHeartRef.current || !contentRef.current) return;// 检查浏览器是否支持canvasif (!document.createElement('canvas').getContext) {if (errorMsgRef.current) {errorMsgRef.current.innerHTML ="您的浏览器不支持HTML5!<br/>推荐使用 Chrome 14+/IE 9+/Firefox 7+/Safari 4+";}if (codeRef.current) {codeRef.current.style.display = "none";}return;}// 初始化画布const gardenCanvas = canvasRef.current;gardenCanvas.width = loveHeartRef.current.offsetWidth;gardenCanvas.height = loveHeartRef.current.offsetHeight;// 获取2D上下文const ctx = gardenCanvas.getContext('2d');if (!ctx) return;// 设置混合模式ctx.globalCompositeOperation = "lighter";// 创建花园实例gardenRef.current = new Garden(ctx, gardenCanvas);// 调整布局adjustLayout();// 花园渲染循环const renderInterval = setInterval(() => {gardenRef.current?.render();}, Garden.options.growSpeed);animationRefs.current.intervals.push(renderInterval);// 启动代码打字效果typeWriterCodeContent();// 光标闪烁效果const cursorInterval = setInterval(() => {if (clearValRef.current) {setShowCursor(prev => !prev);} else {clearInterval(cursorInterval);setShowCursor(false);}}, 600);animationRefs.current.intervals.push(cursorInterval);// 5秒后开始心形动画const heartTimeout = setTimeout(() => {startHeartAnimation();}, 5000);animationRefs.current.timeouts.push(heartTimeout);// 初始化计时器timeElapse(startDate);const timeInterval = setInterval(() => timeElapse(startDate), 500);animationRefs.current.intervals.push(timeInterval);// 窗口大小变化监听const handleResize = () => adjustLayout();window.addEventListener('resize', handleResize);// 清理函数return () => {animationRefs.current.intervals.forEach(interval => clearInterval(interval));animationRefs.current.timeouts.forEach(timeout => clearTimeout(timeout));window.removeEventListener('resize', handleResize);};}, [startDate]);// 显示消息后的副作用useEffect(() => {if (showMessages) {adjustWordsPosition();const timer = setTimeout(() => setShowLoveU(true), 5000);animationRefs.current.timeouts.push(timer);return () => clearTimeout(timer);}}, [showMessages]);// 显示告白后的副作用useEffect(() => {if (showLoveU && loveURef.current) {const loveUContent = `${messages.love}<br/><div class='signature'>${messages.signature}</div>`;loveURef.current.innerHTML = '';typeWriter(loveURef.current, loveUContent, 75);}}, [showLoveU, messages]);// 同步clearVal状态到refuseEffect(() => {clearValRef.current = clearVal;}, [clearVal]);// ========== 工具函数 ==========/*** 代码打字效果*/const typeWriterCodeContent = () => {setShowCursor(true);let i = 0;const speed = 10; // 打字速度(毫秒/字符)const typing = setInterval(() => {if (i < fullCodeContent.length) {setCodeContent(fullCodeContent.substring(0, i + 1));i++;} else {clearInterval(typing);setClearVal(false); // 打字完成,停止光标闪烁}}, speed);animationRefs.current.intervals.push(typing);};/*** 计算心形曲线上的点* @param angle 角度(弧度)* @returns [x, y]坐标*/const getHeartPoint = (angle: number): [number, number] => {// 心形曲线参数方程const x = 19.5 * (16 * Math.pow(Math.sin(angle), 3));const y = -20 * (13 * Math.cos(angle) - 5 * Math.cos(2 * angle) - 2 * Math.cos(3 * angle) - Math.cos(4 * angle));// 计算相对于心形容器中心的坐标const offsetX = loveHeartRef.current?.offsetWidth ? loveHeartRef.current.offsetWidth / 2 : 0;const offsetY = loveHeartRef.current?.offsetHeight ? loveHeartRef.current.offsetHeight / 2 - 55 : 0;return [offsetX + x, offsetY + y];};/*** 开始心形动画*/const startHeartAnimation = () => {const interval = 50; // 花朵生成间隔(毫秒)const speed = 0.2;   // 角度变化速度let angle = 10;      // 起始角度const points: [number, number][] = []; // 已生成的点const animation = setInterval(() => {const point = getHeartPoint(angle);let valid = true;// 检查新点与已有点的距离for (const p of points) {const distance = Math.sqrt(Math.pow(p[0] - point[0], 2) + Math.pow(p[1] - point[1], 2));if (distance < Garden.options.bloomRadius.max * 1.3) {valid = false;break;}}// 如果点有效,创建花朵if (valid && gardenRef.current) {points.push(point);gardenRef.current.createRandomBloom(point[0], point[1]);}// 动画结束条件if (angle >= 30) {clearInterval(animation);setShowMessages(true); // 显示消息} else {angle += speed; // 继续动画}}, interval);animationRefs.current.intervals.push(animation);};/*** 通用打字机效果* @param element 目标DOM元素* @param text 要显示的文本* @param speed 打字速度(毫秒/字符)*/const typeWriter = (element: HTMLElement, text: string, speed: number) => {let i = 0;element.innerHTML = '';const typing = setInterval(() => {if (i < text.length) {const char = text.substr(i, 1);// 跳过HTML标签if (char === '<') {const closingIndex = text.indexOf('>', i);i = closingIndex === -1 ? text.length : closingIndex + 1;} else {i++;}// 更新内容并添加光标element.innerHTML = text.substring(0, i) + (i % 2 ? '_' : '');} else {clearInterval(typing);}}, speed);animationRefs.current.intervals.push(typing);};/*** 计算并显示恋爱时长* @param date 开始日期*/const timeElapse = (date: Date) => {if (!elapseClockRef.current) return;const now = new Date();const seconds = (now.getTime() - date.getTime()) / 1000;// 计算天数const days = Math.floor(seconds / (3600 * 24));let remaining = seconds % (3600 * 24);// 计算小时const hours = Math.floor(remaining / 3600);remaining %= 3600;// 计算分钟const minutes = Math.floor(remaining / 60);remaining %= 60;// 格式化显示(补零)const formattedHours = hours < 10 ? `0${hours}` : hours.toString();const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes.toString();const formattedSeconds = remaining < 10 ? `0${Math.floor(remaining)}` : Math.floor(remaining).toString();// 更新DOMelapseClockRef.current.innerHTML = `<span class="digit">${days}</span> 天 <span class="digit">${formattedHours}</span> 小时 <span class="digit">${formattedMinutes}</span> 分钟 <span class="digit">${formattedSeconds}</span> 秒`;};/*** 调整文字位置*/const adjustWordsPosition = () => {if (!wordsRef.current || !canvasRef.current) return;const garden = canvasRef.current;const words = wordsRef.current;words.style.position = 'absolute';words.style.top = `${garden.offsetTop + 195}px`;words.style.left = `${garden.offsetLeft + 70}px`;};/*** 调整代码区域位置*/const adjustCodePosition = () => {if (!codeRef.current || !canvasRef.current) return;const garden = canvasRef.current;const code = codeRef.current;code.style.marginTop = `${(garden.offsetHeight - code.offsetHeight) / 2}px`;};/*** 响应式布局调整*/const adjustLayout = () => {if (!contentRef.current || !loveHeartRef.current || !codeRef.current) return;const content = contentRef.current;const loveHeart = loveHeartRef.current;const code = codeRef.current;// 计算合适尺寸const width = loveHeart.offsetWidth + code.offsetWidth;const height = Math.max(loveHeart.offsetHeight, code.offsetHeight);// 设置容器尺寸(考虑窗口边界)content.style.width = `${Math.min(width, window.innerWidth - 40)}px`;content.style.height = `${Math.min(height, window.innerHeight - 40)}px`;// 居中显示content.style.marginTop = `${Math.max((window.innerHeight - content.offsetHeight) / 2, 10)}px`;content.style.marginLeft = `${Math.max((window.innerWidth - content.offsetWidth) / 2, 10)}px`;// 调整代码区域垂直居中adjustCodePosition();};/*** 渲染代码区域*/const renderCodeContent = () => {return (<div id="code" ref={codeRef}>{/* 使用dangerouslySetInnerHTML显示带HTML格式的代码 */}<div dangerouslySetInnerHTML={{ __html: codeContent }} />{/* 闪烁的光标(心形) */}{showCursor && (<span className="heart-cursor" style={{ color: 'red' }}></span>)}</div>);};// ========== 组件渲染 ==========return (<div className="btnbg lovePage">{/* 背景层 */}<div id="mainDiv">{/* 主内容容器 */}<div id="content" ref={contentRef}>{/* 左侧:代码区域 */}{renderCodeContent()}{/* 右侧:心形动画区域 */}<div id="loveHeart" ref={loveHeartRef}>{/* 花园画布 */}<canvas id="garden" ref={canvasRef}></canvas>{/* 情话文本区域(默认隐藏) */}<divid="words"ref={wordsRef}style={{display: showMessages ? 'block' : 'none',opacity: showMessages ? 1 : 0,transition: 'opacity 1s ease-in-out'}}>{/* 初始消息 */}<div id="messages" ref={messagesRef}>{messages.initial}{/* 恋爱计时器 */}<div id="elapseClock" ref={elapseClockRef}></div></div>{/* 最终告白(默认隐藏) */}<divid="loveu"ref={loveURef}style={{display: showLoveU ? 'block' : 'none',opacity: showLoveU ? 1 : 0,transition: 'opacity 1s ease-in-out'}}/></div></div></div></div>{/* 浏览器兼容性错误提示 */}<div id="errorMsg" ref={errorMsgRef}></div></div>);
};export default LoveAnimation;

GardenClasses.ts文件:

// GardenClasses.ts
export interface VectorProps {x: number;y: number;
}export interface PetalOptions {stretchA: number;stretchB: number;startAngle: number;angle: number;growFactor: number;bloom: Bloom;
}export interface BloomOptions {p: Vector;r: number;c: string;pc: number;garden: Garden;
}export interface GardenOptions {petalCount: { min: number; max: number };petalStretch: { min: number; max: number };growFactor: { min: number; max: number };bloomRadius: { min: number; max: number };density: number;growSpeed: number;color: {rmin: number;rmax: number;gmin: number;gmax: number;bmin: number;bmax: number;opacity: number;};tanAngle: number;
}export class Vector {x: number;y: number;constructor(x: number, y: number) {this.x = x;this.y = y;}rotate(angle: number): Vector {const x = this.x;const y = this.y;this.x = Math.cos(angle) * x - Math.sin(angle) * y;this.y = Math.sin(angle) * x + Math.cos(angle) * y;return this;}mult(factor: number): Vector {this.x *= factor;this.y *= factor;return this;}clone(): Vector {return new Vector(this.x, this.y);}length(): number {return Math.sqrt(this.x * this.x + this.y * this.y);}subtract(v: Vector): Vector {this.x -= v.x;this.y -= v.y;return this;}set(x: number, y: number): Vector {this.x = x;this.y = y;return this;}
}export class Petal {stretchA: number;stretchB: number;startAngle: number;angle: number;bloom: Bloom;growFactor: number;r: number;isfinished: boolean;constructor(options: PetalOptions) {this.stretchA = options.stretchA;this.stretchB = options.stretchB;this.startAngle = options.startAngle;this.angle = options.angle;this.bloom = options.bloom;this.growFactor = options.growFactor;this.r = 1;this.isfinished = false;}draw(): void {const ctx = this.bloom.garden.ctx;const e = new Vector(0, this.r).rotate(Garden.degrad(this.startAngle));const d = e.clone().rotate(Garden.degrad(this.angle));const c = e.clone().mult(this.stretchA);const b = d.clone().mult(this.stretchB);ctx.strokeStyle = this.bloom.c;ctx.beginPath();ctx.moveTo(e.x, e.y);ctx.bezierCurveTo(c.x, c.y, b.x, b.y, d.x, d.y);ctx.stroke();}render(): void {if (this.r <= this.bloom.r) {this.r += this.growFactor;this.draw();} else {this.isfinished = true;}}
}export class Bloom {p: Vector;r: number;c: string;pc: number;petals: Petal[];garden: Garden;constructor(options: BloomOptions) {this.p = options.p;this.r = options.r;this.c = options.c;this.pc = options.pc;this.petals = [];this.garden = options.garden;this.init();this.garden.addBloom(this);}draw(): void {let isFinished = true;this.garden.ctx.save();this.garden.ctx.translate(this.p.x, this.p.y);for (const petal of this.petals) {petal.render();isFinished = isFinished && petal.isfinished;}this.garden.ctx.restore();if (isFinished) {this.garden.removeBloom(this);}}init(): void {const angle = 360 / this.pc;const startAngle = Garden.randomInt(0, 90);for (let i = 0; i < this.pc; i++) {this.petals.push(new Petal({stretchA: Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max),stretchB: Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max),startAngle: startAngle + i * angle,angle: angle,growFactor: Garden.random(Garden.options.growFactor.min, Garden.options.growFactor.max),bloom: this,}));}}
}export class Garden {blooms: Bloom[];element: HTMLCanvasElement;ctx: CanvasRenderingContext2D;static options: GardenOptions = {petalCount: { min: 8, max: 15 },petalStretch: { min: 0.1, max: 3 },growFactor: { min: 0.1, max: 1 },bloomRadius: { min: 8, max: 10 },density: 10,growSpeed: 1000 / 60,color: {rmin: 128,rmax: 255,gmin: 0,gmax: 128,bmin: 0,bmax: 128,opacity: 0.1,},tanAngle: 60,};constructor(ctx: CanvasRenderingContext2D, element: HTMLCanvasElement) {this.blooms = [];this.element = element;this.ctx = ctx;}render(): void {for (const bloom of this.blooms) {bloom.draw();}}addBloom(bloom: Bloom): void {this.blooms.push(bloom);}removeBloom(bloom: Bloom): void {const index = this.blooms.indexOf(bloom);if (index !== -1) {this.blooms.splice(index, 1);}}createRandomBloom(x: number, y: number): void {this.createBloom(x,y,Garden.randomInt(Garden.options.bloomRadius.min, Garden.options.bloomRadius.max),Garden.randomrgba(Garden.options.color.rmin,Garden.options.color.rmax,Garden.options.color.gmin,Garden.options.color.gmax,Garden.options.color.bmin,Garden.options.color.bmax,Garden.options.color.opacity),Garden.randomInt(Garden.options.petalCount.min, Garden.options.petalCount.max));}createBloom(x: number, y: number, radius: number, color: string, petalCount: number): void {new Bloom({p: new Vector(x, y),r: radius,c: color,pc: petalCount,garden: this,});}clear(): void {this.blooms = [];this.ctx.clearRect(0, 0, this.element.width, this.element.height);}static random(min: number, max: number): number {return Math.random() * (max - min) + min;}static randomInt(min: number, max: number): number {return Math.floor(Math.random() * (max - min + 1)) + min;}static readonly circle = 2 * Math.PI;static degrad(angle: number): number {return (Garden.circle / 360) * angle;}static raddeg(angle: number): number {return (angle / Garden.circle) * 360;}static rgba(r: number, g: number, b: number, a: number): string {return `rgba(${r},${g},${b},${a})`;}static randomrgba(rmin: number,rmax: number,gmin: number,gmax: number,bmin: number,bmax: number,a: number): string {const r = Math.round(Garden.random(rmin, rmax));const g = Math.round(Garden.random(gmin, gmax));const b = Math.round(Garden.random(bmin, bmax));const threshold = 5;if (Math.abs(r - g) <= threshold &&Math.abs(g - b) <= threshold &&Math.abs(b - r) <= threshold) {return Garden.rgba(rmin, rmax, gmin, gmax, bmin, bmax, a);} else {return Garden.rgba(r, g, b, a);}}
}

Love.less

// 主色调(基于 #ffc0cb 扩展的渐变色系)
@color-1: #ffc0cb; // 粉红
@color-2: #ffb6c1; // 稍暗的粉
@color-3: #ffd1dc; // 浅粉
@color-4: #ffdfed; // 更浅的粉
@color-5: #ffecf2; // 接近白色
@font-face {font-family: digit;src: url('digital-7_mono.ttf') format("truetype");
}
// 动画定义
.keyframes() {@keyframes gentleFlow {0% {background-position: 0% 50%;}50% {background-position: 100% 50%;}100% {background-position: 0% 50%;}}
}// 主背景样式
.lovePage {min-height: 100vh;background: linear-gradient(45deg,@color-1,@color-2,@color-3,@color-4,@color-5,@color-1 );background-size: 300% 300%;animation: gentleFlow 12s ease infinite;position: relative;overflow: hidden;.keyframes();// 光斑效果(增强层次感)&::before {content: '';position: absolute;width: 200%;height: 200%;background:radial-gradient(circle at 70% 20%, rgba(255, 255, 255, 0.2) 0%, transparent 30%),radial-gradient(circle at 30% 80%, rgba(255, 255, 255, 0.15) 0%, transparent 30%);animation: gentleFlow 20s linear infinite reverse;}}canvas {padding: 0;margin: 0;
}div.btnbg {width: 100%;height: 100%;}#code,#messages,#loveu{color: #333;
}
#mainDiv {width: 100%;height: 100%
}#loveHeart {width: 670px;height: 625px
}#garden {width: 100%;height: 100%
}#elapseClock {text-align: right;font-size: 18px;margin-top: 10px;margin-bottom: 10px
}#words {font-family: "sans-serif";width: 500px;font-size: 24px;color: #666
}#elapseClock .digit {font-family: "digit";font-size: 36px
}#loveu {padding: 5px;font-size: 22px;margin-top: 40px;margin-right: 120px;text-align: right;display: none
}#loveu .signature {margin-top: 10px;font-size: 20px;font-style: italic
}#clickSound {display: none
}
#content{display: flex;justify-content: center;align-items: center;
}#code {width: 440px;height: 400px;color: #333;font-family: "Consolas","Monaco","Bitstream Vera Sans Mono","Courier New","sans-serif";font-size: 12px;margin: 0 !important;
}.string {color: #2a36ff
}.keyword {color: #7f0055;font-weight: bold
}.placeholder {margin-left: 15px
}.space {margin-left: 7px
}.comments {color: #3f7f5f
}#copyright {margin-top: 10px;text-align: center;width: 100%;color: #666
}#errorMsg {width: 100%;text-align: center;font-size: 24px;position: absolute;top: 100px;left: 0
}#copyright a {color: #666
}
.heart-cursor {animation: blink 1s infinite;font-size: 1em;vertical-align: middle;
}@keyframes blink {0%, 100% { opacity: 1; }50% { opacity: 0; }
}

在这里插入图片描述

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

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

相关文章

从零开始了解数据采集(二十一)——电子制造行业趋势分析案例

这次分享一个偏行业性的趋势分析案例,在项目中为企业实实在在的提高了良品率。不懂什么是趋势分析的同学,可以翻看前面的文章。 在广东某电子制造厂中,管理层发现最近几个月生产良品率有所波动,但无法明确波动原因,也无法预测未来的趋势。为了优化生产过程并稳定良品率,…

在 Git 中,撤销(回退)merge 操作有多种方法

在 Git 中&#xff0c;撤销&#xff08;回退&#xff09;merge 操作有多种方法&#xff0c;具体取决于是否已提交、是否已推送&#xff0c;以及是否需要保留历史记录。以下是几种常见的撤销 merge 的方法&#xff1a; 1. 未提交 merge&#xff08;未 commit&#xff09; 如果 …

基于 Python 的实现:居民用电量数据分析与可视化

基于 Python 的实现:居民用电量数据分析与可视化 本文将介绍如何利用 Python 技术栈(包括 pymysql、pandas、matplotlib 等库)对居民用电量数据进行分析和可视化,以帮助我们更好地理解用电行为模式。 数据准备 在MySQL数据库中创建数据,,数据库表结构如下: date:记录…

Flow原理

fun main() {runBlocking {launch {flow4.collect{println("---collect-4")}println("---flow4")}}val flow4 flow<Boolean>{delay(5000)emit(false) } 我们分析下整个流程 1.flow为什么之后在collect之后才会发送数据 2.collect的调用流程 我…

设备接入与APP(应用程序)接入华为云iotDA平台的路径元素有哪些不同?

目录 壹、设备接入华为云iotDA &#x1f3e2; 形象比喻&#xff1a;设备 员工&#xff0c;IoTDA 平台 安保森严的总部大楼 一、&#x1f4cd; 平台接入地址 总部大楼地址 二、&#x1f9fe; 接入凭证 出入证 / 门禁卡 / 工牌 1. 设备密钥或证书 2. 预置接入凭证密钥&a…

JavaScript基础知识合集笔记2——数组排序、数组转换字符串、迭代方法

文章目录 排序方法reverse()sort() 转换方法join() 迭代方法some()every()forEach()filter()map() 排序方法 组有两个方法可以用来对元素重新排序&#xff1a; reverse()sort() reverse() 顾名思义&#xff0c;将数组元素方向反转。会直接改变原数组&#xff0c;请谨慎使用…

Redis 笔记(三)-Redis 基本知识及五大数据类型

一、redis 基本知识 redis 默认有 16个 数据库&#xff0c;config get databases 查看数据库数量 127.0.0.1:6379> config get databases # 查看数据库数量 1) "databases" 2) "16"默认使用的是第 0个 16 个数据库为&#xff1a;DB 0 ~ DB 15&am…

springboot项目文件上传到服务器本机,返回访问地址

文件上传到服务器本机&#xff0c;然后给出访问地址&#xff1a; 具体如下&#xff1a; 1、添加必要的工具类依赖 <!-- 文件上传工具类 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId>…

巧用 Element - UI 实现图片上传按钮的智能隐藏

引言 在前端开发中&#xff0c;使用 Element - UI 组件库来构建用户界面是非常常见的操作。其中图片上传功能更是在许多项目中频繁出现&#xff0c;比如用户头像上传、商品图片上传等场景。有时候&#xff0c;我们会有这样的需求&#xff1a;当上传图片达到一定数量后&#xf…

Golang|工厂模式

工厂模式是一种创建型设计模式&#xff0c;它的核心思想是&#xff1a;把对象的创建过程封装起来&#xff0c;不直接在代码中 new 一个对象&#xff0c;而是通过一个“工厂”来生成对象。这样做的好处是&#xff1a; 降低了代码之间的耦合&#xff08;依赖具体类减少&#xff0…

CentOS 使用国内镜像安装 nvm 和 Node.js 完整指南

前言‌&#xff1a; 本文是实践过程中的个人总结&#xff0c;介绍在 CentOS 系统上通过国内镜像快速安装 nvm&#xff08;Node Version Manager&#xff09;&#xff0c;并配置镜像源加速 Node.js 的下载和依赖管理&#xff0c;解决因网络问题导致的安装失败或速度缓慢。 一、…

ComfyUI 学习笔记:安装篇及模型下载

背景 去年在掘金看到一个博主使用 ComfyUI 进行 AI 绘画&#xff0c;并基于此工具展开个人业务。知道了这个东西&#xff0c;感觉很厉害的样子。 前段时间玩 DeepSeek 的时候&#xff0c;尝试用它写《历史是一群喵》的漫画&#xff0c;给出了 AI 作画的提示词&#xff0c;但是…

人脑、深思考大模型与其他大模型的区别科普

文章目录 大模型的基本概念与特点深思考大模型的独特之处深思考大模型与其他大模型的对比架构与技术训练数据应用场景提示词编写 大模型给出答案的方式&#xff1a;基于概率还是真的会分析问题&#xff1f;人脑的思考过程基本单位与网络大脑结构与功能分区信息处理流程思维模式…

图像保边滤波之BEEPS滤波算法

目录 1 简介 2 算法原理 3 代码实现 4 演示Demo 4.1 开发环境 4.2 功能介绍 4.3 下载地址 参考 1 简介 BEEPS&#xff08;Bias Elimination in Edge-Preserving Smoothing&#xff09; 是一种基于偏微分方程&#xff08;PDE&#xff09;的边缘保留平滑滤波算法。它能够…

怎样给MP3音频重命名?是时候管理下电脑中的音频文件名了

在处理大量音频文件时&#xff0c;给这些文件起一个有意义的名字可以帮助我们更高效地管理和查找所需的内容。通过使用专业的文件重命名工具如简鹿文件批量重命名工具&#xff0c;可以极大地简化这一过程。本文将详细介绍如何利用该工具对 MP3 音频文件进行重命名。 步骤一&am…

uniapp实现统一添加后端请求Header方法

uniapp把请求写完了&#xff0c;发现需要给接口请求添加头部&#xff0c;每个接口去添加又很麻烦&#xff0c;uniapp可以统一添加&#xff0c;并且还能给某些接口设置不添加头部。 一般用于添加token登录验证信息。 在 main.js 文件中配置。 代码如下&#xff1a; // 在…

Qt/C++面试【速通笔记四】—Qt中的MVC模式

在软件开发中&#xff0c;设计模式是为了让代码结构更加清晰、可维护和扩展的工具。MVC&#xff08;Model-View-Controller&#xff0c;模型-视图-控制器&#xff09;模式就是其中一种经典的设计模式&#xff0c;它被广泛应用于图形界面&#xff08;GUI&#xff09;应用程序中。…

机器学习-入门-线性模型(2)

机器学习-入门-线性模型(2) 3.4广义线性回归 一般形式&#xff1a; y g − 1 ( w T x b ) y g^{-1} \left( w^T x b \right) yg−1(wTxb) 单调可微的联系函数 (link function) 令 g ( ⋅ ) ln ⁡ ( ⋅ ) g(\cdot) \ln (\cdot) g(⋅)ln(⋅) 则得到对数线性回归 ln ⁡…

Scratch——第20课 辗转相除法/绳子算法

辗转相除法是用于求取最大公约数时需要用到的方法&#xff0c;它还有个名字称为绳子算法&#xff0c;这类题目只要理解辗转相处的原理即可拿下。 一、辗转相除法的基本原理 两个整数的最大公约数不变&#xff0c;当较大数减去较小数后&#xff0c;得到的差值与较小数的最大公…

【Keil5-开发指南】

Keil5-编程指南 ■ Keil5 介绍■ Keil5 生成bin文件■ 新建工程后debug在 BX R0 不动了■ J-Flash 使用■ Keil5-Debug调试工具 Jlink---STLink---DAP仿真器■ Keil5 使用 AStyle插件格式化代码■ Keil5-编译4个阶段■ Keil5-Boot和APP配置■ Keil5-报错■ 芯片手册区别 ■ Kei…