当前位置: 首页 > news >正文

第七章 Cesium 3D 粒子烟花效果案例解析:从原理到完整代码

效果图

本文详细介绍如何使用 Cesium.js 创建逼真的 3D 粒子烟花效果,包括核心原理、实现步骤和完整代码,并解决开发过程中常见的 "只读对象修改" 错误。

效果展示与技术原理

我们将在 Cesium 地球表面创建一组动态烟花效果,每个烟花由数百个粒子组成,具有随机的位置、颜色和爆炸范围,最终形成绚丽的 3D 视觉效果。

核心技术原理:

  • 利用 Cesium 的粒子系统 (ParticleSystem) 创建和管理粒子
  • 通过坐标系转换实现粒子在 3D 空间中的精确定位
  • 运用向量运算控制粒子运动轨迹
  • 使用生命周期管理实现粒子的产生、运动和消失

开发准备

环境依赖

  • Cesium.js 1.95(粒子系统 API 稳定版本)
  • 现代浏览器(支持 WebGL)

基础配置

<!-- 引入Cesium核心库 -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script>
<!-- 引入Cesium样式表 -->
<link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet">

实现步骤详解

1. 初始化 Cesium 场景

首先创建基础的 3D 地球场景,并配置卫星影像图层:

// 创建Cesium Viewer实例
const viewer = new Cesium.Viewer("cesiumContainer", {shouldAnimate: true,  // 启用自动动画,确保粒子系统实时更新baseLayerPicker: false // 关闭图层选择器
});// 清除默认图层,添加ArcGIS卫星影像
viewer.imageryLayers.removeAll();
viewer.imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'})
);// 获取场景对象
const scene = viewer.scene;
// 显示帧率信息(调试用)
scene.debugShowFramesPerSecond = true;

2. 配置核心参数

将所有可调整的参数集中管理,便于后续维护和扩展:

const CONFIG = {// 粒子发射的经纬度位置(美国费城附近)emissionCoord: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),// 发射器初始高度(地面以上100米)initialHeight: 100.0,// 粒子在屏幕上的大小particleSize: new Cesium.Cartesian2(7.0, 7.0),// 每次粒子爆发的数量burstCount: 400,// 单个粒子系统的生命周期systemLifetime: 10.0,// 总烟花数量totalFireworks: 20,// 烟花爆炸范围explosionRange: { min: 30.0, max: 100.0 },// 烟花位置的随机偏移范围offsetRange: { x: [-100, 100], y: [-80, 100], z: [-50, 50] },// 烟花颜色方案colorSchemes: [{ minRed: 0.75, green: 0.0, minBlue: 0.8, alpha: 1.0 }, // 粉紫色系{ red: 0.0, minGreen: 0.75, minBlue: 0.8, alpha: 1.0 },  // 青绿色系{ red: 0.0, green: 0.0, minBlue: 0.8, alpha: 1.0 },      // 蓝色系{ minRed: 0.75, minGreen: 0.75, blue: 0.0, alpha: 1.0 }  // 黄色系]
};

3. 创建粒子纹理

定义粒子的外观,使用 canvas 创建白色圆形作为粒子基础纹理:

// 粒子纹理缓存
let particleTexture;/*** 创建粒子纹理(白色圆形)* @returns {HTMLCanvasElement} 粒子纹理画布*/
const getParticleTexture = () => {// 如果纹理已创建,直接返回缓存的纹理if (Cesium.defined(particleTexture)) return particleTexture;// 创建20x20的画布const canvas = document.createElement("canvas");canvas.width = canvas.height = 20;const ctx = canvas.getContext("2d");// 绘制白色圆形ctx.arc(8, 8, 8, 0, Cesium.Math.TWO_PI, true);ctx.fillStyle = "#fff";ctx.fill();// 缓存纹理并返回particleTexture = canvas;return canvas;
};

4. 实现粒子系统核心逻辑

创建单个烟花的核心函数,控制粒子的产生、运动和消失:

