leaflet学习笔记-带过滤的图例(九)

前言

图例不只能够帮助我们在查看地图的时候更加方便容易地分辨不同颜色代表的要素,本文要介绍的图例组件还可以按需求过滤掉不用显示的要素,使地图的更能清晰的显示我们需要显示的内容

技术核心

说到过滤要素,第一时间想到的就是滑块组件,这里我们选择了Element-plus的Slider 滑块组件,主要功能就是根据滑块背景的不同颜色,滑动滑块过滤掉滑块范围以外背景颜色的要素。这里遇到一个大麻烦,本来以为很容易解决的,后面发现没有这么容易完成,就是滑块的背景颜色添加,这里想了好几种方式,最后还是只能使用原生js通过操作dom实现背景颜色的添加和上下两个滑块遮罩的添加(将要过滤的颜色范围遮盖掉)。核心代码如下:

watchEffect(() => {let [min, max] = sliderValue.value//为了添加滑块的遮罩,达到想要的效果(重点)nextTick(() => {let runway = document.getElementsByClassName('sliderLegend')?.[0]?.querySelectorAll('.el-slider__runway')[0]if (!runway.querySelector('.maxBar')) {let div = document.createElement('div')div.setAttribute('class', 'maxBar maskBar')runway.appendChild(div)}if (!runway.querySelector('.minBar')) {let div = document.createElement('div')div.setAttribute('class', 'minBar maskBar')runway.appendChild(div)}let maxMaskBar = document.querySelector('.maxBar')let minMaskBar = document.querySelector('.minBar')if (maxMaskBar) {maxMaskBar.style.height = new BigNumber(100).minus(max).toNumber() + '%'}if (minMaskBar) {minMaskBar.style.height = min + '%'}})
})

完整代码

