mapbox-buildings-mapzen.html 6.8 KB
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Map3D - ECHARTS-GL</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes"> <!-- Fullscreen Landscape on iOS -->
        <link rel="stylesheet" href="./common.css">
    </head>
    <body>
        <div id="main"></div>
        <script src="../node_modules/echarts/dist/echarts.js"></script>
        <script src="../dist/echarts-gl.js"></script>
        <script src='lib/mapbox-gl.js'></script>
        <link href='lib/mapbox-gl.css' rel='stylesheet' />
        <script src="lib/jquery.min.js"></script>
        <script src="lib/dat.gui.js"></script>
        <script src="lib/LRU.js"></script>
        <script src="https://unpkg.com/sphericalmercator"></script>
        <script src="js/commonUI.js"></script>
        <script>
            mapboxgl.accessToken = window.location.search.slice(1);
            var chart = echarts.init(document.getElementById('main'));
            var cache = new LRUCache(100);

            chart.setOption({
                mapbox3D: {
                    // 北京
                    // center: [116.39157, 39.90673],
                    // 纽约
                    center: [-74.02158343200102, 40.6143657735403],
                    // 上海
                    // center: [121.4978, 31.2398],
                    // 伦敦
                    // center: [-0.118092, 51.509865],
                    zoom: 17,
                    pitch: 10,
                    // bearing: -10,
                    style: 'mapbox://styles/mapbox/light-v9',
                    altitudeScale: 2,
                    postEffect: {
                        enable: true,
                        screenSpaceAmbientOcclusion: {
                            enable: true,
                            intensity: 2,
                            quality: 'high',
                            radius: 7
                        },
                        screenSpaceReflection: {
                            enable: false
                        },
                        depthOfField: {
                            enable: false,
                            blurRadius: 5,
                            focalDistance: 80
                        }
                    },
                    light: {
                        main: {
                            intensity: 1,
                            alpha: -30,
                            shadow: true,
                            shadowQuality: 'high'
                        },
                        ambient: {
                            intensity: 0.
                        },
                        ambientCubemap: {
                            texture: 'asset/pisa.hdr',
                            exposure: 1,
                            diffuseIntensity: 0.5,
                            specularIntensity: 1
                        }
                    }
                },
                series: [{
                    type: 'polygons3D',
                    coordinateSystem: 'mapbox3D',
                    data: [],
                    shading: 'realistic',
                    silent: true,
                    realisticMaterial: {
                        metalness: 0,
                        roughness: 0.8
                    }
                }]
            });

            function addBuildings(geoJSON) {
                chart.hideLoading();
                var polygonsData = geoJSON.features.filter(function (feature) {
                    return feature.geometry.type === 'Polygon'
                        || feature.geometry.type === 'MultiPolygon'
                }).map(function (feature) {
                    return {
                        coords: feature.geometry.coordinates,
                        multiPolygon: feature.geometry.type === 'MultiPolygon',
                        value: Math.random(),
                        height: +feature.properties.height || 5
                    };
                });

                chart.addData({
                    seriesIndex: 0,
                    data: polygonsData
                });
            }

            var requests = [];

            function loadBuildings() {
                chart.hideLoading();
                chart.showLoading();

                chart.setOption({
                    series: [{
                        // Clear
                        data: []
                    }]
                });

                var mapbox = chart.getModel().getComponent('mapbox3D').getMapbox();
                var coordBounds = mapbox.getBounds();
                var merc = new SphericalMercator({
                    size: 512
                });
                var tileBounds = merc.xyz(
                    [coordBounds.getWest(), coordBounds.getSouth(), coordBounds.getEast(), coordBounds.getNorth()],
                    15
                );

                var z = 15;
                var loadingCount = 0;

                requests.forEach(function (req) {
                    req.abort();
                });
                requests = [];
                function load(url) {
                    var geoJSON = cache.get(url);
                    if (geoJSON) {
                        addBuildings(geoJSON);
                    }
                    else {
                        loadingCount++;
                        var request = $.getJSON(url).done(function (geoJSON) {
                            loadingCount--;
                            cache.put(url, geoJSON);

                            addBuildings(geoJSON);

                            requests.splice(requests.indexOf(request), 1);
                        });
                        requests.push(request);
                    }
                }
                for (var x = tileBounds.minX; x <= tileBounds.maxX; x++) {
                    for (var y = tileBounds.minY; y <=tileBounds.maxY; y++) {
                        load(`https://tile.mapzen.com/mapzen/vector/v1/512/buildings/${z}/${x}/${y}.json?api_key=${MAPZEN_API}`);
                    }
                }
            };


            var gui = new dat.GUI();
            var config = {
                roughness: 0.4
            }
            gui.add(config, 'roughness', 0.1, 0.9).onFinishChange(function () {
                chart.setOption({
                    series: [{
                        realisticMaterial: {
                            roughness: config.roughness
                        }
                    }]
                });
            });
            window.addEventListener('resize', function () {
                chart.resize();
            });


            loadBuildings();


            var mapbox = chart.getModel().getComponent('mapbox3D').getMapbox();
            mapbox.on('dragend', loadBuildings);
        </script>
    </body>
</html>