/*** 创建单个烟花粒子系统* @param {Cesium.Cartesian3} offset - 烟花相对于初始位置的偏移量* @param {Cesium.Color} color - 烟花的颜色* @param {Cesium.ParticleBurst[]} bursts - 粒子爆发的时间配置*/
const createFirework = (offset, color, bursts) => {// 计算烟花的实际位置 = 初始位置 + 偏移量const fireworkPos = Cesium.Cartesian3.add(initialPos, offset, new Cesium.Cartesian3());// 创建发射器矩阵:将发射器定位到计算出的烟花位置const emitterMatrix = Cesium.Matrix4.fromTranslation(fireworkPos);// 计算坐标系转换矩阵const localToWorld = Cesium.Matrix4.multiply(emissionMatrix, emitterMatrix, new Cesium.Matrix4());const worldToLocal = Cesium.Matrix4.inverseTransformation(localToWorld, localToWorld);// 随机生成当前烟花的爆炸范围const explosionSize = Cesium.Math.randomBetween(CONFIG.explosionRange.min,CONFIG.explosionRange.max);/*** 粒子受力回调函数* 控制粒子运动,超出爆炸范围时停止*/const particleForce = (particle) => {const localPos = Cesium.Matrix4.multiplyByPoint(worldToLocal, particle.position, new Cesium.Cartesian3());// 超出爆炸范围时停止粒子运动if (Cesium.Cartesian3.magnitudeSquared(localPos) >= explosionSize **2) {// 关键修复:创建新的Cartesian3实例而非使用Cesium.Cartesian3.ZERO// 原因:Cesium.Cartesian3.ZERO是只读对象,直接赋值会导致错误particle.velocity = new Cesium.Cartesian3(0, 0, 0);}};// 计算粒子生命周期(与爆炸范围相关)const normalizedSize = (explosionSize - CONFIG.explosionRange.min) / (CONFIG.explosionRange.max - CONFIG.explosionRange.min);const particleLife = 0.3 + normalizedSize * 0.7;// 创建并添加粒子系统scene.primitives.add(new Cesium.ParticleSystem({image: getParticleTexture(),       // 粒子纹理startColor: color,                 // 初始颜色endColor: color.withAlpha(0.0),    // 结束颜色(透明,实现淡出)particleLife: particleLife,        // 粒子生命周期speed: 100.0,                      // 初始速度imageSize: CONFIG.particleSize,    // 粒子大小emissionRate: 0,                   // 不持续发射(仅通过burst)emitter: new Cesium.SphereEmitter(0.1),  // 发射器形状bursts: bursts,                    // 爆发配置lifetime: CONFIG.systemLifetime,   // 粒子系统生命周期updateCallback: particleForce,     // 粒子运动回调modelMatrix: emissionMatrix,       // 基础坐标系矩阵emitterModelMatrix: emitterMatrix  // 发射器位置矩阵}));
};

5. 批量创建烟花效果

循环创建多个烟花,实现多样化的视觉效果:

