动态

详情 返回 返回

threejs接入gis地圖 - 动态 详情

把 TIF 解析成可用紋理(如 PNG/JPEG 或直接用 TIF)。

把它當作材質貼到一個 PlaneGeometry 上。

按照它對應的座標範圍換算成 Three.js 世界座標。

把 Plane 放置在對應位置。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Three.js Scene</title>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
    <script type="importmap">
        {
            "imports": {
                "three": "./three172/build/three.module.js",
                "three/addons/": "./three172/examples/jsm/"
            }
        }
    </script>

    <script type="module">
        import * as THREE from 'three';
        import {OrbitControls} from 'three/addons/controls/OrbitControls.js'
        

        const geoBounds = {
  minLon: 104.055633544921875,
  maxLon: 104.069366455078125,
  minLat: 30.550435135095270,
  maxLat: 30.561078433806014,
};

const imgWidth = 2560;
const imgHeight = 2304;

// ---------------------------------
// 初始化場景、相機、渲染器
// ---------------------------------
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);

const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 500000);
camera.position.set(0, 0, 500); // 從側面看地圖
// camera.up.set(0,0,1); // 調整Z軸向上

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0,0,0);
controls.update();

// ---------------------------------
// 根據邊界計算地圖平面尺寸
// ---------------------------------
// 經緯度範圍(這裏只是用比例換算,不做墨卡託轉換)
const lonRange = geoBounds.maxLon - geoBounds.minLon;
const latRange = geoBounds.maxLat - geoBounds.minLat;

// 按圖片像素比例設置世界單位尺寸,比如按像素大小直接對應世界單位
// 也可以換成比例,比如1像素=1單位
const planeWidth = imgWidth;
const planeHeight = imgHeight;

const texture = new THREE.TextureLoader().load('./assets/55.png', () => {
  renderer.render(scene, camera);
});

// ---------------------------------
// 創建平面貼圖
// ---------------------------------
const planeGeo = new THREE.PlaneGeometry(planeWidth, planeHeight);
const planeMat = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide });
const plane = new THREE.Mesh(planeGeo, planeMat);
scene.add(plane);

// 平面居中放置
plane.rotation.x = -Math.PI / 2; // 讓平面平躺(XZ平面),也可根據需要旋轉
// 默認 plane.center 是 (0,0),所以不用平移
// 你也可以根據經緯度比例換算對應平移,比如:
// plane.position.set(...)


// ---------------------------------
// 座標轉換示例:
// lonLat 到平面座標
// ---------------------------------
function lonLatToPlane(lon, lat) {
  const x = ((lon - geoBounds.minLon) / lonRange - 0.5) * planeWidth;
  const y = ((lat - geoBounds.minLat) / latRange - 0.5) * planeHeight;
  return new THREE.Vector3(x, 0, -y); // Y軸朝上,所以取負
}

// 放個點看看效果
const point = new THREE.Mesh(
  new THREE.SphereGeometry(10),
  new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
const pointPos = lonLatToPlane(104.0646589,30.5568166); // 示例座標
point.position.copy(pointPos);
scene.add(point);

// ---------------------------------
// 燈光
// ---------------------------------
const light = new THREE.HemisphereLight(0xffffff, 0x888888, 1);
scene.add(light);

// ---------------------------------
// 響應式
// ---------------------------------
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth/window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

// ---------------------------------
// 動畫
// ---------------------------------
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

        
    </script>
</body>
</html>

推薦一個數字孿生的開源框架
https://github.com/nikonikoCW/Meteor3DEditor
image.png

user avatar alibabawenyujishu 头像 zaotalk 头像 smalike 头像 jingdongkeji 头像 kobe_fans_zxc 头像 chongdianqishi 头像 huajianketang 头像 xiaoxxuejishu 头像 solvep 头像 febobo 头像 guixiangyyds 头像 zhulongxu 头像
点赞 76 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.