地图(map)

地图

示例

在这里插入图片描述

HTML

<div id="map"></div>

CSS

html,
body {
    padding: 0;
    margin: 0;
    background-color: #111;
}

#map {
    height: 100vh;
}

.controls-container {
    background-color: #eee;
}

JS

mapboxgl.accessToken =  "pk.eyJ1IjoieWFwYWxleGVpIiwiYSI6ImNqNGVuaDRwdjBwZ2MycW1rM2FrMmpmNTQifQ.ouDro4DGQ4viVjdBgaI_Xg";
const { MercatorCoordinate } = mapboxgl;

const center = [-122.67118367793355, 45.520579458294915];
// const center = [0,0];

var map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/light-v10",
    center,
    zoom: 17,
    pitch: 50,
    antialias: true
});
map.showTileBoundaries = true;

map.on("load", function() {
    // map.addControl(new GeoJsonControl(), "bottom-right");
    map.addLayer(new DrawLayer());

class GeoJsonControl {
    onAdd(map) {
        this._map = map;
        this._container = document.createElement("div");
        this._container.className = "mapboxgl-ctrl controls-container";
        this._container.innerText = 'controls container';
        this._container.setAttribute("tabindex", 0);
        return this._container;
    }
    onRemove(map) {}
}

class DrawLayer {
    constructor() {
        this.id = 'threejs-layer';
        this.type = 'custom';
        this.renderingMode = '3d';
        
        this.modelOrigin = [0.5, 0.5];
        this.modelAltitude = 0;
        this.modelRotate = [Math.PI / 2, 0, 0];
        // this.modelScale = 0.000001;//5.41843220338983e-8;
        this.modelScale = 0.00001;
        
        this.myCamera = new THREE.PerspectiveCamera({
            near: 100,
            far: 200
        });
        this.myScene = new THREE.Scene();
        this.geoms = [];
        this.curZoom = null;
        this.curCenter = null;
    }
    
    createGeometryFromFeature(feature) {
        const { geometry, properties } = feature || {};
        if (!geometry) return;
        const { coordinates: coords, type } = geometry;
        const res = { originPoint: null, originLngLat: null, points: [], vectors: [] };
        const HEIGHT_MULTI = 0.035615;
        switch (type) {
            case 'Polygon':
                const path = new THREE.Shape();
                
                coords[0].reduce((sum, item, index, array) => {
                    const mPoint = MercatorCoordinate.fromLngLat([item[0], item[1]]);
                    // first point is the origin 0, 0 but remember it as the offset for the rest
                    if (!sum.originPoint) {
                        sum.originLngLat = item;
                        sum.originPoint = mPoint;
                        path.moveTo(0, 0);
                        return sum;
                    }
                    const originPoint = sum.originPoint;
                    const x = (originPoint.x - mPoint.x) * 1000000;
                    const y = (originPoint.y - mPoint.y) * 1000000;
                    path.lineTo(x, y);
                    return sum;
                }, res);
                const material = new THREE.MeshLambertMaterial( { color: 0xff0000 } );
                material.overdraw = true;
                const height = properties.height ? HEIGHT_MULTI * properties.height : 0;
                var extrudeSettings = {
                    amount: height,
                    bevelEnabled: false,
                	// steps: 16,
                	// depth: 16,
                	// bevelThickness: 1,
                	// bevelSize: 1,
                	// bevelOffset: 0,
                	// bevelSegments: 1
                };

                var geom = new THREE.ExtrudeGeometry( path, extrudeSettings );
                res.mesh = new THREE.Mesh( geom, material );
                res.mesh.castShadow = true;
                res.mesh.rotation.x = Math.PI / 2;
                res.mesh.rotation.z = Math.PI;
                res.mesh.position.y = height;
                
                console.log(res);
        }
        if (res.mesh) {
            this.myScene.add(res.mesh);
            this.geoms.push(res.mesh);
        }
        return res;
    }
    
    onAdd(map, gl) {
        this.map = map;
        // map.on('moveend', (e,b) => {
        //     this.curZoom = map.getZoom();
        //     this.curCenter = map.getCenter();
        //     if (this.curCenter) this.setCubePos(this.curCenter);
        // });
        map.on('click', (e) => {
            const features = map.queryRenderedFeatures(e.point);
            // console.log(features);
            const building = features.find((obj) => obj.layer.id === 'building' || obj.layer.id === '3d-building');
            if (this.geoms.length) {
                this.geoms.forEach((geom) => {
                    this.myScene.remove(geom);
                });
            }
            const res = this.createGeometryFromFeature(building);
            const center = res ? res.originLngLat : e.lngLat.toArray();
            
            this.setCubePos(center);
        });
        const renderer = new THREE.WebGLRenderer({
            canvas: map.getCanvas(),
            context: gl,
            antialias: true,
            precision: 'highp', //"highp", // "mediump" or "lowp"
            // preserveDrawingBuffer: true,
            powerPreference: 'low-power',
            // logarithmicDepthBuffer: true,
            // depth: true
        });
        // renderer.setPixelRatio( window.devicePixelRatio );
        renderer.autoClear = false;
        renderer.shadowMap.enabled = true;
        
        this.renderer = renderer;
        this.setupLights();
        this.setupShadowPlain();
        this.setupMesh();
        this.renderer.shadowMap.needsUpdate = true;
        this.setCubePos = this.setCubePos.bind(this);
    }
    
    setupLights() {
        this.light = new THREE.DirectionalLight(0xffffff, 0.5);
        this.light.position.set(-10, 13, 8);
        this.light.castShadow = true;
        this.light.shadow.camera.far = 1000;
        this.light.shadow.camera.near = 0;
        this.light.shadow.mapSize.width = 2048*2;
        this.light.shadow.mapSize.height = 2048*2;
        this.myScene.add(this.light);
        // this.myScene.add( new THREE.CameraHelper( this.light.shadow.camera ) );
        
        const ambientLight = new THREE.AmbientLight( 0x404040 );
        this.myScene.add(ambientLight);
        
    }
    
    setupShadowPlain() {
        const planeGeometry = new THREE.PlaneGeometry( 1/this.modelScale, 1/this.modelScale );
        const planeMaterial = new THREE.ShadowMaterial();
        planeMaterial.opacity = 0.4;
        planeMaterial.shadowSide = THREE.DoubleSide;
        
        this.shadowPlane = new THREE.Mesh( planeGeometry, planeMaterial );
        this.shadowPlane.rotation.x = -Math.PI / 2;
        this.shadowPlane.position.y = 0;
        this.shadowPlane.receiveShadow = true;
        this.myScene.add( this.shadowPlane );
    }
    
    setCubePos(loc) {
        console.log(loc);
        const center = loc && loc instanceof Array ? loc : loc.toArray && loc.toArray();
        if (center) {
            const p = MercatorCoordinate.fromLngLat(center);
            const mult = 1/this.modelScale;
            const offset = mult / 2;
            const res = { x: p.x * mult, y: p.y * mult };

            if (this.cube) {
                this.cube.position.x = res.x - offset;
                this.cube.position.z = res.y - offset;                
            }
        }
    }

    setupMesh() {
        const scale = .5;
        const segs = 1;
        const mat = new THREE.MeshLambertMaterial( { color: 0x00ff00 } )
        mat.overdraw = true;
        var cube = new THREE.Mesh(new THREE.BoxGeometry( scale, scale, scale, segs, segs, segs ), mat);
        this.cube = cube;
        const l = [-122.67118367793355, 45.520579458294915];
        cube.castShadow = true;
        cube.position.y = scale / 2;
        
        this.setCubePos(l);
        this.myScene.add(cube);
    }

    render(gl, matrix) {
        this.modelTransform = {
            translateX: this.modelOrigin[0],
            translateY: this.modelOrigin[1],
            translateZ: 0,
            rotateX: this.modelRotate[0],
            rotateY: this.modelRotate[1],
            rotateZ: this.modelRotate[2],
            scale: this.modelScale
        };
        var rotationX = new THREE.Matrix4()
            .makeRotationAxis(
                new THREE.Vector3(1, 0, 0),
                this.modelTransform.rotateX
            );
        var rotationY = new THREE.Matrix4()
            .makeRotationAxis(
                new THREE.Vector3(0, 1, 0),
                this.modelTransform.rotateY
            );
        var rotationZ = new THREE.Matrix4()
            .makeRotationAxis(
                new THREE.Vector3(0, 0, 1),
                this.modelTransform.rotateZ
            );

        var m = new THREE.Matrix4().fromArray(matrix);
        var l = new THREE.Matrix4()
            .makeTranslation(
                this.modelTransform.translateX,
                this.modelTransform.translateY,
                this.modelTransform.translateZ
            )
            .scale(
                new THREE.Vector3(
                    this.modelTransform.scale,
                    -this.modelTransform.scale,
                    this.modelTransform.scale
                )
            )
            .multiply(rotationX)
            .multiply(rotationY)
            .multiply(rotationZ);

        this.myCamera.projectionMatrix = m.multiply(l);
        this.renderer.state.reset();
        this.renderer.render(this.myScene, this.myCamera);
        this.map.triggerRepaint();
    }
}
发布了117 篇原创文章 · 获赞 54 · 访问量 8654

猜你喜欢

转载自blog.csdn.net/weixin_45544796/article/details/103801184