/*** 批量创建所有烟花*/
const createAllFireworks = () => {for (let i = 0; i < CONFIG.totalFireworks; i++) {// 生成随机位置偏移const offset = new Cesium.Cartesian3(Cesium.Math.randomBetween(...CONFIG.offsetRange.x),Cesium.Math.randomBetween(...CONFIG.offsetRange.y),Cesium.Math.randomBetween(...CONFIG.offsetRange.z));// 选择烟花颜色(循环使用颜色方案)const colorScheme = CONFIG.colorSchemes[i % CONFIG.colorSchemes.length];const color = Cesium.Color.fromRandom({minimumRed: colorScheme.minRed,red: colorScheme.red,minimumGreen: colorScheme.minGreen,green: colorScheme.green,minimumBlue: colorScheme.minBlue,blue: colorScheme.blue,alpha: colorScheme.alpha});// 配置粒子爆发(3次随机爆发)const bursts = Array.from({ length: 3 }, () => new Cesium.ParticleBurst({time: Cesium.Math.nextRandomNumber() * CONFIG.systemLifetime,minimum: CONFIG.burstCount,maximum: CONFIG.burstCount}));// 创建单个烟花createFirework(offset, color, bursts);}
};

6. 配置相机视角

调整相机位置和朝向,确保烟花效果在最佳视角展示:

/*** 配置相机视角,聚焦烟花区域*/
const setupCamera = () => {const camera = scene.camera;// 相机相对于发射器的偏移位置const cameraOffset = new Cesium.Cartesian3(-300.0, 0.0, 0.0);// 相机定位camera.lookAtTransform(emissionMatrix, cameraOffset);camera.lookAtTransform(Cesium.Matrix4.IDENTITY);// 计算相机看向烟花的方向向量// 关键修复:使用新实例存储结果,避免修改只读对象const lookDir = Cesium.Cartesian3.subtract(initialPos, cameraOffset, new Cesium.Cartesian3());// 归一化方向向量// 关键修复:使用新实例存储归一化结果const normalizedDir = Cesium.Cartesian3.normalize(lookDir, new Cesium.Cartesian3());// 计算并设置相机仰角const pitchAngle = Cesium.Math.PI_OVER_TWO - Math.acos(Cesium.Cartesian3.dot(normalizedDir, Cesium.Cartesian3.UNIT_Z));camera.lookUp(pitchAngle);
};

7. 初始化执行

// 批量创建所有烟花
createAllFireworks();
// 配置相机视角
setupCamera();

常见错误及解决方案

在开发过程中,最容易遇到的是 "Cannot assign to read only property 'x' of object" 错误,这是由于 Cesium 中的一些静态对象(如Cesium.Cartesian3.ZERO)是只读的。

错误原因:直接修改 Cesium 的只读对象

// 错误示例
particle.velocity = Cesium.Cartesian3.ZERO;

解决方案:创建新的对象实例

// 正确示例
particle.velocity = new Cesium.Cartesian3(0, 0, 0);

同样,在处理向量运算时,也要注意不要直接修改原对象:

// 错误示例 - 可能修改原对象
Cesium.Cartesian3.normalize(lookDir, lookDir);// 正确示例 - 使用新实例存储结果
const normalizedDir = Cesium.Cartesian3.normalize(lookDir, new Cesium.Cartesian3());

完整代码

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Cesium粒子火花效果 - 修复版</title><!-- 引入Cesium核心库:提供3D地球和粒子系统支持 --><script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script><!-- 引入Cesium样式表:确保控件正常显示 --><link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><style>* {margin: 0;padding: 0;box-sizing: border-box;}/* 确保场景占满整个屏幕 */body,#cesiumContainer {width: 100vw;height: 100vh;overflow: hidden;}</style>
</head><body><!-- Cesium场景容器:所有3D内容将渲染到这里 --><div id="cesiumContainer"></div><script>/******************************************************************************* 1. 初始化Cesium核心环境* 作用:创建3D视图,配置地图图层,为粒子效果提供基础渲染环境******************************************************************************/// 创建Cesium Viewer实例(核心控制器)// shouldAnimate: true → 启用自动动画,确保粒子系统能实时更新// baseLayerPicker: false → 关闭图层选择器(我们将手动配置地图)const viewer = new Cesium.Viewer("cesiumContainer", {shouldAnimate: true,baseLayerPicker: false});// 清除默认图层(Cesium默认带的地图图层)viewer.imageryLayers.removeAll();// 添加ArcGIS卫星影像图层(高清卫星地图)viewer.imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'}));// 获取场景对象(所有渲染和粒子系统的基础)const scene = viewer.scene;// 显示帧率信息(左下角,用于调试性能)scene.debugShowFramesPerSecond = true;/******************************************************************************* 2. 全局配置与工具函数* 作用:集中管理所有常量参数和复用性工具函数******************************************************************************/// 配置常量:所有可调整的参数集中在这里,便于维护const CONFIG = {// 粒子发射的经纬度位置(美国费城附近)emissionCoord: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),// 发射器初始高度(地面以上100米)initialHeight: 100.0,// 粒子在屏幕上的大小(宽7像素,高7像素)particleSize: new Cesium.Cartesian2(7.0, 7.0),// 每次粒子爆发的数量burstCount: 400,// 单个粒子系统的生命周期(10秒后自动消失)systemLifetime: 10.0,// 总烟花数量totalFireworks: 20,// 烟花爆炸范围的最小值和最大值(单位:米)explosionRange: { min: 30.0, max: 100.0 },// 烟花位置的随机偏移范围(单位:米)offsetRange: { x: [-100, 100], y: [-80, 100], z: [-50, 50] },// 烟花颜色方案(4种色系循环使用)colorSchemes: [{ minRed: 0.75, green: 0.0, minBlue: 0.8, alpha: 1.0 }, // 粉紫色系{ red: 0.0, minGreen: 0.75, minBlue: 0.8, alpha: 1.0 },  // 青绿色系{ red: 0.0, green: 0.0, minBlue: 0.8, alpha: 1.0 },      // 蓝色系{ minRed: 0.75, minGreen: 0.75, blue: 0.0, alpha: 1.0 }  // 黄色系]};// 发射坐标系矩阵:将东-北-上坐标系(局部坐标系)转换到世界坐标系// 基于CONFIG.emissionCoord指定的经纬度创建const emissionMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(CONFIG.emissionCoord);// 发射器初始位置(在局部坐标系中的位置:x=0, y=0, z=100米)const initialPos = new Cesium.Cartesian3(0.0, 0.0, CONFIG.initialHeight);// 设置随机数种子:确保每次运行的随机效果一致,便于调试Cesium.Math.setRandomNumberSeed(315);// 粒子纹理缓存:避免重复创建canvas元素,提升性能let particleTexture;/*** 创建粒子纹理(白色圆形)* 作用:定义粒子的外观,返回一个20x20的白色圆形画布* @returns {HTMLCanvasElement} 粒子纹理画布*/const getParticleTexture = () => {// 如果纹理已创建,直接返回缓存的纹理if (Cesium.defined(particleTexture)) return particleTexture;// 创建20x20的画布const canvas = document.createElement("canvas");canvas.width = canvas.height = 20;const ctx = canvas.getContext("2d");// 绘制白色圆形(粒子形状)ctx.arc(8, 8, 8, 0, Cesium.Math.TWO_PI, true); // 圆心(8,8),半径8ctx.fillStyle = "#fff"; // 白色填充ctx.fill();// 缓存纹理并返回particleTexture = canvas;return canvas;};/******************************************************************************* 3. 粒子系统核心逻辑(创建单个烟花)* 作用:根据位置偏移、颜色和爆发配置,创建一个完整的烟花粒子效果* @param {Cesium.Cartesian3} offset - 烟花相对于初始位置的偏移量* @param {Cesium.Color} color - 烟花的颜色* @param {Cesium.ParticleBurst[]} bursts - 粒子爆发的时间配置******************************************************************************/const createFirework = (offset, color, bursts) => {// 计算烟花的实际位置 = 初始位置 + 偏移量const fireworkPos = Cesium.Cartesian3.add(initialPos, offset, new Cesium.Cartesian3());// 创建发射器矩阵:将发射器定位到计算出的烟花位置const emitterMatrix = Cesium.Matrix4.fromTranslation(fireworkPos);// 计算坐标系转换矩阵:// localToWorld → 将粒子的局部坐标转换为世界坐标// worldToLocal → 将世界坐标转换为粒子的局部坐标(用于计算粒子受力)const localToWorld = Cesium.Matrix4.multiply(emissionMatrix, emitterMatrix, new Cesium.Matrix4());const worldToLocal = Cesium.Matrix4.inverseTransformation(localToWorld, localToWorld);// 随机生成当前烟花的爆炸范围(在配置的最小值和最大值之间)const explosionSize = Cesium.Math.randomBetween(CONFIG.explosionRange.min,CONFIG.explosionRange.max);/*** 粒子受力回调函数* 作用:控制粒子的运动,当粒子超出爆炸范围时停止运动* @param {Cesium.Particle} particle - 单个粒子对象*/const particleForce = (particle) => {// 将粒子的世界位置转换为局部位置(相对于发射器)const localPos = Cesium.Matrix4.multiplyByPoint(worldToLocal, particle.position, new Cesium.Cartesian3());// 判断粒子是否超出爆炸范围(使用平方距离比较,避免开方运算,提升性能)if (Cesium.Cartesian3.magnitudeSquared(localPos) >= explosionSize ** 2) {// 【关键修复】:创建新的Cartesian3实例,而非使用Cesium.Cartesian3.ZERO// 原因:Cesium.Cartesian3.ZERO是只读对象,直接赋值会导致"Cannot assign to read only property"错误particle.velocity = new Cesium.Cartesian3(0, 0, 0);}};// 计算粒子的生命周期:爆炸范围越大,粒子生命周期越长(0.3~1.0秒)// 归一化爆炸范围(将范围值转换为0~1之间的比例)const normalizedSize = (explosionSize - CONFIG.explosionRange.min) / (CONFIG.explosionRange.max - CONFIG.explosionRange.min);const particleLife = 0.3 + normalizedSize * 0.7;// 创建粒子系统并添加到场景scene.primitives.add(new Cesium.ParticleSystem({image: getParticleTexture(),       // 粒子纹理(白色圆形)startColor: color,                 // 粒子初始颜色endColor: color.withAlpha(0.0),    // 粒子结束颜色(透明,实现淡出效果)particleLife: particleLife,        // 单个粒子的生命周期(秒)speed: 100.0,                      // 粒子初始速度(米/秒)imageSize: CONFIG.particleSize,    // 粒子在屏幕上的大小emissionRate: 0,                   // 不持续发射粒子(仅通过burst爆发)emitter: new Cesium.SphereEmitter(0.1),  // 发射器形状(半径0.1米的球体)bursts: bursts,                    // 粒子爆发的时间和数量配置lifetime: CONFIG.systemLifetime,   // 整个粒子系统的生命周期(秒)updateCallback: particleForce,     // 粒子运动的更新回调(控制受力)modelMatrix: emissionMatrix,       // 基础坐标系矩阵emitterModelMatrix: emitterMatrix  // 发射器的位置矩阵}));};/******************************************************************************* 4. 批量创建烟花* 作用:循环创建指定数量的烟花,每个烟花有随机位置、颜色和爆发时间******************************************************************************/const createAllFireworks = () => {// 循环创建CONFIG.totalFireworks个烟花for (let i = 0; i < CONFIG.totalFireworks; i++) {// 1. 生成随机位置偏移(在配置的范围内)const offset = new Cesium.Cartesian3(Cesium.Math.randomBetween(...CONFIG.offsetRange.x),  // x轴偏移Cesium.Math.randomBetween(...CONFIG.offsetRange.y),  // y轴偏移Cesium.Math.randomBetween(...CONFIG.offsetRange.z)   // z轴偏移);// 2. 选择烟花颜色(循环使用配置的颜色方案)const colorScheme = CONFIG.colorSchemes[i % CONFIG.colorSchemes.length];const color = Cesium.Color.fromRandom({minimumRed: colorScheme.minRed,red: colorScheme.red,minimumGreen: colorScheme.minGreen,green: colorScheme.green,minimumBlue: colorScheme.minBlue,blue: colorScheme.blue,alpha: colorScheme.alpha});// 3. 配置粒子爆发(每个烟花爆发3次,时间在生命周期内随机)const bursts = Array.from({ length: 3 }, () =>new Cesium.ParticleBurst({time: Cesium.Math.nextRandomNumber() * CONFIG.systemLifetime, // 随机爆发时间minimum: CONFIG.burstCount,  // 每次爆发的最小粒子数maximum: CONFIG.burstCount   // 每次爆发的最大粒子数(固定值)}));// 4. 创建单个烟花createFirework(offset, color, bursts);}};/******************************************************************************* 5. 相机视角配置* 作用:调整相机位置和朝向,确保烟花效果在视野中居中显示******************************************************************************/const setupCamera = () => {const camera = scene.camera;// 相机相对于发射器的偏移位置(在烟花区域前方300米)const cameraOffset = new Cesium.Cartesian3(-1000.0, 0.0, 0.0);// 相机定位:基于发射坐标系的偏移位置camera.lookAtTransform(emissionMatrix, cameraOffset);// 重置相机坐标系(切换回世界坐标系)camera.lookAtTransform(Cesium.Matrix4.IDENTITY);// 计算相机看向烟花的方向向量// 【关键修复】:使用new Cesium.Cartesian3()创建新实例存储结果// 原因:避免修改原对象,防止只读对象错误const lookDir = Cesium.Cartesian3.subtract(initialPos, cameraOffset, new Cesium.Cartesian3());// 归一化方向向量(将向量长度转换为1)// 【关键修复】:使用新实例存储归一化结果,不修改原向量const normalizedDir = Cesium.Cartesian3.normalize(lookDir, new Cesium.Cartesian3());// 计算相机仰角:让相机朝上看向烟花区域const pitchAngle = Cesium.Math.PI_OVER_TWO - Math.acos(Cesium.Cartesian3.dot(normalizedDir, Cesium.Cartesian3.UNIT_Z));camera.lookUp(pitchAngle);};/******************************************************************************* 6. 初始化执行* 作用:启动整个粒子效果流程******************************************************************************/createAllFireworks();  // 批量创建所有烟花setupCamera();         // 配置相机视角,聚焦烟花区域</script>
</body></html>

扩展与优化建议

  1. 交互扩展:添加鼠标点击事件,允许用户在地球表面任意位置触发烟花效果
  2. 性能优化
    • 限制同时存在的粒子数量
    • 根据设备性能动态调整粒子数量和大小
  3. 效果增强
    • 添加粒子尾迹效果
    • 实现烟花上升阶段动画
    • 增加声音效果同步
  4. 参数控制:添加 UI 控件,允许用户实时调整粒子大小、颜色、爆炸范围等参数

通过本文介绍的方法,可以在 Cesium 中创建出各种炫酷的粒子效果,不仅限于烟花,还可以实现火焰、烟雾、喷泉等多种视觉效果。


文章转载自:

http://uYeUjNim.pqppj.cn
http://CfdAVK00.pqppj.cn
http://pkh8nhE7.pqppj.cn
http://oKYoKz2k.pqppj.cn
http://OAgDK7of.pqppj.cn
http://gQl39stz.pqppj.cn
http://22KXMyIq.pqppj.cn
http://L9oXqoLf.pqppj.cn
http://MvCMRFGr.pqppj.cn
http://cVyPO5RN.pqppj.cn
http://mqcU4SyG.pqppj.cn
http://6kuL0ASQ.pqppj.cn
http://ufeznY0K.pqppj.cn
http://o4i3K9Am.pqppj.cn
http://tCBvkLih.pqppj.cn
http://338DCTCv.pqppj.cn
http://kFhoeJBc.pqppj.cn
http://l4M3NDPZ.pqppj.cn
http://LThid5ct.pqppj.cn
http://4FzmifHh.pqppj.cn
http://AKaATa3q.pqppj.cn
http://ynxpRXaq.pqppj.cn
http://xcBAAaTd.pqppj.cn
http://2GZPgD7m.pqppj.cn
http://me42MOhY.pqppj.cn
http://yGcKxkBu.pqppj.cn
http://s6d8fTZn.pqppj.cn
http://hBflFPaB.pqppj.cn
http://hyZQ2OSe.pqppj.cn
http://93tkeLjd.pqppj.cn
http://www.dtcms.com/a/369579.html

相关文章:

  • 【110】基于51单片机金属探测器【Proteus仿真+Keil程序+报告+原理图】
  • (双指针)LeetCode 209 长度最小的子数组+3 无重复字符的最长子串
  • 技术面:Java并发(线程池、ForkJoinPool)
  • 2026秋招Leetcode刷题记录
  • 探讨Xsens在人形机器人研发中的四个核心应用
  • [特殊字符] 香蕉超市|Nano Bananary|ZHO|已开源
  • 一种基于注解与AOP的Spring Boot接口限流防刷方案
  • 新启航开启深孔测量新纪元:激光频率梳技术攻克光学遮挡,达 130mm 深度 2μm 精度
  • ZyperWin++一个超好用的工具
  • 共用体与枚举:C++高效内存技巧
  • Semi-Supervised 3-D Medical
  • 解决网络太慢问题
  • IP5326_BZ 支持C同口输入输出的移动电源芯片 2.4A的充放电电流 支持4LED指示灯
  • 如何通过 Gitee API 上传文件到指定仓库
  • 商密保护密码:非公知性鉴定的攻防之道
  • 从零到上线:Docker、Docker Compose 与 Runtime 安装部署全指南(含实战示例与应用场景)
  • 2025 年 8 个最佳网站内容管理系统(CMS)
  • Java中的包
  • 彻底搞懂深度学习:强化学习和智能体(动图讲解)
  • 基于STM32单片机FM调频TEA5767功放收音机液晶显示设计
  • 邪修实战系列(1)
  • 今日行情明日机会——20250905
  • MCP(Model Context Protocol)与大模型一起运用
  • 【Lin通信】AUTOSAR架构下TC3xx芯片Lin报文收发详解
  • SDRAM详细分析—06 存储单元架构和放大器
  • stm32——NVIC,EXIT
  • Leetcode每日一练--20
  • 关机之前未正确关闭代理,导致DNS出现问题无法上网的解决方法(windows和linux)
  • Linux查看设备树信息
  • *MOS 半导体功率器件简介 | 结构 / 制程 / 简史