Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心基类

  • Control控件篇

  • Geom几何图形篇

  • Layer图层篇

  • Renderer篇

    • VectorContext类
    • Build类
    • TextBuilder类
    • BuilderGroup类
    • PolygonBuilder类
    • LineStringBuilder类
      • 概述
      • 源码分析
        • LineStringBuilder类的源码实现
        • LineStringBuilder类的构造函数
        • LineStringBuilder类的主要方法
      • 总结
    • ImageBuilder类
    • renderFeature介绍
    • CanvasLayerRenderer类
    • LayerRender类
  • Feature篇

  • style样式篇

  • 《Openlayers源码》笔记
  • Renderer篇
东流
2025-01-11
目录

LineStringBuilder类

# 概述

在 Openlayers 中,CanvasLineStringBuilder类用于构建绘制线段指令集的构建器,它继承于CanvasBuilder类,关于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);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

# 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_去构建绘制路径的指令,并将指令添加到绘制指令集中。

编辑 (opens new window)
上次更新: 2025/01/13, 10:21:25
PolygonBuilder类
ImageBuilder类

← PolygonBuilder类 ImageBuilder类→

最近更新
01
GeoJSON
05-08
02
Circle
04-15
03
CircleMarker
04-15
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式