/**
* sliderLegend.vue 可以拖动滑块过滤的图例
* @Author ZhangJun
* @Date  2024/1/19 9:36
**/
<template><el-card class='slider-block absolute right-10 bottom-10'v-if='grades.values&&grades.values.length>0'style='z-index: 1000;'><el-space direction='vertical' :size='20'><el-text size='large' type='info'>{{ grades.desc }}{{ grades.unit }}</el-text><div style='width: 60px;text-align: left;'><el-slider ref='legendRef'class='sliderLegend'v-model='sliderValue'@change='onChange':range='true'vertical:marks='marks'v-bind='options' /></div></el-space></el-card>
</template><script setup>
import { ref, defineProps, computed, reactive, watchEffect, nextTick } from 'vue'
import BigNumber from 'bignumber.js'const props = defineProps({gradesValues: { type: Array, default: () => ([]) },//分级的value数值gradesColors: { type: Array, default: () => ([]) },//分级的color数值(需要与gradesValues一一对应)
})const emits = defineEmits(['update:modeValue'])let legendRef = ref()//当前滑块的值
let sliderValue = ref([0, 100])//间隔数值
let interval = ref()//为了获取真实数据和百分比之间的映射关系
let percentage2ValueDic = {}
let valueDic2Percentage = {}/*** @Description 生成滑块的背景颜色* @Param colors 备选颜色集合* @Author ZhangJun* @Date  2024-01-19 01:43:56* @return void**/
let generationLinearGradient = computed(() => {let { colors } = gradeslet interval = new BigNumber(1).div(colors?.length)let temp = colors.map((color, index) => {let percentage = interval.times(index).times(100).toFixed(0) + '%'let rgba = `rgba(${color[0]},${color[1]},${color[2]},${color.length > 3 ? color[3] / 255 : 1})`if (index === 0) {return [rgba]} else {return [percentage, rgba]}})return `linear-gradient(to top,${temp.flat()})`
})//刻度值
const marks = computed(() => {//清空percentage2ValueDic = {}valueDic2Percentage = {}let { values, unit } = gradesinterval.value = new BigNumber(1).div(values?.length - 1)let marks = {}values.forEach((value, index) => {let percentageVal = interval.value.times(index).times(100).toFixed(0)marks = { ...marks, [percentageVal]: `${value}` }//做映射使用percentage2ValueDic = { ...percentage2ValueDic, [percentageVal]: value }valueDic2Percentage = { ...valueDic2Percentage, [value]: percentageVal }})return marks
})//分级数据
let grades = reactive({values: props.gradesValues,colors: props.gradesColors,unit: undefined,desc: '',
})//默认的配置参数
let options = computed(() => {let { values } = gradeslet height = (values?.length - 1) * 40height = height > 300 ? 300 : heightreturn {min: 0,max: 100,height: `${height}px`,step: interval.value.times(100).toFixed(0),showTooltip: false,}
})/*** @Description 初始化当前control* @Param gradesData 分级参数* @Author ZhangJun* @Date  2024-01-22 09:38:17* @return void**/
function initControl(gradesData) {sliderValue.value = [0, 100]grades = Object.assign(grades, gradesData)
}/*** @Description 获取数组里面最接近这个值的数* @Param arr 数组* @Param target 目标值* @Author ZhangJun* @Date  2024-01-19 07:19:21* @return void**/
function getClosestNumber(arr = [], target) {let minDistance = Math.abs(target - arr[0])let [closestNumber] = arrfor (let i = 1; i < arr.length; i++) {let distance = Math.abs(target - arr[i])if (distance < minDistance) {minDistance = distanceclosestNumber = arr[i]}}return closestNumber
}/*** @Description 滑块数值改变* @Param e 事件回调参数* @Author ZhangJun* @Date  2024-01-22 09:38:59* @return void**/
function onChange(e) {let [min, max] = elet arr = Object.keys(percentage2ValueDic)min = getClosestNumber(arr, min)max = getClosestNumber(arr, max)emits('update:modeValue', [percentage2ValueDic[min], percentage2ValueDic[max]])
}watchEffect(() => {let [min, max] = sliderValue.value//为了添加滑块的遮罩,达到想要的效果(重点)nextTick(() => {let runway = document.getElementsByClassName('sliderLegend')?.[0]?.querySelectorAll('.el-slider__runway')[0]if (!runway.querySelector('.maxBar')) {let div = document.createElement('div')div.setAttribute('class', 'maxBar maskBar')runway.appendChild(div)}if (!runway.querySelector('.minBar')) {let div = document.createElement('div')div.setAttribute('class', 'minBar maskBar')runway.appendChild(div)}let maxMaskBar = document.querySelector('.maxBar')let minMaskBar = document.querySelector('.minBar')if (maxMaskBar) {maxMaskBar.style.height = new BigNumber(100).minus(max).toNumber() + '%'}if (minMaskBar) {minMaskBar.style.height = min + '%'}})
})defineExpose({ initControl })</script><style scoped lang='scss'>
::v-deep .el-slider__runway {background: v-bind(generationLinearGradient);.maskBar {width: 100%;height: auto;background: lightgrey;position: absolute;border-radius: 6px;}.maxBar {top: -3px;}.minBar {bottom: -3px;}
}::v-deep .el-slider__bar {background: transparent;
}
</style>

效果

过滤后的效果

在这里插入图片描述

本来原理很简单,主要时间还是花费到了slider的背景颜色上,还要添加一个上下滑动的遮罩,才能将要过滤掉的颜色范围遮掉

进阶版

加入可横向/竖向选择

