leaflet学习笔记-贝塞尔曲线绘制(八)
前言
两点之间的连线是很常见的,但是都是直直的一条线段,为了使连线更加平滑,我们可以使用曲线进行连线,本功能考虑使用贝塞尔曲线进行连线绘制,最后将线段的两端节点连接,返回一个polygon。
贝塞尔简介
给定不同的点 P0 和 P1,线性贝塞尔曲线只是这两点之间的一条线。
相当于线性插值。

Turf.bezierSpline()简介
接受一条线,通过应用贝塞尔样条算法返回一个弯曲的版本
官方例子
var line = turf.lineString([[-76.091308, 18.427501],[-76.695556, 18.729501],[-76.552734, 19.40443],[-74.61914, 19.134789],[-73.652343, 20.07657],[-73.157958, 20.210656]
]);var curved = turf.bezierSpline(line);
参数说明
line:input LineString
options:{
resolution:点之间的时间(毫秒)
sharpness:衡量样条路径应该有多弯曲的一个度量
}
具体可以查看官方的bezierSpline函数
UseBezierSpline.js完整代码
import { onBeforeUnmount, reactive, ref } from 'vue'
import * as turf from '@turf/turf'/*** @Description 接受一条线,通过应用贝塞尔样条算法返回一个弯曲的版本(贝塞尔曲线)* @param mainMap 地图对象* @param drawComplete 完成绘制的回调函数* @Param bezierOptions* @Param bezierOptions.resolution 点之间的时间(毫秒)* @Param bezierOptions.sharpness 衡量样条路径应该有多弯曲的一个度量* @param drawLayer 绘制图形的layer* @Author ZhangJun* @Date 2024-01-11 09:55:12* @return void**/
export default function useBezierSpline(mainMap, drawComplete = null, bezierOptions = {}, drawLayer = undefined) {//默认的贝塞尔配置参数合并let bezierOptions_config = reactive({resolution: 1000,sharpness: 0.85,...bezierOptions,})//绘制事件状态let status = ref('start')// 记录当前状态是否可以拖动绘制let isDragging = true//拖动绘制的坐标let drawPath = []//拖动绘制的线let drawLine = reactive(null)//鼠标正在移动的点let movePoint//最终绘制的polygon,最终返回的就是它的轮廓坐标let polygon_draw = reactive(null)//鼠标提示let mouseEventPopup = new L.popup({ className: 'customPopup', closeButton: false })if (mainMap) {//关闭的时候一定要销毁onBeforeUnmount(() => {closeDraw()mainMap?.removeLayer(drawLayer)})if (!drawLayer) {drawLayer = L.featureGroup([])drawLayer.addTo(mainMap)}//初始化事件let initEvents = () => {isDragging = false//按下鼠标确定需要添加的节点(暂停中)mainMap.on('mousedown', (e) => {isDragging = falselet { lat, lng } = e.latlngdrawPath = [...drawPath, [lng, lat]]//如果才开始点击第一次,就创建一个polyline,后面需要动态需改它的pathif (drawPath?.length === 1) {status.value = 'start'//添加绘制linedrawLine = L.polyline(drawPath, { color: 'red' }).addTo(mainMap)}})//松开鼠标开始拖动绘制(开始绘制)mainMap.on('mouseup', (e) => {isDragging = true})//鼠标移动绘制(绘制中)mainMap.on('mousemove', (e) => {if (isDragging) {let { lat, lng } = e.latlngmovePoint = [lng, lat]//动态生成贝塞尔曲线的featurelet splineFeature = generationBezierSpline(drawPath, movePoint)if (splineFeature) {let tempCoords = turf.getCoords(turf.flip(splineFeature))//将生成的贝塞尔曲线的坐标传给polyline,在地图上刷新渲染drawLine?.setLatLngs(tempCoords)}}mouseEventPopup?.setLatLng(e.latlng)?.setContent('右键结束绘制')//如果还没有添加就直接先添加一下if (!mainMap.hasLayer(mouseEventPopup)) {//打开方向的popupmouseEventPopup?.openOn(mainMap)}})//右键结束(结束绘制)mainMap.on('contextmenu', (e) => {let coords = turf.getCoords(turf.flip(drawLine.toGeoJSON()))//生成polygonpolygon_draw = L.polygon(coords, { color: 'green' })clearDrawLayer()addLayersToDrawLayer([polygon_draw])//移除曲线mainMap?.removeLayer(drawLine)status.value = 'end'//绘制完成的回调if (typeof drawComplete === 'function') {let result = getResult(polygon_draw)drawComplete(result)}})}//移除事件let removeEvents = () => {//按下鼠标mainMap?.off('mousedown')//抬起鼠标mainMap?.off('mouseup')//拖拽事件mainMap?.off('mousemove')//右键事件mainMap?.off('contextmenu')}//开始绘制let startDraw = () => {//禁止拖动地图mainMap?.dragging?.disable()//初始化事件initEvents()}//清除原来绘制的内容let clearDrawLayer = () => {drawPath = []drawLayer?.clearLayers()}//添加要素到drawLayerlet addLayersToDrawLayer = (features = []) => {features?.forEach(feature => {drawLayer.addLayer(feature)})}/*** @Description 生成曲线* @Param originalPath 已经确定的点坐标集合* @Param lastPoint 最后一个坐标点,一般为移动的点坐标* @Author ZhangJun* @Date 2024-01-11 10:36:11* @return void**/let generationBezierSpline = (originalPath = drawPath, lastPoint = movePoint) => {if (originalPath?.length > 0) {//加入最后一个点let line = turf.lineString([...originalPath, lastPoint], bezierOptions_config)return turf.bezierSpline(line)}return null}//关闭绘制功能let closeDraw = () => {//清空绘制的几何clearDrawLayer()//一定要移除事件,否则事件之间会有干扰removeEvents()//移除popupmainMap?.closePopup(mouseEventPopup)//激活拖拽功能mainMap?.dragging?.enable()}//获取最终的polygon的轮廓坐标let getResult = (feature = polygon_draw) => {if (feature) {//获取输入 feature 并将它们的所有坐标从 [x, y] 翻转为 [y, x]。let featureCollection = turf.flip(feature.toGeoJSON())return turf.getCoords(featureCollection)}return []}return { status, getResult, closeDraw, drawLayer, bezierOptions_config, startDraw }}return {}
}
UseBezierSpline.js使用
if (wizMap?.map) {let { startDraw, closeDraw, status: temp, getResult } = useBezierSpline(wizMap?.map)getCoords = getResult//当前绘制状态(是否完成绘制)status.value = temponMounted(() => {//需要这种处理,不然会有异常nextTick(() => {startDraw()})})
}
效果
贝塞尔曲线
本文为学习笔记,仅供参考
相关文章:
leaflet学习笔记-贝塞尔曲线绘制(八)
前言 两点之间的连线是很常见的,但是都是直直的一条线段,为了使连线更加平滑,我们可以使用曲线进行连线,本功能考虑使用贝塞尔曲线进行连线绘制,最后将线段的两端节点连接,返回一个polygon。 贝塞尔简介 …...
42-单双多路分支,嵌套分支,switch分支,for循环,for in,while,do while,break,continue
js流程控制,代码的执行机制:顺序控制,分支控制,循环控制 1.顺序控制:就是按照代码的书写顺序,自上而下执行 2.分支控制 2.1单路分支 // 单路分支// if(条件表达式){// 执行代码// }// 如果条件表达式满…...
CNCF之CoreDNS
目前我们学习云原生技术,就不得不去了解CNCF,即Cloud Native Computing Foundation,云原生计算基金会,它的宣言或理念是: The Cloud Native Computing Foundation (CNCF) hosts critical components of the global tec…...
MySQL一主一从读写分离
MySQL主从复制 一、主从复制概念 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从服务器中,然后在从服务器上对这些日志重新执行也叫重做,从而使得从数据库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行赋值,从…...
【学术会议】第三届神经计算青年研讨会 学习笔记
第三届神经计算青年研讨会 学习笔记 会议时间:2024-1-6至2024-1-7 会议地点:电子科技大学 会议介绍: 为提升我国神经计算⻘年研究队伍的学术⽔平和国际影响⼒,研讨会主题涵盖:神经系统建模与模拟、脑机接⼝与类脑智能、…...
[C#]使用winform部署PP-MattingV2人像分割onnx模型
【官方框架地址】 https://github.com/PaddlePaddle/PaddleSeg 【算法介绍】 PP-MattingV2是一种先进的图像和视频抠图算法,由百度公司基于PaddlePaddle深度学习框架开发。它旨在提供更精准和高效的图像分割功能,特别是在处理图像中的细微部分…...
回顾2023,立2024flag
文章目录 回顾2023与CSDN相识专栏整理数据回顾 立2024flag 回顾2023 在过去的一年里,前端技术不断演进和创新。新技术、新框架层出不穷,给前端工程师提供了更多选择和挑战。2023年已经成为过去,回首这一年,我们也经历了许多挑战和…...
【PostgreSQL创建索引的锁分析和使用注意】
1.1 创建普通B-tree索引的整体流程 如下是梳理的创建普通B-tree索引的大概流程,可供参考。 1.校验新索引的Catalog元数据|语法解析 ---将创建索引的sql解析成IndexStmt结构|校验B-Tree的handler -----校验内核是否支持该类型的索引,在pg_am中查找&q…...
什么是云安全?如何保护云资源
云计算允许组织通过互联网按需向其客户、合作伙伴或员工提供关键业务应用程序、服务和资源。换句话说,不再需要物理维护资源。每当您通过 Internet 从计算机访问文件或服务时,您都是在访问云。 迁移到云可以帮助企业增强安全性、简化运营并降低成本。企…...
Android可换行的RadioGroup
Android可换行的RadioGroup,有时候需要换行显示的单选列表,当然可以有多种实现方式,比如recycleview或者listview实现,本文采用的是RadioGrouprediobutton方式实现。 一、首先自定义view public class WrapRadioGroup extends RadioGroup {pr…...
【ASP.NET Core 基础知识】--环境设置
一、简介 1.1 .NET Core SDK 概述 .NET Core SDK(Software Development Kit)是Microsoft推出的一个开源跨平台框架,用于开发和部署.NET应用程序。它是.NET Core平台的核心组件之一,为开发者提供了在多个操作系统上构建高性能、可…...
docker/华为云cce 部署nacos 2.3.0 集群模式
镜像地址 https://hub.docker.com/r/nacos/nacos-server 版本 nacos/nacos-server:v2.3.0-slim 关键环境变量 使用mysql数据源 变量值备注MODEcluster启用集群模式MYSQL_SERVICE_DB_NAME数据库名MYSQL_SERVICE_USER数据库用户名MYSQL_SERVICE_PASSWORD数据库密码SPRING_D…...
Doris 数据模型—Aggregate 模型
Doris 数据模型—Aggregate 模型 文章目录 Doris 数据模型—Aggregate 模型基本概念Aggregate 模型示例1:导入数据聚合示例2:保留明细数据示例3:导入数据与已有数据聚合Aggregate 模型限制Aggregate 模型使用场景本文主要从逻辑层面,描述 Doris 的数据模型,以帮助用户更好…...
数据库管理-第130期 JSON二元性(20240109)
数据库管理130期 2024-01-09 第130期 JSON二元性(20240109)1 简介2 关系型表和JSON存储的优劣3 Oracle JSON关系型二元性视图总结 第130期 JSON二元性(20240109) 上周,又双叒飞了一趟上海,也是2024年第一飞…...
k8s--动态pvc和pv
前情回顾 存储卷: emptyDir 容器内部,随着pod销毁,emptyDir也会消失 不能做数据持久化 hostPath:持久化存储数据 可以和节点上目录做挂载。pod被销毁了数据还在 NFS:一台机器,提供pod内容器所有的挂载点…...
C++:常量
const的最初动机 const的使用方法 使用const的好处是允许指定一种语义上的约束,即某种对象不能被修改,且由编译器具体实施这种约束。 const声明格式:const 类型名 对象名;修饰普通变量,时期不能被随意修改 【注意】1.C中的const…...
java JDBC 连接数据库
必须先插入工具包 DataSource ds JdbcHelper.getDs();System.out.println(ds);JdbcTemplate jdbcTemplatenew JdbcTemplate(ds);System.out.println(jdbcTemplate);//新增String sql1"insert into biao values(null,?,?,?)";int ijdbcTemplate.update(sql1,"…...
图神经网络|5.消息传递的计算方法 6.多层GNN的作用
5.消息传递的计算方法 边的存放方式 注意,在实际的边的实现方式中,并不是以邻接矩阵来进行实现的,这是因为在图的更新中,用邻接矩阵进行更新所占用的时间开销相对大,二是因为领接矩阵占用的空间大(N方&am…...
构建中国人自己的私人GPT
创作不易,请大家多鼓励支持。 在现实生活中,很多人的资料是不愿意公布在互联网上的,但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢?于是我们构建自己或公司的私人GPT变得非常重要。 先看效果 一、…...
添加气泡与菜单
目录 1、添加气泡 1.1、文本提示气泡 1.2、带按钮的提示气泡 1.3、自定义气泡 2、菜单 2.1、创建默认样式的菜单 2.2、创建自定义样式的菜单 1、添加气泡 Popup属性可绑定在组件上显示气泡弹窗提示,设置弹窗内容、交互逻辑和显示状态。主要用于…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
