三十八、openlayers官网示例Earthquakes with custom symbols——将矢量数据渲染为自定义图形

官网demo地址:

Earthquakes with custom symbols 

上一篇我们使用星星表示了地震数据,能绘制星星图形主要依靠 openlayers中的RegularShape类,那如果想要绘制自定义图形该怎么写呢,这篇提供了解决方案。

const vector = new VectorLayer({
      source: new VectorSource({
        url: "https://openlayers.org/en/latest/examples/data/kml/2012_Earthquakes_Mag5.kml",
        format: new KML({
          extractStyles: false,
        }),
      }),
      style: styleFunction,
    });

依然是通过样式函数styleFunction设置图形。

styleCache做了一个缓存,以免每次都要重新生成。

从feature中获取自定义属性地震等级大小name决定图形大小。

 const styleFunction = function (feature) {
      const name = feature.get("name");
      const magnitude = parseFloat(name.substr(2));
      const size = parseInt(10 + 40 * (magnitude - 5), 10);
      scale = size / 10;
      let style = styleCache[size];
      if (!style) {
        
        styleCache[size] = style;
      }
      return style;
    };

symbol 是一个坐标数组,定义了一个多边形的形状。scaleFunction 根据当前的缩放比例 scale 对每个坐标进行缩放。

    const symbol = [
      [0, 0],
      [4, 2],
      [6, 0],
      [10, 5],
      [6, 3],
      [4, 5],
      [0, 0],
    ];
    let scale;
    const scaleFunction = function (coordinate) {
      return [coordinate[0] * scale, coordinate[1] * scale];
    };

    new Polygon([symbol.map(scaleFunction)])

 修改后的某一个图形的坐标数组:

如果不修改会怎样?

如果使用缩放前的坐标,每个图形会是一样大的。

vectorContext.drawGeometry(new Polygon([symbol]));

 

在一个新的 HTML canvas 元素上绘制一个多边形,并使用这个 canvas 作为图标图像,然后创建一个样式对象。

const canvas = document.createElement("canvas");
        const vectorContext = toContext(canvas.getContext("2d"), {
          size: [size, size],
          pixelRatio: 1,
        });
        vectorContext.setStyle(
          new Style({
            fill: new Fill({ color: "rgba(255, 153, 0, 0.4)" }),
            stroke: new Stroke({ color: "rgba(255, 204, 0, 0.2)", width: 2 }),
          })
        );
        vectorContext.drawGeometry(new Polygon([symbol.map(scaleFunction)]));
        style = new Style({
          image: new Icon({
            img: canvas,
            rotation: 1.2,//设置图标的旋转角度为 1.2 弧度。
          }),
        });

toContext方法获取Canvas 的 2D 渲染上下文,使我们可以使用 OpenLayers 的矢量绘图功能在 Canvas 上绘制图形。比如setStyle、drawGeometry等方法。如果不使用toContext方法则需要使用原生canvas的方法绘制图形 

var context2D = canvas.getContext("2d");
context2D.fillStyle = "rgba(255, 153, 0, 0.4)";
context2D.fillRect(0, 0, 50, 50);

 小细节:

[symbol.map(scaleFunction)]生成出来的坐标数组并不是每个图形相对于整个canvas画布的坐标数组。而是相对于每个feature生成的画布的坐标数组。也就是说这个图形的坐标数组和feature的坐标是不一样的。它是在每个feature上再绘制了一个图形。

 

 原本的feature是已经存在的只不过没有给样式所以显示不出来,这个数组源给的是点坐标,如果在这个函数里返回一个普通的圆圈的样式页面会是这样:

// 测试代码;
      style = new Style({
        image: new CircleStyle({
          radius: 20,
          fill: new Fill({
            color: "red",
          }),
        }),
      });
      return style;

完整代码:

<template>
  <div class="box">
    <h1>Earthquakes Heatmap</h1>
    <div id="map"></div>
  </div>
</template>

<script>
import KML from "ol/format/KML.js";
import Map from "ol/Map.js";
import Polygon from "ol/geom/Polygon.js";
import StadiaMaps from "ol/source/StadiaMaps.js";
import VectorSource from "ol/source/Vector.js";
import View from "ol/View.js";
import { Fill, Icon, Stroke, Style, Circle as CircleStyle } from "ol/style.js";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer.js";
import { toContext } from "ol/render.js";
export default {
  name: "",
  components: {},
  data() {
    return {
      map: null,
    };
  },
  computed: {},
  created() {},
  mounted() {
    const symbol = [
      [0, 0],
      [4, 2],
      [6, 0],
      [10, 5],
      [6, 3],
      [4, 5],
      [0, 0],
    ];
    let scale;
    const scaleFunction = function (coordinate) {
      return [coordinate[0] * scale, coordinate[1] * scale];
    };

    const styleCache = {};
    const styleFunction = function (feature) {
      const name = feature.get("name");
      const magnitude = parseFloat(name.substr(2));
      const size = parseInt(10 + 40 * (magnitude - 5), 10);
      scale = size / 10;
      let style = styleCache[size];
      if (!style) {
        const canvas = document.createElement("canvas");
        const vectorContext = toContext(canvas.getContext("2d"), {
          size: [size, size],
          pixelRatio: 1,
        });
        vectorContext.setStyle(
          new Style({
            fill: new Fill({ color: "rgba(255, 153, 0, 0.4)" }),
            stroke: new Stroke({ color: "rgba(255, 204, 0, 0.2)", width: 2 }),
          })
        );
        vectorContext.drawGeometry(new Polygon([symbol.map(scaleFunction)]));
        //测试代码
        // var context2D = canvas.getContext("2d");
        // context2D.fillStyle = "rgba(255, 153, 0, 0.4)";
        // context2D.fillRect(0, 0, 50, 50);
        style = new Style({
          image: new Icon({
            img: canvas,
            rotation: 1.2, //设置图标的旋转角度为 1.2 弧度。
          }),
        });
        styleCache[size] = style;
      }
      // 测试代码;
      //   style = new Style({
      //     image: new CircleStyle({
      //       radius: 20,
      //       fill: new Fill({
      //         color: "red",
      //       }),
      //     }),
      //   });
      return style;
    };

    const vector = new VectorLayer({
      source: new VectorSource({
        url: "https://openlayers.org/en/latest/examples/data/kml/2012_Earthquakes_Mag5.kml",
        format: new KML({
          extractStyles: false,
        }),
      }),
      style: styleFunction,
    });

    const raster = new TileLayer({
      source: new StadiaMaps({
        layer: "stamen_toner",
      }),
    });

    const map = new Map({
      layers: [raster, vector],
      target: "map",
      view: new View({
        center: [0, 0],
        zoom: 2,
      }),
    });
  },
  methods: {},
};
</script>

<style lang="scss" scoped>
#map {
  width: 100%;
  height: 500px;
}
.box {
  height: 100%;
}
</style>

 

  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值