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

Three.js + Cannon.js:打造沉浸式3D物理交互游戏场景(实战篇)

1. 从零搭建Three.js与Cannon.js开发环境第一次接触3D物理交互开发时我被各种配置搞得晕头转向。现在回想起来其实只需要掌握几个关键步骤就能快速搭建开发环境。这里我推荐使用Vite作为构建工具它比Webpack配置简单得多特别适合新手快速上手。首先创建一个干净的Vue项目React同理npm create vitelatest threejs-cannonjs-demo --template vue-ts cd threejs-cannonjs-demo npm install three types/three cannon-es安装完基础依赖后我们需要处理一个关键问题TypeScript类型定义。cannon-es的类型定义需要额外安装这里有个小坑我踩过 - 直接npm install types/cannon-es会报错正确的做法是npm install types/cannon接下来在main.ts中初始化基础场景。我习惯把Three.js的渲染器、相机等核心对象放在Vue的provide/inject中这样组件树中的任何地方都能访问到// main.ts import { createApp } from vue import App from ./App.vue import * as THREE from three const app createApp(App) // 初始化基础Three.js环境 const renderer new THREE.WebGLRenderer({ antialias: true }) renderer.setSize(window.innerWidth, window.innerHeight) const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) const scene new THREE.Scene() app.provide(three, { renderer, camera, scene }) document.body.appendChild(renderer.domElement) app.mount(#app)2. 物理世界与渲染世界的同步原理刚开始用Cannon.js时最让我困惑的是为什么要在两个地方创建物体 - 既要在Cannon.js的物理世界创建刚体又要在Three.js的场景中创建网格。后来才明白这是典型的ECS实体-组件-系统架构思想。物理引擎只负责计算物体的位置、旋转等物理状态而Three.js负责将这些状态可视化。两者通过每帧的同步实现联动。这里分享一个实用的同步模式const physicsBodies: CANNON.Body[] [] // 存储所有物理刚体 const visualMeshes: THREE.Mesh[] [] // 存储所有可视化网格 // 创建物理刚体 const sphereShape new CANNON.Sphere(0.5) const sphereBody new CANNON.Body({ mass: 1, shape: sphereShape, position: new CANNON.Vec3(0, 5, 0) }) world.addBody(sphereBody) physicsBodies.push(sphereBody) // 创建可视化网格 const sphereGeometry new THREE.SphereGeometry(0.5) const sphereMaterial new THREE.MeshBasicMaterial({ color: 0xff0000 }) const sphereMesh new THREE.Mesh(sphereGeometry, sphereMaterial) scene.add(sphereMesh) visualMeshes.push(sphereMesh) // 动画循环中同步状态 function animate() { requestAnimationFrame(animate) const delta clock.getDelta() world.step(delta) // 更新物理世界 // 同步所有物体状态 for(let i 0; i physicsBodies.length; i) { visualMeshes[i].position.copy(physicsBodies[i].position) visualMeshes[i].quaternion.copy(physicsBodies[i].quaternion) } renderer.render(scene, camera) }这种模式的优势在于物理计算与渲染解耦方便批量处理大量物体性能更好避免每帧都创建新对象3. 刚体碰撞的实战技巧在实现物体碰撞时新手常会遇到物体穿透或者反弹不自然的问题。经过多次实践我总结出几个关键参数需要特别注意质量(mass)的设置静态物体如地面mass设为0动态物体mass建议从1开始尝试过大的mass值会导致物体太重难以推动碰撞形状的选择// 常用碰撞形状及性能对比 const shapes { sphere: new CANNON.Sphere(0.5), // 性能最好 box: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)), cylinder: new CANNON.Cylinder(0.5, 0.5, 1, 8), // 边数越少性能越好 convex: new CANNON.ConvexPolyhedron(vertices, faces) // 最耗性能 }解决物体穿透的实用方案增加物理模拟的步频world.step(1/60, delta, 3) // 最大子步数设为3减小碰撞检测的间隔world.broadphase new CANNON.NaiveBroadphase()使用连续碰撞检测(CCD)sphereBody.collisionResponse true sphereBody.ccdSpeedThreshold 0.5 sphereBody.ccdIterations 5一个完整的碰撞场景示例// 创建倾斜平面 const planeShape new CANNON.Box(new CANNON.Vec3(5, 0.1, 5)) const planeBody new CANNON.Body({ type: CANNON.Body.STATIC, shape: planeShape, position: new CANNON.Vec3(0, 0, 0) }) planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -0.2) world.addBody(planeBody) // 创建多个随机球体 for(let i 0; i 10; i) { const radius 0.2 Math.random() * 0.3 const sphereShape new CANNON.Sphere(radius) const sphereBody new CANNON.Body({ mass: 0.3, shape: sphereShape, position: new CANNON.Vec3( Math.random() * 4 - 2, 5 Math.random() * 3, Math.random() * 4 - 2 ) }) world.addBody(sphereBody) physicsBodies.push(sphereBody) // 可视化部分... }4. 高级物理材质与交互效果要让3D场景的物理效果更真实必须掌握材质系统的使用。Cannon.js的材质系统可以模拟现实世界中的各种物理特性我通过实验总结了这些参数的实用范围摩擦系数(friction)0完全光滑如冰面0.3-0.6常见材质木制、金属0.8-1高摩擦橡胶、粗糙表面弹性系数(restitution)0完全无弹性0.5适中弹性篮球0.9-1超级弹性弹力球创建自定义材质并设置接触响应的完整流程// 1. 创建两种材质 const iceMaterial new CANNON.Material(ice) iceMaterial.friction 0.1 const rubberMaterial new CANNON.Material(rubber) rubberMaterial.friction 0.8 rubberMaterial.restitution 0.7 // 2. 定义材质间的交互规则 const iceRubberContact new CANNON.ContactMaterial( iceMaterial, rubberMaterial, { friction: 0.3, // 混合摩擦系数 restitution: 0.5 // 混合弹性系数 } ) world.addContactMaterial(iceRubberContact) // 3. 应用到刚体 const iceFloor new CANNON.Body({ shape: new CANNON.Plane(), material: iceMaterial, type: CANNON.Body.STATIC }) const rubberBall new CANNON.Body({ shape: new CANNON.Sphere(0.5), material: rubberMaterial, mass: 1, position: new CANNON.Vec3(0, 5, 0) })实现用户交互的实用技巧// 鼠标拾取物体 function setupMouseInteraction() { const raycaster new THREE.Raycaster() const mouse new THREE.Vector2() window.addEventListener(click, (event) { // 计算鼠标位置归一化坐标 mouse.x (event.clientX / window.innerWidth) * 2 - 1 mouse.y -(event.clientY / window.innerHeight) * 2 1 // 发射射线 raycaster.setFromCamera(mouse, camera) const intersects raycaster.intersectObjects(visualMeshes) if(intersects.length 0) { // 找到对应的物理刚体 const index visualMeshes.indexOf(intersects[0].object as THREE.Mesh) const body physicsBodies[index] // 施加冲击力 body.applyImpulse( new CANNON.Vec3(0, 5, 0), new CANNON.Vec3(0, 0, 0) ) } }) }5. 性能优化实战经验当场景中的物体超过100个时性能问题就会突显。经过多个项目的磨练我总结出这些优化方案特别有效1. 碰撞检测优化// 使用更高效的Broadphase算法 world.broadphase new CANNON.SAPBroadphase(world) // 设置碰撞检测的边界 world.broadphase.useBoundingBoxes true world.broadphase.dirty true2. 渲染优化技巧对静态物体使用相同的材质对大量相似物体使用InstancedMesh合理设置相机的far/near参数3. 物理模拟优化// 调整求解器迭代次数 world.solver.iterations 7 // 默认10越小性能越好但精度越低 // 启用睡眠模式 world.allowSleep true // 使用固定时间步长 let lastTime 0 function animate(time) { const delta Math.min((time - lastTime) / 1000, 0.1) // 最大delta限制 world.step(1/60, delta, 3) lastTime time // ...渲染逻辑 }4. 对象池模式对于需要频繁创建销毁的物体使用对象池可以大幅提升性能class PhysicsObjectPool { private freeList: CANNON.Body[] [] createBody(options: BodyOptions): CANNON.Body { if(this.freeList.length 0) { const body this.freeList.pop() // 重置body状态 body.position.copy(options.position) body.velocity.set(0, 0, 0) return body } // 新建刚体 return new CANNON.Body(options) } releaseBody(body: CANNON.Body) { world.removeBody(body) this.freeList.push(body) } }6. 复杂交互场景构建结合Three.js的动画系统和Cannon.js的物理引擎可以创造出令人惊艳的交互效果。这里分享一个多米诺骨牌效应的实现方案// 创建多米诺骨牌 const dominoShape new CANNON.Box(new CANNON.Vec3(0.1, 0.5, 1)) const dominoMaterial new CANNON.Material(domino) for(let i 0; i 20; i) { const domino new CANNON.Body({ mass: 0.5, shape: dominoShape, position: new CANNON.Vec3(i * 0.6, 0.5, 0), material: dominoMaterial }) domino.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), Math.PI/2) world.addBody(domino) // 可视化部分... } // 创建触发球 const ball new CANNON.Body({ mass: 2, shape: new CANNON.Sphere(0.3), position: new CANNON.Vec3(-2, 2, 0) }) world.addBody(ball) // 添加初始力 setTimeout(() { ball.applyImpulse(new CANNON.Vec3(5, 0, 0), new CANNON.Vec3(0, 0, 0)) }, 1000)实现绳索/约束的进阶技巧// 创建两个固定点 const fixedBody new CANNON.Body({ mass: 0 }) const startPoint new CANNON.Vec3(-3, 5, 0) const endPoint new CANNON.Vec3(3, 5, 0) // 创建多个连接的刚体 const segmentCount 10 const segments: CANNON.Body[] [] for(let i 0; i segmentCount; i) { const segment new CANNON.Body({ mass: 0.1, shape: new CANNON.Sphere(0.1), position: new CANNON.Vec3( startPoint.x (endPoint.x - startPoint.x) * i / (segmentCount - 1), startPoint.y, startPoint.z ) }) world.addBody(segment) segments.push(segment) // 添加约束 if(i 0) { const constraint new CANNON.DistanceConstraint( segments[i-1], segment, 0.5 // 最大距离 ) world.addConstraint(constraint) } } // 固定两端 world.addConstraint(new CANNON.PointToPointConstraint( fixedBody, new CANNON.Vec3(startPoint.x, startPoint.y, startPoint.z), segments[0], new CANNON.Vec3(0, 0, 0) )) world.addConstraint(new CANNON.PointToPointConstraint( fixedBody, new CANNON.Vec3(endPoint.x, endPoint.y, endPoint.z), segments[segmentCount-1], new CANNON.Vec3(0, 0, 0) ))7. 调试与问题排查指南开发物理交互场景时调试往往比编码更耗时。这些工具和方法帮我节省了大量时间1. 物理调试渲染器import { CannonDebugRenderer } from cannon-es-debugger const cannonDebugRenderer new CannonDebugRenderer(scene, world) function animate() { // ...其他逻辑 cannonDebugRenderer.update() // 每帧更新调试渲染 }2. 性能监测面板import Stats from stats.js const stats new Stats() stats.showPanel(0) // 0: fps, 1: ms, 2: mb document.body.appendChild(stats.dom) function animate() { stats.begin() // ...主逻辑 stats.end() }3. 常见问题排查表问题现象可能原因解决方案物体穿透时间步长太大减小world.step()的delta值物体抖动质量差异过大调整mass值使相近性能骤降复杂碰撞形状改用简单碰撞形状或减少面数反弹不正常弹性系数过高降低restitution值物体不移动mass设为0动态物体mass需大于04. 实用调试代码片段// 实时修改物理参数 gui.add(world.gravity, y, -20, 0).name(重力大小) gui.add(world.solver, iterations, 1, 20).name(求解器迭代) // 打印物体状态 console.log(body.position, body.velocity) // 暂停物理模拟 let physicsPaused false window.addEventListener(keydown, (e) { if(e.key ) physicsPaused !physicsPaused })8. 项目架构与最佳实践经过多个3D物理项目的迭代我总结出这套可维护的项目架构src/ ├── assets/ # 静态资源 ├── components/ # 通用3D组件 │ ├── PhysicsObject.vue # 物理对象基类 │ ├── Domino.vue # 具体物体实现 │ └── Ball.vue ├── composables/ # 逻辑复用 │ ├── usePhysics.ts # 物理引擎封装 │ └── useRenderer.ts # 渲染逻辑 ├── scenes/ # 场景管理 │ ├── MainScene.ts # 主场景 │ └── GameScene.ts └── utils/ # 工具函数 ├── physicsUtils.ts # 物理辅助 └── threeUtils.ts # Three.js辅助关键实现代码示例使用Composition API// usePhysics.ts export default function usePhysics() { const world new CANNON.World() world.gravity.set(0, -9.82, 0) // 添加默认接触材质 const defaultMaterial new CANNON.Material(default) const defaultContact new CANNON.ContactMaterial( defaultMaterial, defaultMaterial, { friction: 0.3, restitution: 0.3 } ) world.addContactMaterial(defaultContact) // 物理更新循环 const updatePhysics (delta: number) { world.step(delta) } return { world, updatePhysics } } // PhysicsObject.vue export default defineComponent({ props: { position: { type: Object as PropTypeTHREE.Vector3, default: () new THREE.Vector3() } }, setup(props) { const { world } inject(physics)! const { scene } inject(three)! const body new CANNON.Body({ mass: 1, shape: new CANNON.Sphere(0.5), position: new CANNON.Vec3(...props.position.toArray()) }) const mesh new THREE.Mesh( new THREE.SphereGeometry(0.5), new THREE.MeshBasicMaterial({ color: 0xff0000 }) ) onMounted(() { world.addBody(body) scene.add(mesh) }) onUnmounted(() { world.removeBody(body) scene.remove(mesh) }) return { body, mesh } } })在大型项目中这种架构的优势非常明显物理逻辑与渲染逻辑分离组件化开发复用性高类型安全维护方便场景切换时资源自动清理

