首页 > 其他分享 >three.js实现简单的3D中国省份立体板块地图

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

时间:2022-09-06 18:01:45浏览次数:79  
标签: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
From: https://www.cnblogs.com/huangchun/p/16662779.html

相关文章

  • jsp大文件上传解决方案支持分片断点上传
    ​前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对Http协议较模糊,故这次采用渐进的方式来学习文件上传的原......
  • Js学习之------如何判断对象为空?
    1、JSON.stringify()JSON.stringify()可以把json对象转为json字符串只需要判断序列化后的对象是否全等于字符串“{}”即可2、Object.keys()ES6中Object.keys()方法,会把对象中......
  • 关于nodejs的一些笔记
    node.js和JavaScript还是有一定的渊源的简单来说,Nodejs就是运行在服务端的JavaScript浏览器有一个引擎比如谷歌的chrome里的叫做V8这个引擎可以翻译JavaScript脚本,然......
  • python requests.post() 请求中 json 和 data 的区别
    requests.post()请求中json和data的区别post请求中,可以使用data传递参数,也可以使用json传递参数。那么,两种方式有什么区别?1.如果参数为JSON数据,可以直接传入json参......
  • js之三级联动省市县
    1<!DOCTYPEhtml>2<htmllang="en">34<head>5<metacharset="UTF-8">6<metahttp-equiv="X-UA-Compatible"content="IE=edge">7......
  • 前端不缓存,ajax不缓存,js操作cookie
    前端不缓存,ajax不缓存,js操作cookie 今天实现网站注销功能时,需要清除cookie缓存,开始在网上搜索的是“js清除缓存”,发现很多都是预先防患缓存存储的内容,千篇一律,不过也......
  • 通过JSON处理网络信息
    在build.gradle中引用如下dependencies{ implementation'net.sf.json-lib:json-lib:2.2.3:jdk15'//jsonobjectimplementation'commons-beanutils:commons-b......
  • webgl(three.js)实现室内三维定位,3D定位,3D楼宇bim、实时定位三维可视化解决方案——
    序:还是要抽出时间看书的,迷上了豆豆的作品,最近在看《天幕红尘》,书中主人公的人生价值观以及修为都是让我惊为叹止。很想成为那样的人,但是再看看自己每天干的事,与时间的......
  • three.js绘制地图(平面、曲面)
    加载中国地图json数据letloader=newTHREE.FileLoader();loader.load('model/chinaJson.json',function(data){letjsonData=JSON.parse(data);initMap(......
  • js大文件上传解决方案(500M以上)
    ​一、功能性需求与非功能性需求要求操作便利,一次选择多个文件和文件夹进行上传;支持PC端全平台操作系统,Windows,Linux,Mac支持文件和文件夹的批量下载,断点续传。刷新......