import * as THREE from "three"; import * as d3 from "d3"; import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer"; import { Line2 } from "three/examples/jsm/lines/Line2"; import { LineGeometry } from "three/examples/jsm/lines/LineGeometry"; import { LineMaterial } from "three/examples/jsm/lines/LineMaterial"; // import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'; // import { ProjectionFnParamType } from "./index.vue"; import { mapConfig } from "./mapConfig"; // 绘制挤出的材质 export function drawExtrudeMesh( point, projectionFn ) { const shape = new THREE.Shape(); const pointsArray = []; for (let i = 0; i < point.length; i++) { const [x, y] = projectionFn(point[i]); // 将每一个经纬度转化为坐标点 if (i === 0) { shape.moveTo(x, -y); } shape.lineTo(x, -y); pointsArray.push(x, -y, mapConfig.topLineZIndex); } const geometry = new THREE.ExtrudeGeometry(shape, { depth: mapConfig.mapDepth, // 挤出的形状深度 bevelEnabled: false, // 对挤出的形状应用是否斜角 }); const material = new THREE.MeshPhongMaterial({ // color: mapConfig.mapColor, color: mapConfig.mapColorGradient[Math.floor(Math.random() * 4)], // 随机颜色 // transparent: mapConfig.mapTransparent, // opacity: mapConfig.mapOpacity, }); const materialSide = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color(mapConfig.mapSideColor1), }, color2: { value: new THREE.Color(mapConfig.mapSideColor2), }, }, vertexShader: ` varying vec3 vPosition; void main() { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec3 vPosition; void main() { vec3 mixColor = mix(color1, color2, 0.5 - vPosition.z * 0.2); // 使用顶点坐标 z 分量来控制混合 gl_FragColor = vec4(mixColor, 1.0); } `, // wireframe: true, }); const mesh = new THREE.Mesh(geometry, [material, materialSide]); // userData 存储自定义属性 mesh.userData = { isChangeColor: true, }; // 边框线,赋值空间点坐标,3个一组 const lineGeometry = new LineGeometry(); lineGeometry.setPositions(pointsArray); const lineMaterial = new LineMaterial({ color: mapConfig.topLineColor, linewidth: mapConfig.topLineWidth, }); lineMaterial.resolution.set(window.innerWidth, window.innerHeight); const line = new Line2(lineGeometry, lineMaterial); return { mesh, line }; } // 生成地图3D模型 export function generateMapObject3D( mapdata, projectionFnParam ) { // 地图对象 const mapObject3D = new THREE.Object3D(); // 地图数据 const { features: basicFeatures } = mapdata; const { center, scale } = projectionFnParam; const projectionFn = d3 .geoMercator() .center(center) .scale(scale) .translate([0, 0]); const label2dData = []; // 存储自定义 2d 标签数据 // 每个省的数据 basicFeatures.forEach((basicFeatureItem) => { // 每个省份的地图对象 const provinceMapObject3D = new THREE.Object3D(); // 将地图数据挂在到模型数据上 provinceMapObject3D.customProperties = basicFeatureItem.properties; // 每个坐标类型 const featureType = basicFeatureItem.geometry.type; // 每个坐标数组 const featureCoords = basicFeatureItem.geometry.coordinates; // 每个中心点位置 const featureCenterCoord = basicFeatureItem.properties.centroid && projectionFn(basicFeatureItem.properties.centroid); // 名字 const featureName = basicFeatureItem.properties.name; if (featureCenterCoord) { label2dData.push({ featureCenterCoord, featureName, }); } // MultiPolygon 类型 if (featureType === "MultiPolygon") { featureCoords.forEach((multiPolygon) => { multiPolygon.forEach((polygon) => { const { mesh, line } = drawExtrudeMesh(polygon, projectionFn); provinceMapObject3D.add(mesh); provinceMapObject3D.add(line); }); }); } // Polygon 类型 if (featureType === "Polygon") { featureCoords.forEach((polygon) => { const { mesh, line } = drawExtrudeMesh(polygon, projectionFn); provinceMapObject3D.add(mesh); provinceMapObject3D.add(line); }); } mapObject3D.add(provinceMapObject3D); }); return { mapObject3D, label2dData }; } // 生成地图2D标签 export function generateMapLabel2D(label2dData) { const labelObject2D = new THREE.Object3D(); label2dData.forEach((item) => { const { featureCenterCoord, featureName } = item; const labelObjectItem = draw2dLabel(featureCenterCoord, featureName); if (labelObjectItem) { labelObject2D.add(labelObjectItem); } }); return labelObject2D; } // 生成地图spot点位 export function generateMapSpot(label2dData) { const spotObject3D = new THREE.Object3D(); const spotList = []; label2dData.forEach((item) => { const { featureCenterCoord } = item; const spotObjectItem = drawSpot(featureCenterCoord); if (spotObjectItem && spotObjectItem.circle && spotObjectItem.ring) { spotObject3D.add(spotObjectItem.circle); spotObject3D.add(spotObjectItem.ring); spotList.push(spotObjectItem.ring); } //TODO:渲染铁塔 }); return { spotObject3D, spotList }; } // 绘制二维标签 export const draw2dLabel = (coord, proviceName) => { if (coord && coord.length) { // 模版字符串 const innerHTML = `