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

相关推荐
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
mosquito_lover16 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
柴柴的小记8 小时前
前端vue引入特殊字体不生效
前端·javascript·vue.js
Aphelios3809 小时前
Linux 下 VIM 编辑器学习记录:从基础到进阶(上)
java·linux·编辑器·vim
柠檬豆腐脑9 小时前
从前端到全栈:新闻管理系统及多个应用端展示
前端·全栈