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

Three.js Echarts结合教程

Echarts结合 ·Combine Echarts· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • glTF/FBX/OBJ 外部模型加载
  • 相机交互控制器
  • CSS2D/3D 标签渲染
  • ECharts 与三维融合
  • requestAnimationFrame 渲染循环

效果说明

本案例演示Echarts结合效果:ECharts 图表与 Three.js 场景同屏联动展示;核心用到 OrbitControls、glTF/Draco、ECharts。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Loader异步加载模型;glTF 返回gltf.scene,加载后注意scale与坐标系。Draco 需配置DRACOLoader
  • OrbitControls轨道旋转缩放;开enableDamping时每帧需controls.update()
  • DOM 元素叠加在 3D 坐标上,适合信息面板(注意与 WebGL 深度关系)。
  • 二维图表/飞线与 Cesium/Three 场景叠加或纹理映射。

实现步骤

  • 搭建 Scene / Camera / Renderer 与 OrbitControls
  • Loader 异步加载模型/纹理资源
  • rAF 循环中 update 并 render
  • 代码要点

    import * as THREE from 'three'

    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' import * as echarts from 'echarts'

    const DOM = document.getElementById('box')

    const scene = new THREE.Scene()

    const camera = new THREE.PerspectiveCamera(75, DOM.clientWidth / DOM.clientHeight, 0.1, 10000)

    camera.position.set(50, 90, 300)

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })

    renderer.setSize(DOM.clientWidth, DOM.clientHeight)

    DOM.appendChild(renderer.domElement)

    scene.add(new THREE.AmbientLight(0xffffff, 3))

    new OrbitControls(camera, renderer.domElement)

    const css3DRender = setCss3DRenderer(DOM)

    new GLTFLoader().load(FILE_HOST + "files/model/Fox.glb", gltf => scene.add(gltf.scene))

    animate()

    function animate() {

    requestAnimationFrame(animate)

    renderer.render(scene, camera)

    css3DRender.render(scene, camera) }

    window.onresize = () => {

    renderer.setSize(box.clientWidth, box.clientHeight)

    camera.aspect = box.clientWidth / box.clientHeight

    camera.updateProjectionMatrix()

    css3DRender.resize()

    }

    /css3d 渲染/ function setCss3DRenderer(DOM) {

    const css3DRender = new CSS3DRenderer()

    css3DRender.resize = () => {

    css3DRender.setSize(DOM.clientWidth, DOM.clientHeight)

    css3DRender.domElement.style.zIndex = 0

    css3DRender.domElement.style.position = 'relative'

    css3DRender.domElement.style.top = -DOM.clientHeight + 'px'

    css3DRender.domElement.style.height = DOM.clientHeight + 'px'

    css3DRender.domElement.style.width = DOM.clientWidth + 'px'

    css3DRender.domElement.style.pointerEvents = 'none'

    }

    css3DRender.resize()

    DOM.appendChild(css3DRender.domElement)

    return css3DRender

    }

    /图表 ----------------------------------------------------------------------/

    const container = document.createElement("div") container.style.width = "300px" container.style.height = "200px" const myChart = echarts.init(container)

    myChart.setOption({ graphic: { elements: [ { type: 'text', left: 'center', top: 'center', style: { text: 'Echarts', fontSize: 80, fontWeight: 'bold', lineDash: [0, 200], lineDashOffset: 0, fill: 'transparent', stroke: '#fff', lineWidth: 1 }, keyframeAnimation: { duration: 3000, loop: true, keyframes: [ { percent: 0.7, style: { fill: 'transparent', lineDashOffset: 200, lineDash: [200, 0] } }, { // Stop for a while. percent: 0.8, style: { fill: 'transparent' } }, { percent: 1, style: { fill: 'black' } } ] } } ] } })

    const css3DObject = new CSS3DObject(container) css3DObject.position.set(0, 130, 0) scene.add(css3DObject)

    const container2 = document.createElement("div") container2.style.width = "300px" container2.style.height = "300px" const myChart2 = echarts.init(container2)

    myChart2.setOption({ xAxis: { type: 'category', boundaryGap: false, data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [ { data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line', areaStyle: {} } ] })

    const css3DObject2 = new CSS3DObject(container2) css3DObject2.position.set(0, -80, 0) scene.add(css3DObject2)

    完整源码:GitHub

    小结

    • 本文提供Echarts结合完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
http://www.jsqmd.com/news/1101998/

相关文章:

  • 【仅剩最后47份】OpenAI o3模型企业级适配Checklist(含GPU显存压缩方案、KV Cache剪枝阈值表、合规审计项)
  • 抖音批量下载工具终极指南:如何免费高效获取无水印内容
  • ChatGPT私有化部署致命误区:67%企业误用缓存机制导致PII明文暴露(附Log4j级漏洞复现报告)
  • ExtractorSharp:免费开源的游戏资源编辑器,让游戏MOD制作变得简单
  • MPC5643L/SPC56EL评估板硬件设计解析:电源、时钟与调试接口实战
  • 文件上传漏洞深度解析:从PowerCreatorCMS漏洞看Web安全防护
  • 【信息科学与工程学】机器人运动科学
  • AI Agent 开发 语言 与 架构 的选择 全面对比——Python、TypeScript 与Rust
  • WechatBakTool:3步轻松备份微信聊天记录的终极指南
  • 基于JMeter与AI的智能压测平台:从数据收集到自动化分析报告
  • PowerPC汽车MCU评估板ASD433A硬件设计与调试全解析
  • GDF-8 靶点前沿科研应用 肥胖代谢、衰老肌少症、肌肉纤维化研究方向
  • web第8次作业
  • ChatGPT企业版价格封顶机制揭秘:如何用SLA协议锁定3年不涨价,附OpenAI商务谈判成功案例(含邮件原文)
  • DownKyi终极指南:解锁B站视频下载与批量处理的完整解决方案
  • 小白程序员必看:收藏这份Agent开发进阶指南,抢占高薪风口!
  • UniExtract2:超越传统压缩工具的500+格式万能提取解决方案
  • 【小白也能轻松玩转龙虾】虾壳云一键部署优化定制包,省去 OpenClaw v2.7.9 环境调试(附最新安装包)
  • go work vendor导致golang 工具func (self *TestDbCodeSuite) Test005_QueryModel2UserJoin() {没有执行按扭
  • MIC1557+STM32F303RE实现纳秒级精确定时方案
  • 微信聊天记录永久保存:5步轻松掌握WeChatMsg完全指南
  • Awesome .NET Core:2.1 万 Star 的 .NET Core 资源导航
  • 终极免费iOS激活锁绕过方案:AppleRa1n完整使用指南
  • React Router路径遍历漏洞CVE-2025-31137:原理、影响与修复指南
  • 150、 PCIE Linux驱动探测与初始化:从一次诡异的枚举失败说起
  • Anthropic模型能力演进与可信AI发布机制解析
  • 【Cursor高效编程实战指南】:20年IDE专家亲授5大隐藏技巧,90%开发者从未用过!
  • DiT 技术详解:把扩散模型的 U-Net 换成 Transformer,真正改变了什么
  • Anthropic模型能力演进与访问控制机制解析
  • 曲直天涯路