/**
* sliderLegend.vue 可以拖动滑块过滤的图例
* @Author ZhangJun
* @Date  2024/1/19 9:36
**/
<template><el-cardclass="slider-block absolute right-10 bottom-10 text-center"v-if="grades.values && grades.values.length > 0":body-style="getBodyStyle"style="z-index: 600"><el-space direction="vertical" :size="vertical ? 20 : 0"><el-text type="info">{{ grades.desc }}{{ grades.unit }}</el-text><div style="text-align: left"><el-slider ref="legendRef" class="sliderLegend" v-model="sliderValue" @change="onChange" :range="true" :marks="marks" v-bind="options" /></div></el-space></el-card>
</template><script setup>
import { ref, defineProps, computed, reactive, watchEffect, nextTick } from 'vue'
import BigNumber from 'bignumber.js'const props = defineProps({gradesValues: { type: Array, default: () => [] }, //分级的value数值gradesColors: { type: Array, default: () => [] }, //分级的color数值(需要与gradesValues一一对应)intervalHeight: { type: Number, default: 40 }, //间隔的高的maxHeight: { type: Number, default: 195 }, //图例最高高度限制width: { type: Number, default: 130 }, //图例宽度vertical: { type: Boolean, default: false }, //是否垂直模式
})const emits = defineEmits(['update:modeValue'])let legendRef = ref()//当前滑块的值
let sliderValue = ref([0, 100])//间隔数值
let interval = ref()//为了获取真实数据和百分比之间的映射关系
let percentage2ValueDic = {}
let valueDic2Percentage = {}//得到内容部分的样式
let getBodyStyle = computed(() => {if (props?.vertical) {return { padding: `10px 0 0`, width: `${props.width}px` }} else {return { padding: `10px`, height: `${props.width}px` }}
})/*** @Description 生成滑块的背景颜色* @Param colors 备选颜色集合* @Author ZhangJun* @Date  2024-01-19 01:43:56* @return void**/
let generationLinearGradient = computed(() => {let { colors } = gradeslet interval = new BigNumber(1).div(colors?.length - 1)let temp = colors.map((color, index) => {let percentage = interval.times(index).times(100).toFixed(0) + '%'let rgba = `rgba(${color[0]},${color[1]},${color[2]},${color.length > 3 ? color[3] / 255 : 1})`if (index === 0) {return [rgba]} else {return [percentage, rgba]}})if (props?.vertical) {return `linear-gradient(to top,${temp.flat()})`} else {return `linear-gradient(to right,${temp.flat()})`}
})//刻度值
const marks = computed(() => {//清空percentage2ValueDic = {}valueDic2Percentage = {}let { values, unit } = gradesinterval.value = new BigNumber(1).div(values?.length - 1)let marks = {}values.forEach((value, index) => {let percentageVal = interval.value.times(index).times(100).toFixed(0)marks = { ...marks, [percentageVal]: `${value}` }//做映射使用percentage2ValueDic = { ...percentage2ValueDic, [percentageVal]: value }valueDic2Percentage = { ...valueDic2Percentage, [value]: percentageVal }})return marks
})//分级数据
let grades = reactive({values: props.gradesValues,colors: props.gradesColors,unit: undefined,desc: '',
})//默认的配置参数
let options = computed(() => {let { values } = gradeslet height = new BigNumber(props.intervalHeight).times(values?.length - 1).toNumber()height = height > props.maxHeight ? props.maxHeight : heightlet options_temp = {min: 0,max: 100,step: interval.value.times(100).toFixed(0),showTooltip: false,vertical: props?.vertical,size: 'small',}if (props?.vertical) {options_temp = {...options_temp,height: `${height}px`,}} else {options_temp = {...options_temp,style: {margin: '0 20px 0',width: `${height}px`,},}}return options_temp
})/*** @Description 初始化当前control* @Param gradesData 分级参数* @Author ZhangJun* @Date  2024-01-22 09:38:17* @return void**/
function initControl(gradesData) {sliderValue.value = [0, 100]grades = Object.assign(grades, gradesData)
}/*** @Description 获取数组里面最接近这个值的数* @Param arr 数组* @Param target 目标值* @Author ZhangJun* @Date  2024-01-19 07:19:21* @return void**/
function getClosestNumber(arr = [], target) {let minDistance = Math.abs(target - arr[0])let [closestNumber] = arrarr.forEach((value, index) => {if (index > 0) {let distance = Math.abs(target - value)if (distance < minDistance) {minDistance = distanceclosestNumber = value}}})return closestNumber
}/*** @Description 滑块数值改变* @Param e 事件回调参数* @Author ZhangJun* @Date  2024-01-22 09:38:59* @return void**/
function onChange(e) {let [min, max] = elet arr = Object.keys(percentage2ValueDic)min = getClosestNumber(arr, min)max = getClosestNumber(arr, max)emits('update:modeValue', [percentage2ValueDic[min], percentage2ValueDic[max]])
}watchEffect(() => {let [min, max] = sliderValue.value//为了添加滑块的遮罩,达到想要的效果(重点)nextTick(() => {let runway = document.getElementsByClassName('sliderLegend')?.[0]?.querySelectorAll('.el-slider__runway')[0]if (!runway?.querySelector('.maxBar')) {let div = document.createElement('div')div.setAttribute('class', `maxBar maskBar ${props?.vertical ? 'verticalBar' : ''}`)runway.appendChild(div)}if (!runway?.querySelector('.minBar')) {let div = document.createElement('div')div.setAttribute('class', `minBar maskBar ${props?.vertical ? 'verticalBar' : ''}`)runway.appendChild(div)}let maxMaskBar = document.querySelector('.maxBar')let minMaskBar = document.querySelector('.minBar')if (maxMaskBar) {if (props?.vertical) {maxMaskBar.style.height = new BigNumber(100).minus(max).toNumber() + '%'} else {debuggermaxMaskBar.style.width = new BigNumber(100).minus(max).toNumber() + '%'}}if (minMaskBar) {if (props?.vertical) {minMaskBar.style.height = min + '%'} else {minMaskBar.style.width = min + '%'}}})
})defineExpose({ initControl })
</script><style scoped lang="scss">
::v-deep .el-slider__runway {background: v-bind(generationLinearGradient);.maskBar {height: 100%;width: auto;top: 0;&.verticalBar {width: 100%;height: auto;top: auto;}background: lightgrey;position: absolute;border-radius: 6px;}.maxBar {right: -3px;&.verticalBar {top: -3px;right: auto;}}.minBar {left: -3px;&.verticalBar {bottom: -3px;left: auto;}}
}::v-deep .el-slider__bar {background: transparent;
}
</style>

