ZhangXianQiang
2024-04-17 35ddaca1fe74191a9861f42b1d6d5f1ed93651a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import * as THREE from 'three';
import * as d3 from 'd3';
import mapData from '@/assets/map/zigong2.json';
 
import textureMapImage from '@/assets/map/texture/gz-map.jpg';
import textureMapFxImage from '@/assets/map/texture/gz-map-fx.jpg';
// 地图深度
const MAP_DEPTH = 0.2;
 
const projection = d3.geoMercator().center([104.779307, 29.33924]).translate([0, 0, 0]);
export default class Map {
    constructor(experience) {
        this.experience = experience;
        this.scene = this.experience.scene;
        this.material = null;
        this.textureLoader = new THREE.TextureLoader();
        this.setTexture();
        this.operationData(mapData);
    }
    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, -2);
        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++) {
            const [x, y] = projection(polygon[i]);
            points.push(new THREE.Vector3(x, -y, 0));
        }
        const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
        const lineMaterial = new THREE.LineBasicMaterial({
            color: 0xffffff,
            linewidth: 2,
            transparent: true,
            depthTest: false,
        });
        const line = new THREE.Line(lineGeometry, lineMaterial);
        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,
        });
        return new THREE.Mesh(geometry, [
            this.topFaceMaterial,
            this.sideMaterial,
        ]);
    }
}