相关文章:

Three.js + Cannon.js:打造沉浸式3D物理交互游戏场景(实战篇)

1. 从零搭建Three.js与Cannon.js开发环境 第一次接触3D物理交互开发时,我被各种配置搞得晕头转向。现在回想起来,其实只需要掌握几个关键步骤就能快速搭建开发环境。这里我推荐使用Vite作为构建工具,它比Webpack配置简单得多,特别…...

从仿真到实验:如何用Sentaurus TCAD校准你的MOSFET IV曲线(以77K/300K为例)

从仿真到实验:Sentaurus TCAD MOSFET IV曲线校准实战指南(77K/300K双温区对比) 当仿真曲线与实验数据出现明显偏差时,资深工程师往往需要像侦探一样抽丝剥茧。本文将以300K室温与77K低温环境为对照场景,揭示如何通过参…...

Cesium实战:5分钟搞定3D地球可视化(附完整代码)

Cesium实战:5分钟构建高交互3D地球可视化方案 当我们需要在网页中展示全球气象数据、物流轨迹或城市规划时,传统2D地图往往难以满足空间表达需求。Cesium作为当前最强大的开源WebGL地球引擎,能以不到10行核心代码实现从卫星视角到街道级别的3…...

从XMind到禅道:打造自动化测试用例导入流水线

