# 示例:生成并使用矢量瓦片

对于一些数据量较大的数据,完全动态的渲染会消耗较多的计算和 IO 资源,这个时候可以考虑生成矢量瓦片来加速渲染的速度,甚至可以完全在浏览器中进行渲染。

注意,目前矢量瓦片集只支持生成为互联网常见的 Google 分级定义下的 Web Mercator 数据。

# 1. 创建矢量瓦片集

矢量瓦片集是 HeyCloud 中管理矢量瓦片的数据格式,通过管理控制台都可以很容易地创建一个矢量瓦片集:

# 2. 根据渲染配置生成矢量瓦片数据

点击「生成瓦片」按钮,会弹出设置渲染配置等参数的窗口:

在这个例子中,我们选择一个包含有大量多边形的矢量数据集「ec98ed9b-838c-4247-98d0-f95aaf356fb9」作为数据源进行图层渲染。

{
  "type": "layer",
  "config": {
    "datasource": {
      "name": "blocks",
      "type": "vdataset",
      "source": "ec98ed9b-838c-4247-98d0-f95aaf356fb9"
    },
    "style": {
      "type": "polygon-simple",
      "fillColor": "#f00",
      "fillOpacity": 0.6,
      "outlineColor": "#fff",
      "outlineWidth": 1
    }
  }
}

注意,这个配置对象首先是指定type可选值为layermap,分别对应渲染引擎中的单图层渲染和多图层的地图渲染;在config中设置的是对应类型的渲染配置。另外,数据源一定要指定name属性,这个属性用于在矢量瓦片中区分不同的图层数据,这样才可以在矢量瓦片最终渲染时进行样式的修改。

其它参数如地图范围、生成级别等设置成功后,点击「确认」按钮开始生成矢量瓦片数据,按钮会切换状态,显示生成的进度,并可以随时中止生成操作:

# 3. 使用矢量瓦片进行服务端渲染

HeyCloud 的渲染引擎支持直接使用矢量瓦片集作为渲染数据源,在管理控制台中的矢量瓦片集预览就是采用了这种方法。渲染时,首先 POST 一个渲染配置请求到/api/render/tiles

{
  "datasource": {
    "type": "vtileset",
    "source": "f6cf43c0-072b-4a50-ac52-4d6cb7c075d6"
  },
  "vtileConfig": {
    "layers": [
      {
        "data": "shape",
        "style": {
          "type": "polygon-simple",
          "fillColor": "#f00",
          "fillOpacity": 0.6,
          "outlineColor": "#fff",
          "outlineWidth": 1
        }
      }
    ]
  }
}

这会返回一个渲染配置的uid,根据这个uid就可以获取渲染结果,例如:/api/render/tiles/74b68de5243784fd7120d809cfd31e1d/6/45/24/2/image.webp。需要注意的是,这个例子中指定渲染的数据名为shape,代表的这个图层数据的形状;如果生成矢量瓦片的时候还指定了标注,那么可以通过label这个数据名指定标注的渲染样式。

这是渲染的效果:

# 4. 使用矢量瓦片进行客户端渲染

矢量瓦片也可以直接用于在浏览器中进行渲染,在改变显示样式方面更加灵活。

新建一个名为vtile-viz.html的文件,内容如下:

<!DOCTYPE html>
<html>
  <meta charset="utf-8" />

  <head>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css"
      type="text/css"
    />
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  </head>

  <body>
    <div id="app">
      <div id="map" style="width: 600px; height: 600px"></div>
    </div>

    <script>
      var app = new Vue({
        el: '#app',
        data: {
          map: null,

          accountId: '3897a3d3-3d32-4b6d-a138-489657278b70',
          vtilesetId: 'f6cf43c0-072b-4a50-ac52-4d6cb7c075d6',
        },

        mounted() {
          this.map = new ol.Map({
            target: 'map',
            view: new ol.View({
              center: ol.proj.fromLonLat([110, 35]),
              zoom: 7,
            }),
            layers: [
              new ol.layer.VectorTile({
                source: new ol.source.VectorTile({
                  format: new ol.format.MVT(),
                  url: `http://localhost:9000/heycloud/api/data/vtileset/${this.vtilesetId}/{z}/{x}/{y}?x-heycloud-account-id=${this.accountId}`,
                  crossOrigin: '*',
                }),
                style: function(feature, resolution) {
                  switch (feature.get('layer')) {
                    case 'shape':
                      return new ol.style.Style({
                        stroke: new ol.style.Stroke({
                          color: '#fff',
                          width: 1,
                        }),
                        fill: new ol.style.Fill({
                          color: '#aaa',
                        }),
                      });
                  }
                },
              }),
            ],
          });
        },
      });
    </script>
  </body>
</html>

页面将会呈现这样的效果:

在这里矢量瓦片的渲染样式通过style函数控制,通过改变这个函数的定义就可以很容易地切换渲染的样式,比如将渲染填充色改成蓝色,描边改成红色:

style: function(feature, resolution) {
  switch (feature.get('layer')) {
    case 'shape':
      return new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#f00',
          width: 1,
        }),
        fill: new ol.style.Fill({
          color: '#00f',
        }),
      });
  }
}

页面显示效果就会变成如下的样子: