[WebGIS example] (8) MapboxGL draws flashing points

Official website example: Add an animated icon to the map | Mapbox GL JS

Please add a picture description

accomplish

sample data

const sampleData = {
    
    
  "type": "FeatureCollection",
  "features": [
    {
    
    
      "type": "Feature",
      "properties": {
    
    },
      "geometry": {
    
    
        "coordinates": [
          112.58261709330202,
          22.76596784315703
        ],
        "type": "Point"
      }
    },
    {
    
    
      "type": "Feature",
      "properties": {
    
    },
      "geometry": {
    
    
        "coordinates": [
          113.59425670069453,
          23.67775776441485
        ],
        "type": "Point"
      }
    },
    {
    
    
      "type": "Feature",
      "properties": {
    
    },
      "geometry": {
    
    
        "coordinates": [
          114.37244101407515,
          23.249455907195042
        ],
        "type": "Point"
      }
    }
  ]
}

main content

// !引入地图对象 const map = new mapboxgl.Map({
    
    {...}) 的那个
import map from "../creatMap.js"; 

export class AnimatedPoint {
    
    
  constructor() {
    
    
    const size = 200;
    const pulsingDot = {
    
    
      width: size,
      height: size,
      data: new Uint8Array(size * size * 4),

      // When the layer is added to the map,
      // get the rendering context for the map canvas.
      onAdd: function () {
    
    
        const canvas = document.createElement('canvas');
        canvas.width = this.width;
        canvas.height = this.height;
        this.context = canvas.getContext('2d');
      },

      // Call once before every frame where the icon will be used.
      render: function () {
    
    
        const duration = 1000;
        const t = (performance.now() % duration) / duration;

        const radius = (size / 2) * 0.3;
        const outerRadius = (size / 2) * 0.7 * t + radius;
        const context = this.context;

        // Draw the 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 the 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.addImage('pulsing-dot', pulsingDot, {
    
     pixelRatio: 1 });
  }

  // 绘制点
  drawPoint(features) {
    
    
    // 如果已经存在名为animatedPoint的数据源了,就更新数据
    // 否则就新建一个数据源和图层
    if (map.getSource('animatedPoint')) {
    
    
      map.getSource('animatedPoint').setData({
    
    
        type: "FeatureCollection",
        features: features,
      });
    } else {
    
    
      map.addSource('animatedPoint', {
    
    
        type: "geojson",
        data: features
      })
      map.addLayer({
    
    
        'id': 'animatedPoint', //图层ID
        'type': 'symbol', //图层类型
        'source': 'animatedPoint', //数据源
        layout: {
    
    
          'icon-image': 'pulsing-dot',
          'icon-anchor': 'center',
        },
      })
    }
  }
  
  // 移除点图层
  clearPoint() {
    
    
    if (map.getSource('animatedPoint')) {
    
    
      map.removeLayer('animatedPoint')
      map.removeSource('animatedPoint')
    }
  }
}

transfer

// 引入
import {
    
     AnimatedPoint } from './AnimatedPoint'

// 声明
window.animatedPoint = new AnimatedPoint()

// 绘制示例数据
window.animatedPoint.drawPoint(sampleData)

// 移除示例数据的图层
window.animatedPoint.clearPoint()

illustrate

Introduction to Core Objects

The core of this function is const pulsingDot = {...}this end. pulsingDotThis object represents a dynamic pulse point, which includes the following properties and methods:

  1. widthand height: represent the width and height of the pulse point respectively.
  2. data: Represents the pixel data stored in the form of a one-dimensional array for rendering animation effects.
  3. onAdd: The method used to add pulse points to the map, will create a canvas element, and set its size to be the same as the object's widthand heightattributes.
  4. render: The method used to render dynamic pulse points on the canvas. Inside the method, the progress percentage of the current time relative to the total time of a cycle is first calculated t. Next, tcalculate the size, color and border of the pulse point according to the style, and use the canvas API to draw the effect of the pulse point on the canvas. Finally copy the result into dataa property of this object and notify the map to redraw.

The effect of this dynamic pulse point is renderrealized by calling the method regularly. Each time this method is called, the effect of the pulse point is recalculated and drawn, and the pixel data ( this.data) in it is updated. After adding this object to the map, it will automatically call its onAddmethods to initialize the canvas and complete some other settings.

The final final use map.triggerRepaint()of causes the map view to do a redraw.

onAdd

onAddis a function in the Mapbox GL JS API that is a callback function that is executed when a custom map element is added to the map. When you use methods such as map.addControl, map.addSource, or map.addLayerto add a custom layer, control or source to the map, Mapbox GL JS will automatically call the onAdd()function of the element to perform some initialization settings.

Guess you like

Origin blog.csdn.net/ReBeX/article/details/130639788