1. 为什么需要从XMind到禅道的自动化转换 作为一名测试工程师,我深刻理解手动创建测试用例的痛苦。每次产品迭代,我们都需要在禅道中一条条添加测试用例,光是复制粘贴就能耗掉大半天时间。而使用XMind编写测试用例就高效多了 - 通过思维导图的…...

Linux CFS 的 block_avg:阻塞任务的平均等待时间

一、简介在Linux内核的CFS(Completely Fair Scheduler)调度器中,任务的状态转换和等待时间统计是理解系统性能瓶颈的关键。block_avg作为调度实体(sched_entity)统计信息中的核心指标,记录了任务因I/O操作、…...

从零到一:51单片机驱动数码管时钟的软硬件全解析

1. 项目背景与需求分析 第一次接触51单片机的朋友可能会觉得数码管时钟是个"高大上"的项目,其实它的核心逻辑比你想象的简单得多。这个项目的本质就是让单片机按照人类的时间规则来计数,并通过数码管这个"电子显示屏"把数字展示出来…...

FFmpeg 版本选择全解析:从协议到架构,新手到专家的避坑指南

1. FFmpeg版本选择的底层逻辑 第一次接触FFmpeg官网下载页面的开发者,大概率会被各种版本后缀搞得晕头转向。gpl、lgpl、shared、static、master、n6.1...这些看似简单的字母组合,实际上代表着完全不同的技术路线和法律责任。我见过不少项目因为选错版本…...

