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)
  • 框架

  • core模块

  • dom模块

  • control

  • geometry

  • geo

  • layer

    • marker

    • tile

    • vector

      • Renderer
      • Canvas
      • Path
        • 概述
        • 源码分析
          • 源码实现
          • 源码详解
          • 类继承与定位
          • 核心方法解析
          • 渲染器交互机制
          • 设计思想
          • 与其他模块的关系
        • 总结
      • Polyline
      • Polygon
      • Rectangle
      • Render.getRenderer
      • SVG
      • SVG.Util
      • SVG.VML
      • CircleMarker
      • Circle
    • Layer
    • LayerGroup
    • FeatureGroup
    • DivOverlay
    • Popup
    • Tooltip
    • ImageOverlay
    • SVGOverlay
    • VideoOverlay
    • GeoJSON
  • Map

  • 《Leaflet源码》笔记
  • layer
  • vector
东流
2025-04-15
目录

Path

# 概述

Path类继承自Layer基类,是一个抽象类,不能直接使用,通常它用于矢量覆盖图层如多边形、折线和圆形的基类,为具体的矢量图形提供共同的功能和属性。

# 源码分析

# 源码实现

Path的源码实现如下:

export var Path = Layer.extend({
  options: {
    // 描边样式
    stroke: true, // 是否显示描边(默认开启)
    color: "#3388ff", // 描边颜色(默认蓝色)
    weight: 3, // 线宽
    opacity: 1, // 透明度
    lineCap: "round", // 线端形状(圆角)
    lineJoin: "round",// 拐角形状(圆角)
    dashArray: null,// 虚线模式
    dashOffset: null,// 虚线偏移量
    // 填充样式
    fill: false,// 是否填充(默认关闭)
    fillColor: null,// 填充颜色 (默认继承描边颜色)
    fillOpacity: 0.2, // 填充透明度
    fillRule: "evenodd", // 填充规则 (SVG的evenodd算法)
    // 交互样式
    interactive: true, // 是否响应鼠标事件
    bubblingMouseEvents: true, // 事件冒泡到地图
  },
  // 添加到地图前,绑定渲染器
  beforeAdd: function (map) {
    this._renderer = map.getRenderer(this); // 获取渲染器 (SVG/Canvas)
  },
  // 添加到地图时:初始化路径并渲染
  onAdd: function () {
    this._renderer._initPath(this); // 初始化路径数据结构
    this._reset(); // 子类实现,坐标转换
    this._renderer._addPath(this); // 添加到渲染器
  },
  // 从地图移除时:清理资源
  onRemove: function () {
    this._renderer._removePath(this); //从渲染器移除
  },
  // 重绘路径(数据变化时调用)
  redraw: function () {
    if (this._map) {
      this._renderer._updatePath(this);
    }
    return this;
  },
  // 动态更新样式
  setStyle: function (style) {
    Util.setOptions(this, style); // 合并新样式
    if (this._renderer) {
      this._renderer._updateStyle(this); // 渲染器应用样式
      // 更新点击检测区域
      if (
        this.options.stroke &&
        style &&
        Object.prototype.hasOwnProperty.call(style, "weight")
      ) {
        this._updateBounds();
      }
    }
    return this;
  },
  // 调整图层叠放顺序
  bringToFront: function () {
    if (this._renderer) {
      this._renderer._bringToFront(this);
    }
    return this;
  },
  bringToBack: function () {
    if (this._renderer) {
      this._renderer._bringToBack(this);
    }
    return this;
  },
  getElement: function () {
    return this._path;
  },
  // 子类实现:坐标投影与路径更新
  _reset: function () {
    this._project(); // 经纬度 → 平面坐标 (墨卡托投影)
    this._update(); // 生成路径数据 (如SVG的d属性)
  },
  // 计算点击检测容差(Canvas 专用)
  _clickTolerance: function () {
    return (
      (this.options.stroke ? this.options.weight / 2 : 0) +
      (this._renderer.options.tolerance || 0)
    );
  },
});
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

# 源码详解

# 类继承与定位

  • 继承自Layer:继承图层基类,具备地图生命周期管理能力(onAdd/onRemove)
  • 抽象类:不可直接实例化,需通过子类(如Polygon、Circle)实现具体图形

# 核心方法解析

1.生命周期钩子

除了beforeAdd、onAdd和onRemove等生命周期钩子函数外,还引入了渲染器,即渲染逻辑由Renderer的子类(如SVGRenderer、CanvasRenderer)实现

2.图形操作

  • 重绘方法:redraw在数据变化时会被调用,也是通过渲染器进行更新绘制
  • 更新样式:setStyle方法支持动态设置样式
  • **bringToFront和bringToBack**可以调整矢量图形的堆叠顺序

# 渲染器交互机制

  • 职责分离:Path类不能直接操作DOM/Canvas,而是通过渲染器Renderer子类委托进行操作:
    • _initPath:创建路径元素,(如SVG <path>)
    • _addPath/_removePath:增删元素到画布
    • _updatePath:路径数据变化时重绘
    • _updateStyle:应用样式属性(颜色、透明度等)
    • _bringToFront/_bringToBack:控制Z轴顺序

# 设计思想

1.抽象基类模式

  • 通用逻辑在Path中实现(样式管理、生命周期)
  • 具体图形(如Polygon)继承后实现_project和_update

2.渲染器抽象层

  • 通过Renderer隔离不同渲染技术(SVG、Canvas)
  • 扩展性:未来可添加WebGL渲染器

3.性能优化

  • 批量更新:样式变更后统一渲染
  • 按需重绘:redraw手动触发,避免频繁操作

4.交互兼容

  • interactive:控制是否响应事件
  • _clickTolerance:解决Canvas无原生事件的问题

# 与其他模块的关系

  • 依赖Renderer:由SVGRenderer或CanvasRenderer实现具体绘制
  • 事件系统:继承自Interactive Layer,支持click、mouseover等事件
  • 坐标系统:_project方法依赖Map的投影转换

# 总结

Leaflet 的 Path 模块通过抽象基类与渲染器分离的设计,实现了矢量图形的高效管理和跨平台渲染。其核心在于:

​​- 样式与数据分离​​:通过 options 统一管理外观属性。 ​​- 生命周期与渲染解耦​​:通过 Renderer 接口适配不同渲染技术。

  • 高性能更新​​:手动控制重绘,避免不必要的计算。

这种设计使得 Leaflet 能够灵活支持 SVG 和 Canvas 渲染,并提供了扩展自定义矢量图形的坚实基础

编辑 (opens new window)
上次更新: 2025/05/08, 10:32:25
Canvas
Polyline

← Canvas Polyline→

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