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类
      • 概述
      • 源码分析
        • CanvasPolygonBuilder类的源码实现
        • CanvasPolygonBuilder类的构造函数
        • CanvasPolygonBuilder类的主要方法
      • 总结
    • LineStringBuilder类
    • ImageBuilder类
    • renderFeature介绍
    • CanvasLayerRenderer类
    • LayerRender类
  • Feature篇

  • style样式篇

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

PolygonBuilder类

# 概述

在 Openlayers 中,CanvasPolygonBuilder类是用于构造几何图形Circle、多边形Polygon和多个多边形MultiPolygon绘制指令集的构造器,CanvasPolygonBuilder类继承于CanvasBuilder类,关于CanvasBuilder类可以参考这篇文章

# 源码分析

# CanvasPolygonBuilder类的源码实现

CanvasPolygonBuilder类的源码实现如下:

class CanvasPolygonBuilder extends CanvasBuilder {
  constructor(tolerance, maxExtent, resolution, pixelRatio) {
    super(tolerance, maxExtent, resolution, pixelRatio);
  }
  setFillStrokeStyles_() {
    const state = this.state;
    const fillStyle = state.fillStyle;
    if (fillStyle !== undefined) {
      this.updateFillStyle(state, this.createFill);
    }
    if (state.strokeStyle !== undefined) {
      this.updateStrokeStyle(state, this.applyStroke);
    }
  }

  drawFlatCoordinatess_(flatCoordinates, offset, ends, stride) {
    const state = this.state;
    const fill = state.fillStyle !== undefined;
    const stroke = state.strokeStyle !== undefined;
    const numEnds = ends.length;
    this.instructions.push(beginPathInstruction);
    this.hitDetectionInstructions.push(beginPathInstruction);
    for (let i = 0; i < numEnds; ++i) {
      const end = ends[i];
      const myBegin = this.coordinates.length;
      const myEnd = this.appendFlatLineCoordinates(
        flatCoordinates,
        offset,
        end,
        stride,
        true,
        !stroke
      );
      const moveToLineToInstruction = [
        CanvasInstruction.MOVE_TO_LINE_TO,
        myBegin,
        myEnd,
      ];
      this.instructions.push(moveToLineToInstruction);
      this.hitDetectionInstructions.push(moveToLineToInstruction);
      if (stroke) {
        this.instructions.push(closePathInstruction);
        this.hitDetectionInstructions.push(closePathInstruction);
      }
      offset = end;
    }
    if (fill) {
      this.instructions.push(fillInstruction);
      this.hitDetectionInstructions.push(fillInstruction);
    }
    if (stroke) {
      this.instructions.push(strokeInstruction);
      this.hitDetectionInstructions.push(strokeInstruction);
    }
    return offset;
  }

  drawCircle(circleGeometry, feature, index) {
    const state = this.state;
    const fillStyle = state.fillStyle;
    const strokeStyle = state.strokeStyle;
    if (fillStyle === undefined && strokeStyle === undefined) {
      return;
    }
    this.setFillStrokeStyles_();
    this.beginGeometry(circleGeometry, feature, index);
    if (state.fillStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_FILL_STYLE,
        defaultFillStyle,
      ]);
    }
    if (state.strokeStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_STROKE_STYLE,
        state.strokeStyle,
        state.lineWidth,
        state.lineCap,
        state.lineJoin,
        state.miterLimit,
        defaultLineDash,
        defaultLineDashOffset,
      ]);
    }
    const flatCoordinates = circleGeometry.getFlatCoordinates();
    const stride = circleGeometry.getStride();
    const myBegin = this.coordinates.length;
    this.appendFlatLineCoordinates(
      flatCoordinates,
      0,
      flatCoordinates.length,
      stride,
      false,
      false
    );
    const circleInstruction = [CanvasInstruction.CIRCLE, myBegin];
    this.instructions.push(beginPathInstruction, circleInstruction);
    this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
    if (state.fillStyle !== undefined) {
      this.instructions.push(fillInstruction);
      this.hitDetectionInstructions.push(fillInstruction);
    }
    if (state.strokeStyle !== undefined) {
      this.instructions.push(strokeInstruction);
      this.hitDetectionInstructions.push(strokeInstruction);
    }
    this.endGeometry(feature);
  }

  drawPolygon(polygonGeometry, feature, index) {
    const state = this.state;
    const fillStyle = state.fillStyle;
    const strokeStyle = state.strokeStyle;
    if (fillStyle === undefined && strokeStyle === undefined) {
      return;
    }
    this.setFillStrokeStyles_();
    this.beginGeometry(polygonGeometry, feature, index);
    if (state.fillStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_FILL_STYLE,
        defaultFillStyle,
      ]);
    }
    if (state.strokeStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_STROKE_STYLE,
        state.strokeStyle,
        state.lineWidth,
        state.lineCap,
        state.lineJoin,
        state.miterLimit,
        defaultLineDash,
        defaultLineDashOffset,
      ]);
    }
    const ends = polygonGeometry.getEnds();
    const flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
    const stride = polygonGeometry.getStride();
    this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
    this.endGeometry(feature);
  }

  drawMultiPolygon(multiPolygonGeometry, feature, index) {
    const state = this.state;
    const fillStyle = state.fillStyle;
    const strokeStyle = state.strokeStyle;
    if (fillStyle === undefined && strokeStyle === undefined) {
      return;
    }
    this.setFillStrokeStyles_();
    this.beginGeometry(multiPolygonGeometry, feature, index);
    if (state.fillStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_FILL_STYLE,
        defaultFillStyle,
      ]);
    }
    if (state.strokeStyle !== undefined) {
      this.hitDetectionInstructions.push([
        CanvasInstruction.SET_STROKE_STYLE,
        state.strokeStyle,
        state.lineWidth,
        state.lineCap,
        state.lineJoin,
        state.miterLimit,
        defaultLineDash,
        defaultLineDashOffset,
      ]);
    }
    const endss = multiPolygonGeometry.getEndss();
    const flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
    const stride = multiPolygonGeometry.getStride();
    let offset = 0;
    for (let i = 0, ii = endss.length; i < ii; ++i) {
      offset = this.drawFlatCoordinatess_(
        flatCoordinates,
        offset,
        endss[i],
        stride
      );
    }
    this.endGeometry(feature);
  }

  finish() {
    this.reverseHitDetectionInstructions();
    this.state = null;
    const tolerance = this.tolerance;
    if (tolerance !== 0) {
      const coordinates = this.coordinates;
      for (let i = 0, ii = coordinates.length; i < ii; ++i) {
        coordinates[i] = snap(coordinates[i], tolerance);
      }
    }
    return super.finish();
  }
}
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

# CanvasPolygonBuilder类的构造函数

CanvasPolygonBuilder类的构造函数比较通用,接受以下参数:

  • tolerance:容差,通常用于指定绘制精度或容许的误差范围。

  • maxExtent:最大范围,用来限制图形的显示范围。

  • resolution:地图的分辨率。

  • pixelRatio:像素比率,用来处理不同屏幕或设备的显示效果。

# CanvasPolygonBuilder类的主要方法

  • drawFlatCoordinatess_(flatCoordinates,offset,ends,stride)方法

drawFlatCoordinatess_方法是一个内部方法,画多边形会被调用,接受四个参数flatCoordinates坐标数组、offset起始位置、ends多边形每条线段结束点的位置索引和stride步幅;该方法主要的目的就是根据参数生成不同的指令,这些指令主要包括绘制指令:beginPathInstruction路径绘制开始指令、moveToLineToInstruction绘制路径指令、closePathInstruction路径绘制结束指令以及样式指令:fillInstruction填充样式指令和strokeInstruction。简单来讲就是计算出多边形线段的起始点位置的索引,与指令相对应,在执行绘制过程中根据指令中的索引位置获取对应的坐标进行操作,然后根据样式指令进行装饰。

  • drawCircle(circleGeometry,feature,index)方法

drawCircle方法用于绘制圆形,接受三个参数:circleGeometry圆形几何对象、feature要素和index索引;drawCircle方法首先从this.state中取样式state.fillStyle和state.strokeStyle,若它们未定义,则直接返回,不做任何操作;否则会调用this.setFillStrokeStyles_内部方法,用于设置或新增和样式有关的指令;然后调用父类的beginGeometry方法,生成绘制几何图形开始的指令,接着判断,若样式state.fillStyle和state.strokeStyle存在,则新增CanvasInstruction.SET_STROKE_STYLE和CanvasInstruction.SET_FILL_STYLE类型的指令;然后从circleGeometry几何对象上获取坐标数据,调用this.appendFlatLineCoordinates方法设置this.coordinates,然后新增CanvasInstruction.CIRCLE类型的指令,然后还是根据样式属性设置fillInstruction和strokeInstruction的指令,最后调用this.endGeometry方法,生成绘制几何图形结束的指令。

  • drawPolygon(polygonGeometry,feature,index)方法

drawPolygon方法用于绘制多边形,大体步骤和drawCircle方法类似,不同的是,绘制线段时drawPolygon方法是调用this.drawFlatCoordinatess_,与之相关的指令类型是beginPathInstruction、CanvasInstruction.MOVE_TO_LINE_TO和closePathInstruction,而drawCircle方法则是CanvasInstruction.CIRCLE。

  • drawMultiPolygon(multiPolygonGeometry,feature,index)方法

drawMultiPolygon方法用于绘制多个多边形,无非就是获取多个多边形的坐标数据,循环调用this.drawFlatCoordinatess_方法。

  • finish()方法

finish方法是在构建绘制指令集、碰撞检测指令集和样式指令集后调用,方法内部会先调用this.reverseHitDetectionInstructions方法反转碰撞检测指令,然后判断,若容差精度this.tolerance不为0,则遍历this.coordinates,对每一个坐标调用snap方法,目的是保留拓扑结构的前提下,对多边形进行量化和点消除,以此简化多边形。最后调用父类的finish方法。

  • setFillStrokeStyles_()方法

setFillStrokeStyles_方法用于设置填充样式和边框样式的指令,主要是调用父类的this.updateFillStyle和this.updateStrokeStyle方法。

# 总结

本文主要介绍了CanvasPolygonBuilder类的实现,它是构建绘制圆和多边形指令集的核心类,在实际应用中会被实例化,然后调用实例对象的方法进行构建和获取指令集。

编辑 (opens new window)
上次更新: 2025/01/13, 05:40:21
BuilderGroup类
LineStringBuilder类

← BuilderGroup类 LineStringBuilder类→

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