threejs导入简单地图模型

抄的b站一个大佬的
添加链接描述
vite建的项目vue3+ts
地图数据需要自己下载
https://overpass-turbo.eu/
浏览器需要调成英文模式不然下不下来(18年以前貌似没事)

<!-- 加载人物模型 -->
<template>
  <div ref="statsDivRef"></div>
  <div ref="threeRef"></div>
</template>

<script lang="ts">
import {
  reactive,
  toRefs,
  onBeforeMount,
  onMounted,
  defineComponent,
  ref,
  render,
} from "vue";
import {
  AmbientLight,
  AnimationMixer,
  AxesHelper,
  BoxGeometry,
  BufferAttribute,
  BufferGeometry,
  Camera,
  Clock,
  Color,
  DirectionalLight,
  DoubleSide,
  ExtrudeBufferGeometry,
  Fog,
  FogExp2,
  GridHelper,
  Group,
  HemisphereLight,
  Line,
  LineBasicMaterial,
  LinePieces,
  Mesh,
  MeshBasicMaterial,
  MeshLambertMaterial,
  MeshNormalMaterial,
  MeshPhongMaterial,
  PerspectiveCamera,
  PlaneBufferGeometry,
  PlaneGeometry,
  PointLight,
  PointLightShadow,
  Scene,
  Shape,
  SphereGeometry,
  SpotLight,
  SpotLightHelper,
  Vector3,
  WebGLRenderer,
} from "three";
import States from "stats.js";
import * as dat from "dat.gui";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { MapControls } from "three/examples/jsm/controls/OrbitControls.js";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
import { getDistance, getRhumbLineBearing } from "geolib";
interface DataProps {}
export default defineComponent({
  name: "ExampleB",
  setup() {
    let camera: any;
    let scene: any;
    let group: any;
    let controls: any;
    let light: any;
    let center = [-3.1846411, 55.9457427];
    let MAT_EUILDING: any;

    const threeRef = ref();
    const statsDivRef = ref<HTMLDivElement>();
    const statsRef = ref<States>();
    function initStats() {
      statsRef.value = new States();
      statsRef.value.showPanel(0);
      if (statsDivRef.value) {
        statsDivRef.value.appendChild(statsRef.value.dom);
      }
    }

    //生成一个group
    function groupObj() {
      group = new Group();
      scene.add(group);
    }

    function Awake() {
      threeRef;
      scene = new Scene();
      scene.background = new Color(0x222222);

      //init
      camera = new PerspectiveCamera(
        25,
        window.innerWidth / window.innerHeight,
        1,
        100
      );
      camera.position.set(8, 4, 0);

      //light
      light = new AmbientLight(0xfafafa, 0.25);

      let light1 = new PointLight(0xfafafa, 0, 4);
      light1.position.set(100, 90, 40);

      let light2 = new PointLight(0xfafafa, 0, 4);
      light2.position.set(200, 90, -40);

      scene.add(light);
      scene.add(light1);
      scene.add(light2);

      let gh = new GridHelper(
        60,
        160,
        new Color(0x555555),
        new Color(0x333333)
      );
      scene.add(gh);

      //renderer 渲染
      let renderer = new WebGLRenderer({ antialias: true });
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);

      //添加到画布上
      threeRef.value.appendChild(renderer.domElement);

      //控制器
      controls = new MapControls(camera, renderer.domElement);
      controls.enableDamping = true;
      controls.dampingFactor = 0.25;
      controls.screenSpacePanning = false;
      controls.maxDistance = 800;

      controls.update();

      Update();

      //全局材质
      MAT_EUILDING = new MeshNormalMaterial();
      GetGeoJson();

      function Update() {
        window.addEventListener("resize", onWindowResize, false);
        requestAnimationFrame(Update);
        renderer.render(scene, camera);
        controls.update();
      }

      //实时拖放窗口
      function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
      }

      //jsoN文件
      function GetGeoJson() {
        fetch("./assets/export.geojson").then((res) => {
          res.json().then((data) => {
            loadBuilding(data);
          });
        });
      }

      //加载建筑数据
      function loadBuilding(data: any) {
        let features = data.features;

        for (let i = 0; i < features.length; i++) {
          let fel = features[i];
          if (!fel["properties"]) return;

          if (fel.properties["building"]) {
            addBuilding(
              fel.geometry.coordinates,
              fel.properties,
              fel.properties["building:levels"]
            );
          }
        }
      }

      function addBuilding(data: any, info: any, height = 1) {
        for (let i = 0; i < data.length; i++) {
          let el = data[i];

          let shape = genShape(el, center);
          let geometry = genGeometry(shape, {
            curveSegments: 1,
            depth: 0.05 * height,
            bevelEnabled: false,
          });

          geometry.rotateX(Math.PI /2)
          geometry.rotateZ(Math.PI)

          let mesh = new Mesh(geometry, MAT_EUILDING);

          scene.add(mesh);
        }
      }

      function genShape(points: any, el: any) {
        let shape = new Shape();

        for (let index = 0; index < points.length; index++) {
          let elp = points[index];

          elp = GPSPosition(elp, center);

          if (index == 0) {
            shape.moveTo(elp[0], elp[1]);
          } else {
            shape.lineTo(elp[0], elp[1]);
          }
        }
        return shape;
      }

      /**
       * yarn add geolib
       * import { getDistance } from 'geolib';
       */
      function GPSPosition(objPosi: any, centerPosi: any) {
        let dis = getDistance(objPosi, centerPosi);

        let bearing = getRhumbLineBearing(objPosi, centerPosi);

        let x = centerPosi[0] + dis * Math.cos((bearing * Math.PI) / 180);

        let y = centerPosi[1] + dis * Math.sin((bearing * Math.PI) / 180);

        return [-x / 100, y / 100];
      }

      function genGeometry(shape: any, config: any) {
        let genGeometry = new ExtrudeBufferGeometry(shape, config);

        genGeometry.computeBoundingBox();

        return genGeometry;
      }
    }

    //更新

    onMounted(() => {
      Awake();
    });
    return {
      statsDivRef,
      threeRef,
    };
  },
});
</script>
<style scoped></style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值