图片标注编辑平台搭建系列教程(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架构。

相关推荐
Jackson__2 分钟前
AI时代,前端开发者到底还剩下什么?又该往哪里走?
前端·ai编程
C澒24 分钟前
微前端容器标准化:容器标准化演进
前端·架构
卖报的大地主25 分钟前
Learn Claude Code Agent 开发 | 2、插拔式工具系统:扩展功能不修改核心循环
前端·chrome
qzhqbb41 分钟前
Web 服务器(Nginx、Apache)
服务器·前端·nginx
天若有情6731 小时前
前端进阶必看:吃透这些高阶知识,告别CRUD,迈向高级前端工程师
前端·状态模式
_长银1 小时前
Sublime Text保持只打开一个
编辑器·sublime text
coderYYY1 小时前
git push报错Authentication failed for ‘xxx’也不会弹要求输入用户名密码的最终解决方法
前端·git·gitee·github
l1t2 小时前
QWen 3.5plus总结的总结基准测试结果的正确方法
前端·数据库
kyriewen112 小时前
为什么我的代码在测试环境跑得好好的,一到用户电脑就崩?原来凶手躲在地址栏旁边
开发语言·前端·javascript·chrome·ecmascript·html5
小北方城市网2 小时前
JavaScript 实战 —— 实现一个简易的 TodoList(适合前端入门 / 进阶)
开发语言·前端·javascript