本文为学习笔记,仅供参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/245002.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内网穿透、远程桌面、VPN的理解

最近在研究内网穿透的相关技术&#xff0c;然后回想起一些相关的技术&#xff0c;比如说要远程桌面公司的电脑&#xff0c;VPN连入内网等。然后想着在此处记录一下&#xff0c;各个的区别&#xff0c;这个纯粹是从技术层面的理解&#xff0c;此处不详细解释怎么去实现或者用什么…

【C++】stack、queue的使用及模拟实现

目录 一、stack1.1 stack的使用1.2 stack的模拟实现 二、queue2.1 queue的使用2.2 queue的模拟实现 一、stack 1.1 stack的使用 stack是一种容器适配器&#xff0c;它的特点是后进先出&#xff0c;只能在容器的一端进行插入和删除操作。 stack的使用很简单&#xff0c;主要有…

在IDEA中创建SpringBoot项目

概述 SpringBoot是由Pivotal团队提供的全新的框架&#xff0c;其设计的目的是用来简化Spring应用的初始搭建以及开发过程。 传统方式构建Spring应用程序 导入依赖繁琐 依赖冲突 项目配置繁琐 SpringBoot特性 1、起步依赖 本质上就行一个Maven坐标&#xff0c;整合了完成一…

Java 集合List相关面试题

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…

dataGrip连接数据库mysql和intersystems的iris

文章目录 前言创建新项目选择对应的数据库产品类型新建数据库资源连接sql命令窗体手动配置本地驱动 前言 intersystems公司的产品iris是cache的升级版本&#xff0c;目前绝大多数数据库工具都没法连接这个数据库 datagrip下载地址 https://download-cdn.jetbrains.com.cn/da…

eBay在人工智能道路上的成败得失:衡量标准是关键

我是2006年加入eBay的。2009年&#xff0c;这家公司的运营状况非常糟糕&#xff0c;其股价创历史新低&#xff08;远低于近24美元的历史高位&#xff09;&#xff0c;还出现削减各项成本、负增长、市场占有率降低、技术团队缺乏创新能力等情况。 简而言之&#xff0c;eBay公司…

CentOS7自动备份数据库到git

虽然数据库没什么数据&#xff0c;但是有就是珍贵的啦&#xff0c;为了服务器什么的无了&#xff0c;所以还是要自动备份一下比较好。 Open备忘第一页 步骤 在Gitee&#xff08;github&#xff09;上创建一个私有仓库Gitee&#xff08;github&#xff09;配置好服务器的ssh在服…

