首页 > 编程语言 >源码分析之Openlayers中CanvasLineStringBuilder类

源码分析之Openlayers中CanvasLineStringBuilder类

时间:2025-01-13 16:57:51浏览次数:3  
标签:const 方法 指令 state 源码 Openlayers CanvasLineStringBuilder 绘制 线段

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

标签:const,方法,指令,state,源码,Openlayers,CanvasLineStringBuilder,绘制,线段
From: https://blog.csdn.net/m0_46281382/article/details/145119361

相关文章

  • 【附源码】springboot 高校教师工作量管理系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 干洗店预约洗衣系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 在线学习过程管理系统软件设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot Javaweb 的网上商城系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 在线学习过程管理系统软件设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 干洗店预约洗衣系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 高校教师工作量管理系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 干洗店预约洗衣系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 在线学习过程管理系统软件设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 【附源码】springboot 干洗店预约洗衣系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......