Linux CFS 的 sleep_avg:睡眠任务的平均等待时间

一、前言:为什么关注睡眠任务的统计在Linux内核的进程调度子系统中,CFS(Completely Fair Scheduler)自2.6.23版本引入以来,一直是桌面和服务器系统的核心调度器。与早期的O(1)调度器依赖复杂的启发式算法(如…...

AVPro Video插件避坑指南:解决拖动进度条杂音与NaN问题

AVPro Video插件实战:彻底解决进度条杂音与NaN显示问题 第一次在Unity项目里集成AVPro Video插件时,那个突如其来的"刺啦"杂音差点让我摔了耳机——每次拖动进度条都像用指甲刮黑板。更诡异的是Slider突然变成的"NaN"提示&#xff0…...

RT-Thread中SPI设备初始化与操作函数关联的常见陷阱

1. SPI设备初始化流程中的关键步骤 在RT-Thread操作系统中使用SPI设备时,正确的初始化流程是避免后续问题的关键。很多开发者容易忽略操作函数关联这个环节,导致运行时出现各种奇怪的错误。下面我结合自己踩过的坑,详细说说标准初始化流程应该…...

荣耀/华为耳机弹窗原理大揭秘:RCSP协议如何实现开盖即连(附多设备切换教程)

荣耀/华为耳机弹窗原理与RCSP协议深度解析 当你打开荣耀或华为耳机的充电盒盖,手机屏幕瞬间弹出精美的连接界面,实时显示耳机与充电盒电量——这种行云流水般的交互体验背后,是荣耀/华为自主研发的RCSP协议在发挥作用。作为生态互联的核心技术…...

STM32G474外部中断避坑指南:从CubeMX配置到中断服务函数编写,新手常犯的5个错误

STM32G474外部中断避坑指南:从CubeMX配置到中断服务函数编写 第一次接触STM32G474的外部中断功能时,很多开发者都会遇到各种奇怪的问题——中断不触发、响应异常甚至系统卡死。这些问题往往源于几个容易被忽视的细节配置。本文将深入剖析新手最容易踩的5…...

【实战指南】从编码器脉冲到轮速计算:嵌入式测速全流程解析

1. 编码器测速的核心原理 第一次接触编码器测速时,我被那一堆专业术语搞得头晕眼花。后来才发现,这东西本质上就是个会"打喷嚏"的旋转装置——每转一定角度就打一个电脉冲"喷嚏"。AB相编码器就像两个配合默契的喷嚏者,A…...

生成式AI应用安全上线前最后一步:SITS2026强制合规检查清单(含GDPR/等保2.0/内容审核三重校验模板)

第一章:生成式AI应用安全上线前最后一步:SITS2026强制合规检查清单(含GDPR/等保2.0/内容审核三重校验模板) 2026奇点智能技术大会(https://ml-summit.org) SITS2026(Secure Integration & Trustworthiness Standa…...

SeuratWrappers完整指南:3步掌握单细胞分析扩展工具集

SeuratWrappers完整指南:3步掌握单细胞分析扩展工具集 【免费下载链接】seurat-wrappers Community-provided extensions to Seurat 项目地址: https://gitcode.com/gh_mirrors/se/seurat-wrappers SeuratWrappers 是单细胞RNA测序分析领域的革命性扩展包&am…...

别再只用扫码枪了!用LabVIEW+OpenCV打造你的条形码/二维码混合识别系统

工业级视觉识别系统实战:用LabVIEWOpenCV替代传统扫码枪 在自动化产线和智能仓储场景中,扫码设备如同神经末梢般重要。但传统扫码枪的局限性日益凸显——固定安装方式难以适应柔性生产需求,高精度型号动辄上万元的采购成本让中小企业望而却步…...

华硕笔记本性能调控终极方案:G-Helper轻量级工具完全指南

华硕笔记本性能调控终极方案:G-Helper轻量级工具完全指南 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix,…...

AutoSubs:基于本地AI转录引擎的DaVinci Resolve字幕自动化解决方案

AutoSubs:基于本地AI转录引擎的DaVinci Resolve字幕自动化解决方案 【免费下载链接】auto-subs Instantly generate AI-powered subtitles on your device. Works standalone or connects to DaVinci Resolve. 项目地址: https://gitcode.com/gh_mirrors/au/auto-…...

Verilog 超声波测距:从时序控制到距离计算的模块化设计

1. 超声波测距原理与Verilog实现思路 超声波测距听起来很高科技,其实原理特别简单。想象一下你在山谷里大喊一声,然后听回声——超声波测距就是这个原理的电子版。模块发射超声波,遇到障碍物反射回来,我们只要计算声波往返时间&am…...

用AI起飞,组织为何躺平?CSDN收藏必备:解锁AI转型的正确姿势!

本文揭示了当前许多公司在应用AI技术时,虽然个人效率显著提升,但整体组织效能并未得到同步改善的现象。文章通过历史类比,指出AI转型需重构组织形态,而非简单叠加技术。AI如同铁路时代的变革,要求企业建立统一协作框架…...

收藏!程序员必看:AI冲击下,如何不被大厂裁员和低薪offer淘汰?

文章指出当前IT市场因大厂降本增效、AI编程工具发展、供过于求及业务增长放缓等因素,导致程序员求职难度加大、薪资增长空间缩小。文章强调AI并未完全取代程序员,而是提高了对程序员的能力要求,如业务理解、架构能力等。建议程序员积极拥抱AI…...

从SolidWorks到Matlab:机械臂STL模型导入与plot3D可视化全流程解析

1. 从SolidWorks导出机械臂STL文件的正确姿势 搞机械臂仿真的朋友应该都遇到过这样的场景:在SolidWorks里精心设计的模型,导出STL后导入Matlab就各种错位、缺失。我当年做五自由度机械臂项目时,光是模型导入就折腾了整整三天。下面这些血泪经…...

从DTU数据集到MVSNet:点云重建精度与完整度的量化评估实战

1. 从零开始理解DTU数据集与MVSNet 第一次接触三维重建时,我被各种专业术语搞得晕头转向。直到亲手用DTU数据集跑通了MVSNet,才真正理解点云重建的奥妙。DTU数据集就像三维世界的"标尺",而MVSNet则是帮你画图的"智能画笔"…...

Zotero 6.0用户必看:如何绕过插件兼容性检查安装最新工具

Zotero 6.0插件兼容性破解指南:解锁新版工具的全套方案 当你发现心仪的Zotero插件因为版本限制无法安装时,那种感觉就像找到一本绝版书却被图书馆管理员拦在门外。作为文献管理工具的中坚力量,Zotero 6.0用户常常面临这样的困境——新插件要求…...

优化Windows开发环境:迁移Yarn全局目录释放C盘空间

1. 为什么你的C盘总是不够用? 作为一个长期在Windows下搞开发的老鸟,我太懂那种看着C盘空间一点点被蚕食的痛苦了。特别是用了Yarn之后,你会发现不知不觉中C盘就红了。这其实是因为Yarn默认把所有全局安装的包、缓存文件都塞进了你的用户目录…...

老鼠监测站 鼠害监测系统

设备搭载高效太阳能供电模块,采用单晶硅太阳能电池板,可将太阳能转化为电能,一部分直接供给设备正常运行,另一部分存储至内置大容量锂电池中,实现“白天储能、夜间/阴雨天供电”的自主循环,全程无需接入市电…...

河流水位雨量监测系统 雨量水位监测站

自动监测系统凭借超强抗干扰能力、精准监测性能、便捷安装与操作优势,广泛应用于各类河道监测场景,为防汛抗旱、水资源管理、水环境治理等工作提供可靠支撑,具体应用场景如下:河道水位日常监测:部署于各类天然河道、人…...

六要素自动气象站 自动气象站六要素

六要素自动气象站设备搭载低功耗采集器,静态功耗小于1mA,大幅降低电能消耗,搭配太阳能充电管理系统,可实现长期稳定运行,无需频繁更换电源或充电。即使在光照不足的阴雨天,也能凭借低功耗特性延长续航时间&…...

[Python] 实战解析百度慧眼API:构建城市人口热力数据自动化采集与可视化系统

1. 百度慧眼API与城市人口热力数据简介 百度慧眼是百度地图面向政企用户推出的城市大数据分析平台,其中人口热力图功能能够直观展示城市中的人群分布密度。作为一名长期从事城市数据分析的研究者,我经常需要获取这类数据来分析商业区人流规律、交通枢纽拥…...

tao-8k部署教程(Linux/macOS双平台):Xinference源码安装与模型注册

tao-8k部署教程(Linux/macOS双平台):Xinference源码安装与模型注册 1. 引言:为什么选择tao-8k? 如果你正在寻找一个能处理超长文本的嵌入模型,tao-8k绝对值得你花时间了解一下。这个由Hugging Face开发者…...