ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

three.js实现简单的3D中国省份立体板块地图

2022-09-06 18:00:44  阅读:282  来源: 互联网

标签:function const material THREE three window new js 3D


image

源码资料获取:https://github.com/huangchun0121/3D-example/tree/main/省份立体板块

实现代码:

点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>中国地图</title>
    <style>
        /*body{*/
        /*    width: 100%;*/
        /*    height: 100%;*/
        /*    padding: 0;*/
        /*    margin: 0;*/
        /*}*/


    </style>
</head>
<body>
<div id="provinceInfo"></div>
<script src="js/three.js"></script>
<script src="js/three.orbitcontrols.js"></script>
<script src="js/d3-array.v1.min.js"></script>
<script src="js/d3-geo.v1.min.js"></script>
<script>

    let renderer, camera, scene, light, controller;
    const width = window.innerWidth, height = window.innerHeight;
    var map;

    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    /**
     * @description 初始化渲染场景
     */
    function initRenderer() {
       renderer = new THREE.WebGLRenderer({attributes:true});
       renderer.setSize(width,height);
       document.body.appendChild(renderer.domElement);
    }
    /**
     * @description 初始化相机
     */
    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, -70, 150);
        camera.lookAt(0, 0, 0);
    }
    /**
     * @description 初始化场景
     */
    function initScene() {
        scene = new THREE.Scene();
    }
    /**
     * 初始化用户交互
     **/
    function initControls() {
        controller = new THREE.OrbitControls(camera, renderer.domElement);
    }

    /**
     * 初始化物体
     */
    function initObject(){
        var loader = new THREE.FileLoader();
        loader.load('model/chinaJson.json',function(data){
            var chinaData = JSON.parse(data);
            initMap(chinaData);
        });
        window.addEventListener('mousemove', onm ouseMove, false);
    }
    /**
     * 描绘中国边界(平面)
     */
    function initMap(chinaJson) {
        // 建一个空对象存放对象
        map = new THREE.Object3D();

        // 墨卡托投影转换
        const projection = d3.geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0]);

        chinaJson.features.forEach(elem => {
            // 定一个省份3D对象
            const province = new THREE.Object3D();
            // 每个的 坐标 数组
            const coordinates = elem.geometry.coordinates;
            // 循环坐标数组
            coordinates.forEach(multiPolygon => {

                multiPolygon.forEach(polygon => {
                    const shape = new THREE.Shape();
                    const lineMaterial = new THREE.LineBasicMaterial({
                        color: 'white'
                    });
                    const lineGeometry = new THREE.Geometry();

                    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);
                        lineGeometry.vertices.push(new THREE.Vector3(x, -y, 4.01));
                    }

                    const extrudeSettings = {
                        depth: 4,
                        bevelEnabled: false
                    };

                    const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
                    const material = new THREE.MeshBasicMaterial({
                        color: '#02A1E2',
                        transparent: true,
                        opacity: 0.6
                    });
                    const material1 = new THREE.MeshBasicMaterial({
                        color: '#3480C4',
                        transparent: true,
                        opacity: 0.5
                    });
                    /* const material = new THREE.MeshBasicMaterial({ color: '#dedede', transparent: false, opacity: 0.6 });
                    const material1 = new THREE.MeshBasicMaterial({ color: '#dedede', transparent: false, opacity: 0.5 }); */
                    const mesh = new THREE.Mesh(geometry, [material, material1]);
                    const line = new THREE.Line(lineGeometry, lineMaterial);
                    province.add(mesh);
                    province.add(line)

                })

            })
            // 将geo的属性放到省份模型中
            province.properties = elem.properties;
            if (elem.properties.contorid) {
                const [x, y] = projection(elem.properties.contorid);
                province.properties._centroid = [x, y];
            }

            map.add(province);

        })

       scene.add(map);
    }

    /**
     * 鼠标拾取
     */

    function onm ouseMove(event) {

        // calculate mouse position in normalized device coordinates
        // (-1 to +1) for both components

       mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    }
    /**
     * @description 初始化光
     */
    function initLight() {
        const ambientLight = new THREE.AmbientLight( 0xffffff );
        scene.add( ambientLight );
    }

    /**
     * 窗口变动
     **/
    function onWindowResize() {
        camera.aspect = innerWidth / innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( innerWidth, innerHeight );
        renders();
    }

    /**
     * 渲染
     */
    function renders() {
        renderer.clear();
        renderer.render( scene, camera );
    }

    /**
     * 更新
     **/
    var activeInstersect =[];//用于存放选中的物体
    function animate() {
        requestAnimationFrame(animate);
        if(controller) controller.update();

        raycaster.setFromCamera(mouse,camera);
        var intersects = raycaster.intersectObjects(scene.children,true);//获取鼠标与屏幕射线相交的物体

        if (activeInstersect.length > 0) { // 将上一次选中的恢复好颜色
            activeInstersect.forEach(element => {
                element.object.material[0].color.set('#02A1E2');
                element.object.material[1].color.set('#3480C4');
            });
        }

         activeInstersect = []; // 设置为空

        for (var i = 0; i < intersects.length; i++) {      //
            if (intersects[i].object.material && intersects[i].object.material.length === 2) {
                activeInstersect.push(intersects[i]);
                intersects[i].object.material[0].color.set(0xff0000);
                intersects[i].object.material[1].color.set(0xff0000);
                break; // 只取第一个
            }
        }

        renders();
    }

    window.onload = () => {
        initRenderer();
        initCamera();
        initScene();
        initObject();
        initLight();
        initControls();
        animate();
        window.addEventListener('resize', onWindowResize, false);
    }

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

标签:function,const,material,THREE,three,window,new,js,3D
来源: https://www.cnblogs.com/huangchun/p/16662779.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有