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

相关推荐
前端郭德纲37 分钟前
浅谈React的虚拟DOM
前端·javascript·react.js
2401_879103682 小时前
24.11.10 css
前端·css
ComPDFKit2 小时前
使用 PDF API 合并 PDF 文件
前端·javascript·macos
yqcoder3 小时前
react 中 memo 模块作用
前端·javascript·react.js
优雅永不过时·3 小时前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
神夜大侠6 小时前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱6 小时前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
柯南二号6 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72936 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲7 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6