前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于geojson-vt和canvas的高性能出图

基于geojson-vt和canvas的高性能出图

作者头像
lzugis
发布2023-10-19 14:30:09
2150
发布2023-10-19 14:30:09
举报

概述

本文介绍基于geojson-vtcanvas,实现node端高性能出图。

效果

性能
性能

实现

1. canvas绘图

代码语言:javascript
复制
import { createCanvas } from 'canvas'

const tileSize = 256;
const canvas = createCanvas(tileSize, tileSize)
const ctx = canvas.getContext('2d')

2. 处理geojson

代码语言:javascript
复制
const geojson = result.rows[0].geojson;
geojson.features = geojson.features || []
const tileIndex = geojsonvt(geojson, {
    maxZoom: 22,
    tolerance: 3, // simplification tolerance (higher means simpler)
    extent: 4096, // tile extent (both width and height)
    buffer: 64,   // tile buffer on each side
    debug: 0,     // logging level (0 to disable, 1 or 2)
    lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features
    promoteId: null,    // name of a feature property to promote to feature.id. Cannot be used with `generateId`
    generateId: false,  // whether to generate feature ids. Cannot be used with `promoteId`
    indexMaxZoom: 5,       // max zoom in the initial tile index
    indexMaxPoints: 100000 // max number of points per tile in the index
})
const features = tileIndex.getTile(Number(z), Number(x), Number(y))?.features || [];

3. 绘制features

代码语言:javascript
复制
function drawTile(features, zoom) {
    ctx.clearRect(0, 0, tileSize, tileSize);
    // 绘制边框
    // ctx.strokeStyle = '#fff'
    // ctx.lineWidth = 1
    // ctx.strokeRect(0, 0, tileSize, tileSize)
    for (let i = 0; i < features.length; i++) {
        const feature = features[i];
        const {adcode, name} = feature.tags
        const type = feature.type;
        ctx.beginPath();
        for (let j = 0; j < feature.geometry.length; j++) {
            const geom = feature.geometry[j];
            if (type === 1) { // 1点
                ctx.save()
                ctx.fillStyle = `rgba(${'255,0,0'}, 1)`;
                ctx.strokeStyle = '#fff'
                ctx.lineWidth = 2;
                ctx.textAlign = "center";
                ctx.textBaseline = "middle"
                ctx.font = "bold 16px 宋体";
                // const len = ctx.measureText(name).width / 2;
                // const offset = 5
                // if(x + len > tileSize) x = tileSize - len - offset
                // if(x - len < 0 ) x = len + offset
                if(name && zoom >= 9) {
                    ctx.strokeText(name, geom[0] / 16.0, geom[1] / 16.0)
                    ctx.fillText(name, geom[0] / 16.0, geom[1] / 16.0)
                }
                // ctx.arc(geom[0] / 16.0, geom[1] / 16.0, 3, 0, 2 * Math.PI, false);
                ctx.restore()
                ctx.fill()
                ctx.stroke()
            } else { // 2线 或 3面
                // const color = colorDict[adcode] || '255,0,0'
                const color = '255,0,0'
                ctx.strokeStyle = `rgba(${color}, 1)`;
                ctx.fillStyle = `rgba(${color}, 0.1)`;
                ctx.lineWidth = 1;
                for (let k = 0; k < geom.length; k++) {
                    const p = geom[k];
                    if (k) ctx.lineTo(p[0] / 16.0, p[1] / 16.0);
                    else ctx.moveTo(p[0] / 16.0, p[1] / 16.0);
                }
                // if (type === 3) ctx.fill();
                ctx.stroke();
            }
        }
    }
}

4. 设置缓存并发送到前端

代码语言:javascript
复制
app.get('/tile/:z/:x/:y', (req, res) => {
    const {z, x, y} = req.params
    try {
        getFeatures(x, y, z).then(image => {
            res.setHeader('Expires', new Date(Date.now() + 30 * 1000).toUTCString())
            res.writeHead(200, {
                "Content-Type": "image/png",
            });
            res.end(image);
        })
    } catch (err) {
        console.error(err);
    }   
})

5. 数据获取

数据是存在PG数据库中,可通过node连接获取,可通过如下语句直接将结果转换为geojson。

代码语言:javascript
复制
SELECT json_build_object(
   'type', 'FeatureCollection',
   'features', json_agg(ST_AsGeoJSON(t.*)::json)
) as geojson FROM (
   select adcode, name, geom from base_county where st_intersects(BBox(101, 52, 7), geom)
) as t(adcode, name, geom);
image.png
image.png

6. 前端调用

代码语言:javascript
复制
new ol.layer.Tile({
  source: new ol.source.XYZ({
      url: 'http://127.0.0.1:18089/tile/{z}/{x}/{y}'
  })
}),
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 效果
  • 实现
    • 1. canvas绘图
      • 2. 处理geojson
        • 3. 绘制features
          • 4. 设置缓存并发送到前端
            • 5. 数据获取
              • 6. 前端调用
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档