Oracle BIEE 示例(一)数据透视表2

1 背景 版本:BIEE 12C 视图:数据透视表 实现内容(顺序与具体内容不一致): 2 空列显示(方法一) 2.1 问题 列为空时,标题栏不显示信息。 2.2 期望 即使数据为空,也要显示列名。 2.3 官方资料 2.3.1 操作步骤 2.3.1.1 要在分析级别关闭空值隐藏,请执行以下操作…

MySQL与PostgreSQL对比

对比 许可证 License MySQL 社区版采用 GPL 许可证。Postgres 发布在 PostgreSQL 许可下&#xff0c;是一种类似于 BSD 或 MIT 的自由开源许可。 即便 MySQL 采用了 GPL&#xff0c;仍有人担心 MySQL 归 Oracle 所有&#xff0c;这也是为什么 MariaDB 从 MySQL 分叉出来。 …

mac安装部署gitbook教程

mac安装部署gitbook教程 前言一、安装准备二、GitBook安装三、项目初始化 前言 一些自己实际操作的记录。 一、安装准备 Node.js gitbook基于Node.js&#xff0c;所以需要提前安装。 下载地址&#xff1a;https://nodejs.org/en/&#xff0c;可以下载比较新的版本。(但我的建议…

[已解决]504 Gateway Time-out 网关超时

文章目录 问题&#xff1a;504 Gateway Time-out 504 Gateway Time-out 网关超时思路解决 问题&#xff1a;504 Gateway Time-out 504 Gateway Time-out 网关超时 思路 网上的常规思路是修改nginx配置文件,增加请求执行时间,试过没有用 keepalive_timeout 600; fastcgi_con…

vue3-深入组件-组件注册和props更多细节

组件注册 定义好的组件需要注册才能被使用。 注册方式有两种 全局注册 局部注册 全局注册 .component() 方法&#xff0c;让组件在当前 Vue 应用中全局可用。 在 main.ts 中 import ./assets/main.cssimport { createApp } from vue import { createPinia } from pinia i…

基于springboot+vue的网上租赁系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测,预测新数据

碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测&#xff0c;预测新数据 目录 碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测&#xff0c;预测新数据预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现LSTM长短期记忆神经网络多输入单输出未来…

架构师之路(十六)计算机网络(传输层)

前置知识&#xff08;了解&#xff09;&#xff1a;计算机基础。 作为架构师&#xff0c;我们所设计的系统很少为单机系统&#xff0c;因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 既然网络层已经…

C# Bitmap类学习1

Bitmap对象封装了GDI中的一个位图&#xff0c;此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using …

mybatis----小细节

1、起别名 在MyBatis中&#xff0c;<typeAliases>元素用于定义类型别名&#xff0c;它可以将Java类名映射为一个更简短的别名&#xff0c;这样在映射文件中可以直接使用别名而不需要完整的类名。 下面是一个示例&#xff1a; 在mybatis核心配置文件中配置typeAliases标…

第21课 在Android Native开发中架起java与c++互通的桥梁

在开始本节课&#xff0c;我尝试把项目拷贝到另一台电脑上以便继续工作&#xff0c;但出现了大量的“could not be resolved”问题&#xff0c;尝试包含新的include路径也无法解决该问题&#xff0c;最后删除了项目的Native Support&#xff0c;然后重新添加Native Support才解…

百科同名就不能重建一个百科吗,代创建百科公司是如何做到的

发现自己的名字在百度上已经有百科词条并不出奇&#xff0c;因为同名同姓的人非常多&#xff0c;但是是不是百科已经有同名词条了就不能重建一个百科&#xff0c;很多朋友在自己做百度百科不通过时往往会发出这样的疑问。 实际上百度百科同名也是可以再重新创建的&#xff0c;…

【K8S】Service使用NodePort对外暴露应用

一、背景介绍 Pod是有生命周期的&#xff0c;当一个工作节点(node)销毁时&#xff0c;节点上运行的pods也会被销毁。ReplicationController会动态地在其他节点上创建Pod来保持应用程序的运行&#xff0c;每一个Pod都有一个独立的IP地址&#xff0c;甚至是同一个节点上的Pod。可…