ZhangXianQiang
2024-04-17 dda78e2eb4a04f55d01de2645b4a6abc821cc8f9
feat:绘制3d地图
8个文件已修改
2个文件已添加
2个文件已删除
213988 ■■■■■ 已修改文件
src/assets/map/texture/gz-map-fx.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/texture/gz-map.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/zigong.json 60219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/zigong1.json 73640 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/zigong2.json 79841 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/components/data-map.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map-three/experience/camera.js 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map-three/experience/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map-three/experience/renderer.js 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map-three/experience/world/enviroment.js 90 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map-three/experience/world/map.js 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/components/screen-map/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/texture/gz-map-fx.jpg
src/assets/map/texture/gz-map.jpg
src/assets/map/zigong.json
File was deleted
src/assets/map/zigong1.json
File was deleted
src/assets/map/zigong2.json
Diff too large
src/views/home/data-view/components/data-map.vue
@@ -8,7 +8,7 @@
<script>
import * as echarts from 'echarts';
import 'echarts-gl';
import mapData from '@/assets/map/zigong.json';
import mapData from '@/assets/map/zigong2.json';
echarts.registerMap('zigong', mapData);
console.log(mapData);
let mapChart = null;
src/views/screen/components/screen-map-three/experience/camera.js
@@ -15,16 +15,17 @@
    // 设置透视相机
    setInstance() {
        this.instance = new PerspectiveCamera(75,this.sizes.width / this.sizes.height, 0.1, 1000);
        this.instance.position.set(0, 2, 2);
        this.instance = new PerspectiveCamera(45,this.sizes.width / this.sizes.height, 0.001, 90000000);
        this.instance.position.set(0, 45, 45);
        this.scene.add(this.instance);
        const help = new CameraHelper(this.instance);
        this.scene.add(help);
        // const help = new CameraHelper(this.instance);
        // this.scene.add(help);
    }
    setOrbitControls() {
        this.controls = new OrbitControls(this.instance, this.canvas);
        this.controls.target.set(0, 0, 1);
        this.controls.target.set(0, 0, 5);
        this.controls.enableDamping = true;
    }
    resize() {
src/views/screen/components/screen-map-three/experience/index.js
@@ -1,5 +1,5 @@
import { Scene, GridHelper,AxesHelper } from 'three';
import Stats from "three/examples/jsm/libs/stats.module";
import World from "./world/world";
import Camera from "./camera";
@@ -19,11 +19,14 @@
    this.renderer = new Renderer(this);
    this.world = new World(this);
    const size = 10;
    const divisions = 10;
    // const size = 200;
    // const divisions = 200;
    const gridHelper = new GridHelper(size, divisions);
    this.scene.add(gridHelper);
    // const gridHelper = new GridHelper(size, divisions);
    // this.scene.add(gridHelper);
    this.stats = new Stats();
    document.querySelector('.map-container').appendChild(this.stats.dom);
    
@@ -37,5 +40,6 @@
    this.camera.update();
    this.world.update();
    this.renderer.update();
    this.stats.update();
  }
}
src/views/screen/components/screen-map-three/experience/renderer.js
@@ -13,12 +13,13 @@
        this.instance = new THREE.WebGLRenderer({
            canvas: this.canvas,
            antialias: true,
            alpha: true
            alpha: true,
            // logarithmicDepthBuffer: true
        });
        this.instance.toneMapping = THREE.CineonToneMapping;
        this.instance.toneMappingExposure = 1.75;
        this.instance.shadowMap.enabled = true;
        this.instance.shadowMap.type = THREE.PCFSoftShadowMap;
        // this.instance.toneMapping = THREE.CineonToneMapping;
        // this.instance.toneMappingExposure = 1.75;
        // this.instance.shadowMap.enabled = true;
        // this.instance.shadowMap.type = THREE.PCFSoftShadowMap;
        this.instance.setSize(this.sizes.width, this.sizes.height);
        this.instance.setPixelRatio(this.sizes.pixelRatio);
    }
src/views/screen/components/screen-map-three/experience/world/enviroment.js
@@ -7,46 +7,84 @@
  constructor(experience) {
    this.experience = experience;
    this.scene = this.experience.scene;
    // this.setSunLight();
    this.textureLoader = new THREE.TextureLoader();
    this.setSunLight();
    this.setRotateHola();
    this.setBackground();
    this.setCirclePoint();
  }
  setSunLight() {
    this.sunLight = new THREE.DirectionalLight('#ffffff', 4);
    this.sunLight.castShadow = true;
    this.sunLight.shadow.camera.far = 15;
    this.sunLight.shadow.mapSize.set(2048, 2048);
    this.sunLight.shadow.normalBias = 0.05;
    this.sunLight.position.set(-1.3, 7, 10);
    this.scene.add(this.sunLight);
    //   平行光1
    let directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.6);
    directionalLight1.position.set(400, 200, 200);
    //   平行光2
    let directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.6);
    directionalLight2.position.set(-400, -200, -300);
    // 环境光
    let ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    this.scene.add(directionalLight1);
    this.scene.add(directionalLight2);
    this.scene.add(ambientLight);
  }
  setBackground() {
    const texture = new THREE.TextureLoader();
    const rotatingApertureTexture = texture.load(rotatingAperture);
    const rotatingPointTexture = texture.load(rotatingPoint);
    const circlePointTexture = texture.load(circlePoint);
    const sceneBgTexture = texture.load(sceneBg);
    let meshConfig1 = {
      width: 100,
      height: 100,
  setRotateHola() {
    const rotatingApertureTexture = this.textureLoader.load(rotatingAperture);
    const rotatingPointTexture = this.textureLoader.load(rotatingPoint);
    const meshConfig1 = {
      width: 48,
      height: 48,
      texture: rotatingApertureTexture,
      positionList: [0, 0.13, 0.3],
      scaleList: [0.048, 0.048, 0.048],
      positionList: [0, 0.4, 0.3],
      scaleList: [1, 1, 1],
      rotateList: [-Math.PI / 2, 0, 0]
    };
    let meshConfig2 = {
      width: 100,
      height: 100,
    const meshConfig2 = {
      width: 40,
      height: 40,
      texture: rotatingPointTexture,
      positionList: [0, 0.1, 0.3],
      scaleList: [0.04, 0.04, 0.04],
      positionList: [0, 0.3, 0.3],
      scaleList: [1, 1, 1],
      rotateList: [-Math.PI / 2, 0, 0]
    };
    this.hola1 = this.createMesh(meshConfig1);
    this.hola2 = this.createMesh(meshConfig2);
    this.scene.add(this.hola1);
    this.scene.add(this.hola2);
  }
  setBackground() {
    const sceneBgTexture = this.textureLoader.load(sceneBg);
    const plane = new THREE.PlaneGeometry(120, 120);
    const material = new THREE.MeshPhongMaterial({
      // color: 0x061920,
      color: 0xffffff,
      map: sceneBgTexture,
      transparent: true,
      opacity: 1,
      // depthTest: true
    });
    this.background = new THREE.Mesh(plane, material);
    this.background.rotation.set(-Math.PI / 2, 0, 0);
    this.background.position.set(0, 0.1, 0);
    this.scene.add(this.background);
  }
  setCirclePoint() {
    const circleTexture = this.textureLoader.load(circlePoint);
    const plane = new THREE.PlaneGeometry(45, 45);
    const material = new THREE.MeshPhongMaterial({
      color: 0x00ffff,
      map: circleTexture,
      transparent: true,
      opacity: 1,
      depthTest: false,
    });
    this.circle = new THREE.Mesh(plane, material);
    this.circle.rotation.set(-Math.PI / 2, 0, 0);
    this.circle.position.set(0, 0.2, 0);
    this.scene.add(this.circle);
  }
  createMesh(config) {
@@ -56,7 +94,7 @@
      map: texture,
      transparent: true,
      opacity: 1,
      depthTest: true,
      depthTest: false,
    });
    let mesh = new THREE.Mesh(plane, material);
    mesh.position.set(...positionList);
src/views/screen/components/screen-map-three/experience/world/map.js
@@ -2,8 +2,8 @@
import * as d3 from 'd3';
import mapData from '@/assets/map/zigong2.json';
import textureMap from '@/assets/map/texture/map_texture.jpg';
import textureMapImage from '@/assets/map/texture/gz-map.jpg';
import textureMapFxImage from '@/assets/map/texture/gz-map-fx.jpg';
// 地图深度
const MAP_DEPTH = 0.2;
@@ -13,56 +13,86 @@
        this.experience = experience;
        this.scene = this.experience.scene;
        this.material = null;
        this.textureLoader = new THREE.TextureLoader();
        this.setTexture();
        this.operationData(mapData);
    }
    operationData(jsondata) {
        const loader = new THREE.TextureLoader();
        loader.load(textureMap,
            (texture) => {
                this.material = new THREE.MeshBasicMaterial({
                    map: texture
                });
                this.map = new THREE.Object3D();
                // geo信息
                const features = jsondata.features;
                features.forEach((feature) => {
                    // 单个省份 对象
                    const province = new THREE.Object3D();
                    // 地址
                    province.properties = feature.properties.name;
                    // 多个情况
                    if (feature.geometry.type === "GeometryCollection") {
                        feature.geometry.geometries.forEach((coordinate) => {
                            coordinate.coordinates.forEach((rows) => {
                                const line = this.drawBoundary(rows);
                                const mesh = this.drawExtrudeMesh(rows);
                                province.add(line);
                                province.add(mesh);
                            });
                        });
                    }
                    // 单个情况
                    if (feature.geometry.type === "Polygon") {
                        feature.geometry.coordinates.forEach((coordinate) => {
                            const line = this.drawBoundary(coordinate);
                            const mesh = this.drawExtrudeMesh(coordinate);
                            province.add(line);
                            province.add(mesh);
                        });
                    }
                    this.map.add(province);
                    this.map.position.set(0.001, 0, 0.1);
                    this.map.rotation.set(THREE.MathUtils.degToRad(-90), 0, THREE.MathUtils.degToRad(20));
                });
                this.container = new THREE.Object3D();
                this.container.add(this.map);
                this.scene.add(this.container);
                console.log(this.container);
            }
        )
    setTexture() {
        const textureMap = this.textureLoader.load(textureMapImage);
        const textureMapFx = this.textureLoader.load(textureMapFxImage);
        textureMap.wrapS = textureMapFx.wrapS = THREE.RepeatWrapping;
        textureMap.wrapT = textureMapFx.wrapT = THREE.RepeatWrapping;
        textureMap.flipY = textureMapFx.flipY = false;
        textureMap.rotation = textureMapFx.rotation = THREE.MathUtils.degToRad(45);
        const scale = 0.128;
        textureMap.repeat.set(scale, scale);
        textureMapFx.repeat.set(scale, scale);
        this.topFaceMaterial = new THREE.MeshPhongMaterial({
            map: textureMap,
            color: 0xb4eeea,
            combine: THREE.MultiplyOperation,
            transparent: true,
            opacity: 1,
        });
        this.sideMaterial = new THREE.MeshLambertMaterial({
            color: 0x123024,
            transparent: true,
            opacity: 0.9,
        });
    }
    /**
     * 解析json数据,并绘制地图多边形
     * @param {*} jsondata 地图数据
     */
    operationData(jsondata) {
        this.map = new THREE.Object3D();
        // geo信息
        const features = jsondata.features;
        features.forEach((feature) => {
            // 单个省份 对象
            const province = new THREE.Object3D();
            // 地址
            province.properties = feature.properties.name;
            // 多个情况
            // console.log(feature.geometry.type);
            if (feature.geometry.type === "MultiPolygon") {
                console.log(feature.geometry.coordinates);
                feature.geometry.coordinates.forEach((coordinate) => {
                    coordinate.forEach((rows) => {
                        const line = this.drawBoundary(rows);
                        const mesh = this.drawExtrudeMesh(rows);
                        province.add(line);
                        province.add(mesh);
                    });
                });
            }
            // 单个情况
            if (feature.geometry.type === "Polygon") {
                feature.geometry.coordinates.forEach((coordinate) => {
                    const line = this.drawBoundary(coordinate);
                    const mesh = this.drawExtrudeMesh(coordinate);
                    province.add(line);
                    province.add(mesh);
                });
            }
            this.map.add(province);
        });
        this.map.position.set(1, 1, 0.15);
        this.map.scale.set(10, 10, 10);
        this.map.rotation.set(THREE.MathUtils.degToRad(-90), 0, THREE.MathUtils.degToRad(20));
        this.container = new THREE.Object3D();
        this.container.add(this.map);
        this.scene.add(this.container);
    }
    /**
     * 画区域分界线
     * @param {*} polygon 区域坐标点数组
     * @returns 区域分界线
     */
    drawBoundary(polygon) {
        const points = [];
        for (let i = 0; i < polygon.length; i++) {
@@ -71,36 +101,38 @@
        }
        const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
        const lineMaterial = new THREE.LineBasicMaterial({
            color: 'yellow'
            color: 0xffffff,
            linewidth: 2,
            transparent: true,
            depthTest: false,
        });
        const line = new THREE.Line(lineGeometry, lineMaterial);
        line.translateZ(MAP_DEPTH);
        line.translateZ(MAP_DEPTH + 0.001);
        return line;
    }
    /**
     * 绘制区域多边形
     * @param {*} polygon 区域坐标点数组
     * @returns 区域多边形
     */
    drawExtrudeMesh(polygon) {
        const shape = new THREE.Shape();
        for (let i = 0; i < polygon.length; i++) {
            const [x, y] = projection(polygon[i]);
            if (i === 0) {
                shape.moveTo(x, -y);
            }
            shape.lineTo(x, -y);
        }
        const geometry = new THREE.ExtrudeGeometry(shape, {
            depth: MAP_DEPTH,
            bevelEnabled: false,
            bevelSegments: 1,
            bevelThickness: 0.1,
        });
        const material = new THREE.MeshBasicMaterial({
            color: '#525288',
            transparent: true,
            opacity: 1,
        })
        return new THREE.Mesh(geometry, this.material);
        return new THREE.Mesh(geometry, [
            this.topFaceMaterial,
            this.sideMaterial,
        ]);
    }
}
src/views/screen/components/screen-map/index.vue
@@ -12,7 +12,7 @@
<script>
import * as echarts from 'echarts';
import 'echarts-gl';
import mapData from '@/assets/map/zigong1.json';
import mapData from '@/assets/map/zigong2.json';
import WrapperTitle from '../wrapper-title/index';
import ScreenData from '../screen-data/index';