动态改变地图元素的样式

Changing style of map elements dynamically

我试图即时更改一些地图元素的样式,但没有成功。我的意思是动态更改地图元素的颜色,例如,从计算颜色动态更改水团。使用 Tangram,但如果有更好的解决方案,则对其他引擎开放。由于 Tangram 使用 YAML 文件来设置各种元素的样式,因此我在场景 (YAML) 文件中使用内联 Javascript。换句话说,我不想给它一个固定的颜色,而是想计算颜色(来自图像)。而不是这个:

 water:
    draw:
        polygons:
            color: "blue"

我正在按照这些思路做一些事情(因为我使用的是 Vue Router 而变得更复杂):

 water:
    draw:
        polygons:
            color: function() { return this.colors[0]; }

computedColorsmixing中计算,然后广播到合适的路由:

var colorize = {

    data: function () {
        return {
            computedColors: []
        };
    },

    created: function () {
        this.getColors();
    },

    methods: {
        getColors: function () {
            ...
            self.computedColors = [
              ...
            ];
          self.$broadcast('parent-colors', self.computedColors);
          ...
        };
    };
}

这是路线:

router.map({
'/map': {

    name: 'map',

    component: Vue.extend({

        template: '#map',

        mixins: [colorize],

        data: function () {
            return {
                colors: []
            };
        },

        events: {
            'parent-colors': function (computedColors) {
                this.colors = computedColors;
            }
        },
    ready: {
        var map = L.map('map');
        var layer = Tangram.leafletLayer({
           scene: './tiles/scene.yaml'
        });
        layer.addTo(map);
        map.setView([40.70531887544228, -74.00976419448853], 15);
    }
});

感谢任何关于我可能做错的提示。


更新

我遇到了一些错误。它与七巧板有关,但不太清楚它到底是什么。似乎是 YAML 文件的解析问题。如果我在 scene.yaml:

中更改它
 water:
    draw:
        polygons:
            color: function() { return this.colors[0]; }

有了这个:

 water:
    draw:
        polygons:
            color: function() { return this.color1; }

我没有收到任何错误,但不幸的是,水团仍然没有分配任何颜色。

当然,我也必须更改地图路线实例中的这些行:

 data: function () {
            return {
                color1: ''
            };
        },
 ...

 events: {
     'parent-colors': function (computedColors) {
         this.color1 = computedColors[0];
     }
 }

以下内容并未提供针对动态设置 Tangram 地图样式的特定问题的解决方案(Yaml 似乎不容易允许),但它部分回答了如何动态设置地图矢量样式的问题.它实现了插件 Leaflet.VectorGrid and assigns properties to layers programmatically through the vectorTileLayerStyles 方法(在下面的示例中使用 color: self.colors[6] 完成)。

        L.vectorGrid.slicer(countries, {
        rendererFactory: L.svg.tile,
        vectorTileLayerStyles: {
            sliced: function() {
                return {
                stroke: true,
                color: self.colors[6],
                weight: 0.5,
                };
            }
        },
        }).addTo(map);

变量 countries 实际上只是一个 GeoJson 添加了 var countries =,大致如下:

var countries = {
    "type": "FeatureCollection",
    "features": [
        { "type": "Feature"
        (...)
        }
    ]
};

这是一个简单的解决方案,它可以完美地处理少量数据,但由于它是一个客户端解决方案,因此在处理更大的数据集时浏览器会很繁重。尽管如此,对于那些可能正在寻找一种简单的方法来动态地设计简化的世界地图或有限地图区域的人来说,它可能还是有用的。


更新

一种更高效的解决方案是使用磁贴服务器。下面的例子实现了 t-rex, with canvas renderer L.canvas.tile in the rendererFactory option instead of L.svg.tile and protobuf:

  var lines = "http://127.0.0.1:6767/lines/{z}/{x}/{y}.pbf";
  var multilinestrings = "http://127.0.0.1:6767/multilinestrings/{z}/{x}/{y}.pbf";
  var multipolygons = "http://127.0.0.1:6767/multipolygons/{z}/{x}/{y}.pbf";

  var vectorTileStyling = {
      lines: {
          weight: .8,
          fillColor: this.colors[1],
          color: this.colors[1],
          fillOpacity: .8,
          opacity: .8
      },
      multilinestrings: {
          weight: .8,
          fillColor: this.colors[2],
          color: this.colors[2],
          fillOpacity: .8,
          opacity: .8
      },
      multipolygons: {
          fill: true,
          weight: .8,
          fillColor: this.colors[3],
          color: this.colors[3],
          fillOpacity: .8,
          opacity: .8,
      }
  };

  var externalVectorTileOptions = {
      rendererFactory: L.canvas.tile,
      vectorTileLayerStyles: vectorTileStyling,
      maxZoom: 16,
      minZoom: 14
  };
  L.vectorGrid.protobuf(lines, externalVectorTileOptions).addTo(map);
  L.vectorGrid.protobuf(multilinestrings, externalVectorTileOptions).addTo(map);
  L.vectorGrid.protobuf(multipolygons, externalVectorTileOptions).addTo(map);