threejs 渲染中国地图(相机參数适配) 学习笔记

threejs yekong

问题

渲染出的中国地图没有在坐标中心。

解决方案

使用包围盒获取地图的中心,调整相机的lookAt坐标
threejs 渲染中国地图(相机參数适配) 学习笔记

创建包围盒

// 地图mapGroup的包围盒计算
var box3 = new THREE.Box3();//创建一个包围盒
// .expandByObject()方法:计算层级模型group包围盒
box3.expandByObject(lineGroup);
// console.log('查看包围盒box3', box3);

//scaleV3表示包围盒长宽高尺寸
var scaleV3 = new THREE.Vector3();
// .getSize()计算包围盒长宽高尺寸
box3.getSize(scaleV3)
// 查看控制台包围盒大小,辅助设置相机参数
console.log('查看包围盒尺寸', scaleV3);

//scaleV3表示包围盒的几何体中心
var center = new THREE.Vector3();
// .getCenter()计算一个层级模型对应包围盒的几何体中心
box3.getCenter(center);
// 查看控制台包围盒集合中心,作为lookAt()参数
console.log('查看几何中心', center);

显示效果

显示效果

实例代码

<!--渲染中国地图-->
<template>
  <div class="homebody">
    <div class="canvasGLTFBody">
      <div ref='canvasGLTF' class="canvasGLTF">
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
// 引入Three.js扩展库
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { borderArr } from '@/utils/line.js'
import { shapeMesh } from '@/utils/shapeMesh.js'

export default {
  name: 'GLTFCanvas',
  data () {
    return {
      list: []
    }
  },
  created: function () {

  },
  mounted: function () {
    var that = this
    /**
     * 创建场景对象Scene
     */
    var scene = new THREE.Scene()
    //three.js文件加载类FileLoader:封装了XMLHttpRequest
    var loader = new THREE.FileLoader()
    loader.setResponseType('json')
    // 组对象mapGroup是所有国家边界Line模型的父对象
    var mapGroup = new THREE.Group()
    var lineGroup = new THREE.Group()
    var meshGroup = new THREE.Group()
    mapGroup.add(lineGroup)
    mapGroup.add(meshGroup)
    lineGroup.position.z += 0.1

    scene.add(mapGroup)
    // 异步加载包含世界各个国家边界坐标的GeoJSON文件:china.json
    loader.load('data/china.json', function (data) {
      // 访问所有国家边界坐标数据:data.features
      data.features.forEach(function (area) {
        // "Polygon":国家area有一个封闭轮廓
        //"MultiPolygon":国家area有多个封闭轮廓
        if (area.geometry.type === 'Polygon') {
          // 把"Polygon"和"MultiPolygon"的geometry.coordinates数据结构处理为一致
          area.geometry.coordinates = [area.geometry.coordinates]
        }
        // 解析所有封闭轮廓边界坐标area.geometry.coordinates
        lineGroup.add(borderArr(area.geometry.coordinates))//国家边界轮廓插入组对象mapGroup
        meshGroup.add(shapeMesh(area.geometry.coordinates))//国家轮廓Mesh插入组对象mapGroup
      })
      // 地图mapGroup的包围盒计算
      var box3 = new THREE.Box3()//创建一个包围盒
// .expandByObject()方法:计算层级模型group包围盒
      box3.expandByObject(mapGroup)
// console.log('查看包围盒box3', box3);

//scaleV3表示包围盒长宽高尺寸
      var scaleV3 = new THREE.Vector3()
// .getSize()计算包围盒长宽高尺寸
      box3.getSize(scaleV3)
// 查看控制台包围盒大小,辅助设置相机参数
      console.log('查看包围盒尺寸', scaleV3)

//scaleV3表示包围盒的几何体中心
      var center = new THREE.Vector3()
// .getCenter()计算一个层级模型对应包围盒的几何体中心
      box3.getCenter(center)
// 查看控制台包围盒集合中心,作为lookAt()参数
      console.log('查看几何中心', center)
    })

    //three.js辅助坐标系
    var axesHelper = new THREE.AxesHelper(300)
    scene.add(axesHelper)
    /**
     * 相机设置
     */
    var width = window.innerWidth //窗口宽度
    var height = window.innerHeight //窗口高度
    var k = width / height //窗口宽高比
    // var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
    var s = 30//缩小渲染渲染范围,地图尽量100%填充canvas画布
    //创建相机对象
    var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000)
    // camera.position.set(200, 300, 200); //设置相机位置
    camera.position.set(104.28225326538086, 35.83740043640137, 200) //沿着z轴观察
    camera.lookAt(0, 0, 0) //设置相机方向(指向的场景对象)
    /**
     * 创建渲染器对象
     */
    var renderer = new THREE.WebGLRenderer()
    renderer.setSize(width, height) //设置渲染区域尺寸
    // renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色

    // 渲染函数
    function render () {
      renderer.render(scene, camera) //执行渲染操作
      requestAnimationFrame(render) //请求再次执行渲染函数render,渲染下一帧
    }

    render()
    //创建控件对象  控件可以监听鼠标的变化,改变相机对象的属性
    // 旋转、缩放用于代码调试

    var controls = new OrbitControls(camera, renderer.domElement)
    // 相机控件与.lookAt()无效( .target属性 )
    controls.target.set(104, 35, 0)
    controls.update()
    that.$refs.canvasGLTF.appendChild(renderer.domElement)

  },
  methods: {}
}
</script>

<style lang="scss" scoped>
.homebody {
  width: 100%;
  height: 100%;
  position: fixed;
  background: #0f1633;
  //position: relative;

  .pageMain {
    position: relative;
    width: calc(100% - 60px - 60px);
    margin: 0 auto;
    height: calc(100% - 108px - 150px);
  }
}
</style>

WebGL/Three.js前端3D可视化

WebGL/Three.js前端3D可视化

喜欢