访问Openlayers网站(https://jinuss.github.io/Openlayers_map_pages/,网站是基于
Vue3
+Openlayers
,里面有大量的实践和案例。觉得还不错,可以 给个小星星Star,鼓励一波 https://github.com/Jinuss/OpenlayersMap哦~
概述
在 Openlayers 中,CanvasLineStringBuilder
类用于构建绘制线段指令集的构建器,它继承于CanvasBuilder
类,关于CanvasBuilder
类,可以参考这篇文章源码分析之Openlayers中CanvasBuilder类
本文主要介绍CanvasLineStringBuilder
类构建绘制线段指令集的过程以及源码分析。
源码分析
LineStringBuilder
类的源码实现
LineStringBuilder
类的源码实现如下:
class CanvasLineStringBuilder extends CanvasBuilder {
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super(tolerance, maxExtent, resolution, pixelRatio);
}
drawFlatCoordinates_(flatCoordinates, offset, end, stride) {
const myBegin = this.coordinates.length;
const myEnd = this.appendFlatLineCoordinates(
flatCoordinates,
offset,
end,
stride,
false,
false
);
const moveToLineToInstruction = [
CanvasInstruction.MOVE_TO_LINE_TO,
myBegin,
myEnd,
];
this.instructions.push(moveToLineToInstruction);
this.hitDetectionInstructions.push(moveToLineToInstruction);
return end;
}
drawLineString(lineStringGeometry, feature, index) {
const state = this.state;
const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth;
if (strokeStyle === undefined || lineWidth === undefined) {
return;
}
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(lineStringGeometry, feature, index);
this.hitDetectionInstructions.push(
[
CanvasInstruction.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset,
],
beginPathInstruction
);
const flatCoordinates = lineStringGeometry.getFlatCoordinates();
const stride = lineStringGeometry.getStride();
this.drawFlatCoordinates_(
flatCoordinates,
0,
flatCoordinates.length,
stride
);
this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(feature);
}
drawMultiLineString(multiLineStringGeometry, feature, index) {
const state = this.state;
const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth;
if (strokeStyle === undefined || lineWidth === undefined) {
return;
}
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(multiLineStringGeometry, feature, index);
this.hitDetectionInstructions.push(
[
CanvasInstruction.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset,
],
beginPathInstruction
);
const ends = multiLineStringGeometry.getEnds();
const flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
const stride = multiLineStringGeometry.getStride();
let offset = 0;
for (let i = 0, ii = ends.length; i < ii; ++i) {
offset = this.drawFlatCoordinates_(
flatCoordinates,
offset,
ends[i],
stride
);
}
this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(feature);
}
finish() {
const state = this.state;
if (
state.lastStroke != undefined &&
state.lastStroke != this.coordinates.length
) {
this.instructions.push(strokeInstruction);
}
this.reverseHitDetectionInstructions();
this.state = null;
return super.finish();
}
applyStroke(state) {
if (
state.lastStroke != undefined &&
state.lastStroke != this.coordinates.length
) {
this.instructions.push(strokeInstruction);
state.lastStroke = this.coordinates.length;
}
state.lastStroke = 0;
super.applyStroke(state);
this.instructions.push(beginPathInstruction);
}
}
LineStringBuilder
类的构造函数
LineStringBuilder
类的构造函数比较通用,接受以下参数:
-
tolerance
:容差,通常用于指定绘制精度或容许的误差范围。 -
maxExtent
:最大范围,用来限制图形的显示范围。 -
resolution
:地图的分辨率。 -
pixelRatio
:像素比率,用来处理不同屏幕或设备的显示效果。
LineStringBuilder
类的主要方法
drawFlatCoordinates_(flatCoordinates,offset,end,stride)
方法
drawFlatCoordinates_
方法接受四个参数:flatCoordinates
坐标数组、offset
起始位置、end
线段结束位置和stride
步幅。drawFlatCoordinates
方法会以this.coordinates.length
的长度为起始位置,当绘制一条线段时,此时this.coordinates
为空数组,起始位置就是0
;当之前绘制过线段时,起始位置就是上一条线段的结束位置+1
;然后会调用父类的this.appendFlatLineCoordinates
方法计算出结束位置,为end
,此举也会改变this.coordinates
。然后构建绘制指令,类型为CanvasInstruction.MOVE_TO_LINE_TO
,将指令添加到指令集中,最后返回end
值,如果绘制多线段时,则end
值为下次构建绘制线段指令的offset
值。
drawLineString(lineStringGeometry,feature,index)
方法
drawLineString
方法用于绘制一条线段,接受三个参数:lineStringGeometry
线段几何对象、feature
要素和index
索引。首先会从this.state
上取样式,若未设置,则直接返回;然后调用this.updateStrokeStyle
方法,并且第二个参数是this.applyStroke
方法,this.updateStrokeStyle
方法的作用就是更新this.state
并且调用第二个参数构建样式指令,并将它添加到指令集中;再调用this.beginGeometry
添加开始绘制几何图形的指令以及构建CanvasInstruction.SET_STROKE_STYLE
的指令添加到碰撞检测指令集中,然后从几何对象lineStringGeometry
上取坐标数据,再调用this.drawFlatCoordinates_
方法构建绘制路径(或线段)的指令,后面就是添加边框样式指令strokeInstruction
添加到碰撞检测指令集中;最后调用this.endGeometry
方法构建绘制结束指令并将其添加到指令集中。
drawMultiLineString(multiLineStringGeometry,feature,index)
方法
drawMultiLineString
方法和drawLineString
方法极其类似,不同的就是从几何对象上取坐标的方式不同,并且drawMultiLineString
方法会多次调用this.drawFlatCoordinates_
内部方法,而后者只需要调用一次。
finish
方法
finish
方法会结束当前的绘制操作,检查state.stroke
,判断当前的坐标数量是否与state.stroke
一致,若不一致,则需要添加一个新的的绘制指令strokeInstruction
,然后反转 碰撞检测指令集,最后清空状态,调用父类的finish
方法获取构建的绘制指令集。
applyStroke
方法
applyStroke
方法就是应用当前的描边(绘制)样式,根据当前坐标与上次绘制的比较来决定是否需要添加新的绘制指令,更新状态,最后会新增一个beginPathInstruction
指令,该指令表示开始绘制线段。
总结
本文主要介绍了CanvasLineStringBuilder
类的核心原理,针对多线段MultiLineString
和单线段LineString
实现的原理和思路大致相同,核心都是调用内部方法drawFlatCoordinates_
去构建绘制路径的指令,并将指令添加到绘制指令集中。