图片标注编辑平台搭建系列教程(8)——osmEntity转为fabric.Object

背景

上一章我们讲过,当标注平台解析完数据后,会把数据存入Graph,数据格式为osmEntity。为了渲染出osmEntity,我们还需要将osmEntity转换为fabric.Object的格式。本章介绍这一步的具体实现以及一些坑。

转换原理

我们知道,osmEntity具有geometry属性,这个属性是一个标准的Geometry格式。即

复制代码
{
    type: 'Point',
    coordinates: [10, 10]
}

对于fabric.Object而言,geometry是无法直接使用的,需要进行转换。而且不同的Object需要的参数有些许差异。转换的伪代码如下:

javascript 复制代码
class osmEntity {
    // osmEntity转fabric.Object
    toFabricObject() {
        let object = null;
        const options = this.toFabricCoordinate();
        switch(type) {
            case 'Point': 
                object = new NPoint(options);
            ;
            case 'Polyline': ;
            case 'Polygon': ;
            case 'Rectangle': ; 
        }
        return object;
    },
    // 坐标转换
    toFabricCoordinate() {
        // ...
    }
}

NPoint继承自fabric.Circle,其坐标参数为:

复制代码
{
    left: 10,
    top: 10
}

因此,其toFabricCoordinate可写为:

javascript 复制代码
toFabricCoordinate() {
    const loc = this.geometry.coordinates;
    return {left: this.loc[0], top: this.loc[1]};
}

线

NPolyline继承自fabric.Polyline,其坐标参数为:

javascript 复制代码
{
    left: 10,
    top: 10,
    points: [{x: 0, y: 0}, {x: 5, y: 0}]
}

这边注意找到线的最小外界矩形的左上角点,所有点都转为以该点为坐标原点。

javascript 复制代码
toFabricCoordinate(){
    let result;
    const coordinates = this.geometry.coordinates;
    const extent = bbox(this.geometry);
    result.left = extent[0];
    result.top = extent[1];
    result.points = coordinates.map((p) => {
        return { x: p[0] - extent[0], y: p[1] - extent[1] };
    });
    return result;
}

矩形

NRectangle继承自fabric.Rect,其参数为:

javascript 复制代码
{
    left: 10,
    top: 10,
    width: 100,
    height: 100
}

同样地,转换函数为:

javascript 复制代码
toFabricCoordinate(){
    let result;
    const extent = bbox(this.geometry); // 矩形的geometry存的是polygon
    return {
        left: extent[0],
        top: extent[1],
        width: extent[2] - extent[0],
        height: extent[3] - extent[1]
    }
}

多边形

NPolygon继承自fabric.Path,其参数如下:

javascript 复制代码
{
    path: 'M 10 10 Z',
    left: 10,
    top: 10
}

这里我们需要一个方法将geojson转为svg path的方法。这里参考一些开源仓库,写法如下:

javascript 复制代码
toFabricCoordinate(){
    const extent = bbox(this.geometry);
    let result;
    result.left = extent[0];
    result.top = extent[1];
    let mainStr, holes;
    // 多边形外环
    mainStr = this.getCoordString(coordinates[0], result.left as number, result.top as number);
    // 多边形孔洞
    if (coordinates.length > 1) {
        holes = coordinates.slice(1, coordinates.length);
    }
    let path = 'M' + mainStr;
    if (holes) {
        for (var i = 0; i < holes.length; i++) {
           path += ' M' + this.getCoordString(holes[i], result.left as number, result.top as number);
        }
    }
    path += 'Z';
    result.path = fabric.util.makePathSimpler(fabric.util.parsePath(path)); // string转数组,参考fabric源码
    return result;
},
getCoordString(coords, left, top) {
    let coordStr = coords.map((coord) => coord[0] - left + ',' + (coord[1] - top));
    return coordStr.join(' ');
}

预告

下一章,我们讲讲编辑器里解决性能问题常用的sketchLayer架构。

相关推荐
勇往直前plus13 分钟前
Vue3(篇一) 核心概念——响应式模板语法与组件基础
前端·javascript·vue.js
咩咩啃树皮23 分钟前
第43篇:Vue3计算属性(computed)完全精讲——缓存机制、依赖计算、业务最优解
前端·vue.js·缓存
徐小夕2 小时前
花了一周,3亿tokens,我开源了一款 Word 文档智能审查平台,文稿自动质检+可视化分析,告别低效人工审核
前端·算法·github
kyriewen4 小时前
别再乱用useEffect了——你写的10个里有8个不该存在
前端·javascript·react.js
Ivanqhz4 小时前
Rust &‘static str浅析
java·前端·javascript·rust
IT_陈寒4 小时前
SpringBoot这个分页坑,我踩了三天才爬出来
前端·人工智能·后端
颜酱4 小时前
05 | 召回前置准备:根据业务数据库生成各数据库(读取配置阶段)
前端·人工智能·后端
zandy10115 小时前
衡石 Agentic BI的ReAct 推理框架在 Agentic BI 中的工程化实践
前端·javascript·react.js
罗超驿5 小时前
JavaEE进阶之路:从Web架构原理到HTML标签全解析
前端·html·web·javaee
西安小哥5 小时前
从前端到AI工程师:一场跨越鸿沟的真实蜕变之旅
前端