Three.js地图轮廓分割效果

Three.js地图轮廓分割效果

在这里插入图片描述

  • 基于GeoJson数据解析绘制,支持多级国家/省/市细粒度路径绘制
  • 可以通过Shader/材质/贴图实现不同的轮廓分割效果

阿里云GeoJson配置/下载地址

相关方法

	// 经纬度与世界坐标转换
	 const getPosition = (lng, lat, radius) => {
  		 const phi = (180 + lng) * (Math.PI / 180);
  		 const theta = (90 - lat) * (Math.PI / 180);
  		 return {
   		 	 x: -radius * Math.sin(theta) * Math.cos(phi),
    		 y: radius * Math.cos(theta),
   		 	 z: radius * Math.sin(theta) * Math.sin(phi),
  		 };
      };
      
	// 解析出GeoJson中所有的图形集合
      const parseGeoJson = ({ features }) => {
        if (!features.length) return [];
        return features.reduce((areas, item) => {
          const { coordinates } = item.geometry;
          return areas.concat(
            coordinates.reduce((careas, citem) => {
              return careas.concat(citem);
            }, [])
          );
        }, []);
      };

      // 绘制地球
      const drawEarth = (radius) => {
        const geometry = new THREE.SphereGeometry(radius, 50, 50);
        const texture = new THREE.TextureLoader().load("./img/earth.jpeg");
        const earthMat = new THREE.MeshStandardMaterial({
          transparent: false,
          depthWrite: true,
          map: texture,
          roughness: 0.6,
        });
        return new THREE.Mesh(geometry, earthMat);
      };

      // 绘制球形路径
      const drawEarthWall = (radius, geoJson, height = 1) => {
        // 解析路径数据
        const positionArrays = parseGeoJson(geoJson);
        // 构建透明墙体材质
        const material = createFlowWallMat({});
        const earthWallGroup = new THREE.Group();
        positionArrays.forEach((item) => {
          const path = item.reduce((arr, [lng, lat]) => {
            const p1 = getPosition(lng, lat, radius);
            const p2 = getPosition(lng, lat, radius + height);
            return arr.concat([
              [
                [p1.x, p1.y, p1.z],
                [p2.x, p2.y, p2.z],
              ],
            ]);
          }, []);
          const wallMesh = creatWallByPath({ path, material, expand: false });
          earthWallGroup.add(wallMesh);
        });
        return earthWallGroup;
      };

使用方法

creatWallByPathcreateFlowWallMat 方法参考前面的文章

	  import CQgeoJson from "./data/cq_geo_json.js";
      import CHINAgeoJson from "./data/china_geo_json.js";
      import { creatWallByPath, createFlowWallMat } from "./js/effect.js";
      
		// 地球半径
        const radius = 50;
        // 绘制地球
        const earthMesh = drawEarth(radius);
        // 绘制中国地图轮廓
        const chinaWallMesh = drawEarthWall(radius, CHINAgeoJson, 3);
        // 绘制重庆轮廓
        const cqWallMesh = drawEarthWall(radius, CQgeoJson, 2);

        scene.add(earthMesh);
        scene.add(cqWallMesh);
        scene.add(chinaWallMesh);
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值