vue通过npm安装js实现mapbox自定义3D模板

vue实现mapbox自定义3D模板

  1. 使用npm进行安装js(默认安装最新版) npm地址

    1.npm i mapbox-gl
    2.npm i maptalks
    3.npm i maptalks.mapboxgl
    4.npm i @mapbox/mapbox-gl-language
    5.npm i three
    
  2. 引用我们需要的js

    const mapboxgl = require('mapbox-gl');
    const maptalks = require('maptalks');
    const maptalksM = require('maptalks.mapboxgl');
    const MapboxLanguage = require("@mapbox/mapbox-gl-language");
    const THREE = window.THREE = require('three');
    const {ColladaLoader} = require('three/examples/jsm/loaders/ColladaLoader');//在three.js包下
    
  3. 定义data数据

    data() {
            return {
                positionLocation: [121.509758, 31.300800],
                zoom: 16,
                pitch: 60,  //地图的角度,不写默认是0,取值是0-60度,一般在3D中使用
                bearing: 10,
                antialias: false, //抗锯齿,通过false关闭提升性能
                maxPitch: 60,
                container: 'map',
                lonlats: [],
                baseUrl: "api/service-count",
                markerRe: [],//标点
                x_PI: 3.14159265358979324 * 3000.0 / 180.0,
                PI: 3.1415926535897932384626,
                a: 6378245.0,
                ee: 0.00669342162296594323,
                layer: "",
            };
        },
    
  4. 定义一个容器

    <template>
        <div id="map">
        </div>
    </template>
    <style scoped>
    /* mapbox css*/
     	@import url('https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.css');
        #map {
            position: absolute;
            top: 40px;
            bottom: 0;
            width: 100%;
            margin-left: -24px;
        }
    </style>
    
  5. 完整的js代码 (去mapboxgl官网中注册账号,并新建一个token)

                    
             /**
              * 判断坐标是否在国内   百度坐标转gps坐标 start
              */
             out_of_china(lng, lat) {
                 return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
             },
             /**
              * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
              * 即 百度 转 谷歌、高德
              */
             bd09togcj02(bd_lon, bd_lat) {
                 var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
                 var x = bd_lon - 0.0065;
                 var y = bd_lat - 0.006;
                 var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
                 var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
                 var gg_lng = z * Math.cos(theta);
                 var gg_lat = z * Math.sin(theta);
                 return [gg_lng, gg_lat]
             },
             /**
              * GCJ02 转换为 WGS84
              */
             gcj02towgs84(lng, lat) {
                 if (this.out_of_china(lng, lat)) {
                     return [lng, lat]
                 } else {
                     var dlat = this.transformlat(lng - 105.0, lat - 35.0);
                     var dlng = this.transformlng(lng - 105.0, lat - 35.0);
                     var radlat = lat / 180.0 * this.PI;
                     var magic = Math.sin(radlat);
                     magic = 1 - this.ee * magic * magic;
                     var sqrtmagic = Math.sqrt(magic);
                     dlat = (dlat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtmagic) * this.PI);
                     dlng = (dlng * 180.0) / (this.a / sqrtmagic * Math.cos(radlat) * this.PI);
                     var mglat = lat + dlat;
                     var mglng = lng + dlng;
                     return [lng * 2 - mglng, lat * 2 - mglat]
                 }
             },
             transformlat(lng, lat) {
                 var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
                 ret += (20.0 * Math.sin(6.0 * lng * this.PI) + 20.0 * Math.sin(2.0 * lng * this.PI)) * 2.0 / 3.0;
                 ret += (20.0 * Math.sin(lat * this.PI) + 40.0 * Math.sin(lat / 3.0 * this.PI)) * 2.0 / 3.0;
                 ret += (160.0 * Math.sin(lat / 12.0 * this.PI) + 320 * Math.sin(lat * this.PI / 30.0)) * 2.0 / 3.0;
                 return ret
             },
    
             transformlng(lng, lat) {
                 var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
                 ret += (20.0 * Math.sin(6.0 * lng * this.PI) + 20.0 * Math.sin(2.0 * lng * this.PI)) * 2.0 / 3.0;
                 ret += (20.0 * Math.sin(lng * this.PI) + 40.0 * Math.sin(lng / 3.0 * this.PI)) * 2.0 / 3.0;
                 ret += (150.0 * Math.sin(lng / 12.0 * this.PI) + 300.0 * Math.sin(lng / 30.0 * this.PI)) * 2.0 / 3.0;
                 return ret
             },
             baiMapGps(long, lat) {
                 let bd09togcj = this.bd09togcj02(long, lat);//百度转火星
                 let baiMapGps = this.gcj02towgs84(bd09togcj[0], bd09togcj[1]);//GCJ02 转换为 WGS84
                 return baiMapGps;
             },
             /**
              * 百度坐标转gps坐标 end
              */
             initMarker() {
                 this.$http({
                     url: this.baseUrl + "/xxxx/xx",
                     method: "GET"
                 })
                     .then(response => {
                         this.lonlats = response.data[0];
                         this.marker();
                         this.initMap();
                     })
                     .catch(e => {
                         console.log(e);
                     });
             },
             initMap() {
                 mapboxgl.accessToken = 'pk.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
                 var map = new mapboxgl.Map({
                     container: 'map',
                     style: 'mapbox://styles/mapbox/dark-v9',
                     maxPitch: this.maxPitch,
                     center: this.positionLocation,
                     zoom: this.zoom,
                     pitch: this.pitch,
                     bearing: this.bearing
                 });
                 /**
                  * 设置中文
                  */
                 map.addControl(new MapboxLanguage({
                     defaultLanguage: 'zh'
                 }));
                 /**
                  * 添加 3D模板 start
                  */
                     // 确保模型在地图上正确地理参考的参数
                 var modelOrigin = [121.509758, 31.300800];
                 var modelAltitude = 0;
                 var modelRotate = [Math.PI / 2, 0, 0];
                 var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
                     modelOrigin,
                     modelAltitude
                 );
    
                 // 转换参数以在地图上定位,旋转和缩放3D模型
                 var modelTransform = {
                     translateX: modelAsMercatorCoordinate.x,
                     translateY: modelAsMercatorCoordinate.y,
                     translateZ: modelAsMercatorCoordinate.z,
                     rotateX: modelRotate[0],
                     rotateY: modelRotate[1],
                     rotateZ: modelRotate[2],
                     /* Since our 3D model is in real world meters, a scale transform needs to be
                     * applied since the CustomLayerInterface expects units in MercatorCoordinates.
                     */
                     scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
                 };
                 // 根据CustomLayerInterface为3D模型配置自定义层
                 //var THREE = window.THREE; //= require('three');
                 var customLayer = {
                     id: '3d-model',
                     type: 'custom',
                     renderingMode: '3d',
                     onAdd: function (map, gl) {
                         this.camera = new THREE.Camera();
                         this.scene = new THREE.Scene();
    
                         // 创建两个three.js灯来照亮模型
                         var directionalLight = new THREE.DirectionalLight(0xcccccc);
                         directionalLight.position.set(0, -70, 100).normalize();
                         this.scene.add(directionalLight);
    
                         var directionalLight2 = new THREE.DirectionalLight(0xcccccc);
                         directionalLight2.position.set(0, 70, 100).normalize();
                         this.scene.add(directionalLight2);
    
                         // 使用three.js GLTF加载器将3D模型添加到three.js场景
                         var loader = new ColladaLoader;
                         loader.load('./dist/xxx.dae',
                             function (gltf) {
                                 this.scene.add(gltf.scene);
                             }.bind(this),
                             // called while loading is progressing
                             function (xhr) {
                                 //console.log("xhr:", xhr);
                                 //console.log((xhr.loaded / xhr.total * 100) + '% loaded');
                             },
                             // called when loading has errors
                             function (error) {
                                 console.log("errot:", error);
                             }
                         );
                         this.map = map;
                         // 对three.js使用Mapbox GL JS地图画布
                         this.renderer = new THREE.WebGLRenderer({
                             canvas: map.getCanvas(),
                             context: gl,
                             antialias: true
                         });
                         this.renderer.autoClear = false;
                     },
                     render: function (gl, matrix) {
                         var rotationX = new THREE.Matrix4().makeRotationAxis(
                             new THREE.Vector3(1, 0, 0),
                             modelTransform.rotateX
                         );
                         var rotationY = new THREE.Matrix4().makeRotationAxis(
                             new THREE.Vector3(0, 1, 0),
                             modelTransform.rotateY
                         );
                         var rotationZ = new THREE.Matrix4().makeRotationAxis(
                             new THREE.Vector3(0, 0, 1),
                             modelTransform.rotateZ
                         );
    
                         var m = new THREE.Matrix4().fromArray(matrix);
                         var l = new THREE.Matrix4()
                             .makeTranslation(
                                 modelTransform.translateX,
                                 modelTransform.translateY,
                                 modelTransform.translateZ
                             )
                             .scale(
                                 new THREE.Vector3(
                                     modelTransform.scale,
                                     -modelTransform.scale,
                                     modelTransform.scale
                                 )
                             )
                             .multiply(rotationX)
                             .multiply(rotationY)
                             .multiply(rotationZ);
    
                         this.camera.projectionMatrix = m.multiply(l);
                         this.renderer.state.reset();
                         this.renderer.render(this.scene, this.camera);
                         this.map.triggerRepaint();
                     }
                 };
                 /**
                  * 添加 3D模板 end
                  */
                 /**
                  * 添加 热力图 start
                  */
                 let lonlat = this.lonlats.lonlat;
                 let arrList = [];
                 for (let i = 0; i < lonlat.length; i++) {
                     let aa = {
                         type: "Feature",
                         properties: {
                             dbh: Math.ceil(Math.random() * 100)
                         },
                         geometry: {
                             type: "Point",
                             coordinates: this.baiMapGps(lonlat[i].lon, lonlat[i].lat)
                         }
                     };
                     arrList.push(aa);
                 }
                 var geojson = {
                     type: "FeatureCollection",
                     features: arrList
                 };
                 /* 摄像头数据 */
                 let cameraGeojson = {
                     type: "FeatureCollection",
                     features: [
                         {
                             type: 'Feature',
                             properties: {
                                 dbh: '摄像头1'
                             },
                             geometry: {
                                 type: 'Point',
                                 coordinates: [121.510758, 31.301800],
                             }
                         },
                     ]
                 };
                 map.on('load', function () {
                     /* 3D 模板 */
                     map.addLayer(customLayer, 'waterway-label');
                     /* 摄像头 */
                     map.loadImage(
                         './dist/2.png',
                         function (error, image) {
                             if (error) throw error;
                             map.addImage('camera', image);
                             map.addSource('point', {
                                 'type': 'geojson',
                                 'data': cameraGeojson
                             });
                             map.addLayer({
                                 id: 'points',
                                 type: 'symbol',
                                 source: 'point',
                                 layout: {
                                     'icon-image': 'camera',
                                     'icon-size': 1.0
                                 }
                             });
                             map.on('click', 'points', function (e) {
                                 alert(e.features[0].properties.dbh);
                             });
                         });
                     /* 热力图 */
                     map.addSource('trees', {
                         type: 'geojson',
                         data: geojson
                     });
                     // add heatmap layer here
                     // add circle layer here
                     map.addLayer({
                         id: 'trees-heat',
                         type: 'heatmap',
                         source: 'trees',
                         maxzoom: 15,
                         paint: {
                             // increase weight as diameter breast height increases
                             'heatmap-weight': {
                                 property: 'dbh',
                                 type: 'exponential',
                                 stops: [
                                     [1, 0],
                                     [62, 1]
                                 ]
                             },
                             // increase intensity as zoom level increases
                             'heatmap-intensity': {
                                 stops: [
                                     [11, 1],
                                     [15, 3]
                                 ]
                             },
                             // assign color values be applied to points depending on their density
                             'heatmap-color': [
                                 'interpolate',
                                 ['linear'],
                                 ['heatmap-density'],
                                 0, 'rgba(236,222,239,0)',
                                 0.2, 'rgb(208,209,230)',
                                 0.4, 'rgb(166,189,219)',
                                 0.6, 'rgb(103,169,207)',
                                 0.8, 'rgb(28,144,153)',
                                 1.0, 'rgb(219,63,99)'
                             ],
                             // increase radius as zoom increases
                             'heatmap-radius': {
                                 stops: [
                                     [11, 15],
                                     [15, 20]
                                 ]
                             },
                             // decrease opacity to transition into the circle layer
                             'heatmap-opacity': {
                                 default: 1,
                                 stops: [
                                     [14, 1],
                                     [15, 0]
                                 ]
                             },
                         }
                     }, 'waterway-label');
                     map.addLayer({
                         id: 'trees-point',
                         type: 'circle',
                         source: 'trees',
                         minzoom: 14,
                         paint: {
                             // increase the radius of the circle as the zoom level and dbh value increases
                             'circle-radius': {
                                 property: 'dbh',
                                 type: 'exponential',
                                 stops: [
                                     [{zoom: 15, value: 1}, 5],
                                     [{zoom: 15, value: 62}, 10],
                                     [{zoom: 22, value: 1}, 20],
                                     [{zoom: 22, value: 62}, 50],
                                 ]
                             },
                             'circle-color': {
                                 property: 'dbh',
                                 type: 'exponential',
                                 stops: [
                                     [0, 'rgba(236,222,239,0)'],
                                     [10, 'rgb(236,222,239)'],
                                     [20, 'rgb(208,209,230)'],
                                     [30, 'rgb(166,189,219)'],
                                     [40, 'rgb(103,169,207)'],
                                     [50, 'rgb(28,144,153)'],
                                     [60, 'rgb(1,108,89)'],
                                     [80, 'rgb(232,78,109)'],
    
                                 ]
                             },
                             'circle-stroke-color': 'white',
                             'circle-stroke-width': 1,
                             'circle-opacity': {
                                 stops: [
                                     [14, 0],
                                     [15, 1]
                                 ]
                             }
                         }
                     }, 'waterway-label');
                     map.on('click', 'trees-point', function (e) {
                         var proup = new mapboxgl.Popup()
                         proup.setLngLat(e.features[0].geometry.coordinates)
                         proup.setHTML('<div>当前人数:'+ e.features[0].properties.dbh +'</div> ')
                         proup.addTo(map);
    
                     });
                 });
                 /**
                  * 热力图 end
                  */
             }
    
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值