美文网首页开源GIS相关
MapBox GL融合Canvas制作动态效果

MapBox GL融合Canvas制作动态效果

作者: giscoder | 来源:发表于2020-03-08 18:20 被阅读0次

    问题描述

    当我们在使用MapBox过程中,有时需要添加动态图标或者一些其他复杂的效果。由于MapBox未提供添加GIF格式图片的接口。所以添加起来比较麻烦。而往往这些效果使用HTML或使用Canvas绘制很容易实现,所以本文主要介绍如何在MapBox中集成HTML或集成自定义Canvas效果。

    相关接口

    MapBox提供了addImage(id,image,options)方法,其具体介绍如下:

     Add an image to the style. This image can be displayed on the map like any other icon in the style's sprite using the image's ID with icon-image, background-pattern, fill-pattern, or line-pattern. A Map#error event will be fired if there is not enough space in the sprite to add this image.
    
    Parameters
    id(string)The ID of the image.
    image((HTMLImageElement | ImageBitmap | ImageData | {width: number, height: number, data: (Uint8Array | Uint8ClampedArray)} | StyleImageInterface))The image as an HTMLImageElement , ImageData , ImageBitmap or object with width , height , and data properties with the same format as ImageData .
    

    从接口中,我们可以看到,在image参数中,可以使用HTMLImageElement图片,我们可以查看HTMLImageElement的介绍。这就为我们使用自动有HTML或Canvas提供了方法。

    官方示例

    在MapBox的官方示例中提供了一种绘制动态点的例子。Add an animated icon to the map。该示例如下:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>Add an animated icon to the map</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css" rel="stylesheet" />
    <style>
        body { margin: 0; padding: 0; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
    </style>
    </head>
    <body>
    <div id="map"></div>
     
    <script>
        mapboxgl.accessToken = '<your access token here>';
    var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v9'
    });
     
    var size = 200;
     
    // implementation of CustomLayerInterface to draw a pulsing dot icon on the map
    // see https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface for more info
    var pulsingDot = {
    width: size,
    height: size,
    data: new Uint8Array(size * size * 4),
     
    // get rendering context for the map canvas when layer is added to the map
    onAdd: function() {
    var canvas = document.createElement('canvas');
    canvas.width = this.width;
    canvas.height = this.height;
    this.context = canvas.getContext('2d');
    },
     
    // called once before every frame where the icon will be used
    render: function() {
    var duration = 1000;
    var t = (performance.now() % duration) / duration;
     
    var radius = (size / 2) * 0.3;
    var outerRadius = (size / 2) * 0.7 * t + radius;
    var context = this.context;
     
    // draw outer circle
    context.clearRect(0, 0, this.width, this.height);
    context.beginPath();
    context.arc(
    this.width / 2,
    this.height / 2,
    outerRadius,
    0,
    Math.PI * 2
    );
    context.fillStyle = 'rgba(255, 200, 200,' + (1 - t) + ')';
    context.fill();
     
    // draw inner circle
    context.beginPath();
    context.arc(
    this.width / 2,
    this.height / 2,
    radius,
    0,
    Math.PI * 2
    );
    context.fillStyle = 'rgba(255, 100, 100, 1)';
    context.strokeStyle = 'white';
    context.lineWidth = 2 + 4 * (1 - t);
    context.fill();
    context.stroke();
     
    // update this image's data with data from the canvas
    this.data = context.getImageData(
    0,
    0,
    this.width,
    this.height
    ).data;
     
    // continuously repaint the map, resulting in the smooth animation of the dot
    map.triggerRepaint();
     
    // return `true` to let the map know that the image was updated
    return true;
    }
    };
     
    map.on('load', function() {
    map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });
     
    map.addSource('points', {
    'type': 'geojson',
    'data': {
    'type': 'FeatureCollection',
    'features': [
    {
    'type': 'Feature',
    'geometry': {
    'type': 'Point',
    'coordinates': [0, 0]
    }
    }
    ]
    }
    });
    map.addLayer({
    'id': 'points',
    'type': 'symbol',
    'source': 'points',
    'layout': {
    'icon-image': 'pulsing-dot'
    }
    });
    });
    </script>
     
    </body>
    </html>
    

    修改示例

    在我们自定义HTML或Canvas时,只需更改上述示例中的pulsingDot即可。下面我们修改一个扇形扫描的效果。

    var pulsingDot= {
          width: size,
          height: size,
          data: new Uint8Array(size * size * 4),
          // get rendering context for the map canvas when layer is added to the map
          onAdd: function () {
            let canvas = document.createElement('canvas');
            canvas.width = this.width;
            canvas.height = this.height;
            this.context = canvas.getContext('2d');
          },
    
          // called once before every frame where the icon will be used
          render: function () {
            let t = (performance.now() % duration) / duration;
    
            let radius = (size / 2) * 0.3;
            let outerRadius = (size / 2) * 0.7 * t + radius;
            let context = this.context;
            context.clearRect(0, 0, this.width, this.height);
            context.beginPath();
            context.arc(
              this.width / 2,
              this.height / 2,
              outerRadius,
              0,
              Math.PI * 2
            );
            context.fillStyle = 'rgba(' + colorList[0] + ',' + colorList[1] + ',' + colorList[2] + ',' + (1 - t) + ' )';
            context.fill();
    
            // draw inner circle
            context.beginPath();
            context.arc(
              this.width / 2,
              this.height / 2,
              radius,
              0,
              Math.PI * 2
            );
            this.data = context.getImageData(
              0,
              0,
              this.width,
              this.height
            ).data;
    
            // continuously repaint the map, resulting in the smooth animation of the dot
            map.triggerRepaint();
    
            // return `true` to let the map know that the image was updated
            return true;
          }
        };
    

    扫描下方二维码,关注微信公众号,精彩内容同步更新,有问题可随时交流

    微信公众号

    相关文章

      网友评论

        本文标题:MapBox GL融合Canvas制作动态效果

        本文链接:https://www.haomeiwen.com/subject/qwqjdhtx.html