背景
上一章我们讲过,当标注平台解析完数据后,会把数据存入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架构。