技术标签: # Vue # Web GIS vue 前端 javascript
<template>
<div class="leaflet-map-panel"
ref="leaflet-map-panel"
v-loading="loading">
<!-- 地图容器 -->
<div id="map-container"
ref="map">
</div>
<!-- 搜索输入框 -->
<poi-search @select="jumpToTargetMarker"></poi-search>
<!-- 信息窗体 -->
<div style="display:none">
<infowindow ref="infowindow"
:deviceInfo="showDeviceInfo">
</infowindow>
</div>
</div>
</template>
npm 安装
npm i leaflet --save
or
index.html加入以下代码
..
<body>
...
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
...
</body>
...
个人建议使用npm安装,因为我在使用index.html导入时,在发布版下会报“L未定义”的错误
官方文档
// https://www.cnblogs.com/yingyigongzi/p/10810110.html
// https://www.cnblogs.com/zhonglinke/p/11525965.html
async mapInit() {
try {
// 第一个参数为元素id
this.map.instance = new L.map('map-container', {
// 顺序反的反的!!
center: [this.mapParams.location.lat, this.mapParams.location.lng], // 初始化地图中心点
zoom: 16, // 初始化地图层级
minZoom: 8,
zoomControl: false,
attributionControl: false
})
this.map.markerLayer = new L.featureGroup()
this.map.markerLayer.addTo(this.map.instance)
this.map.otherLayer = new L.featureGroup()
this.map.otherLayer.addTo(this.map.instance)
// 绑定地图click事件
this.map.instance.on('click', this.mapClick)
// 绑定地图移动与缩放事件,就不贴出来了
this.mapRegisterEvent()
// 处理弹出窗自适应事件
this.map.instance.on('autopanstart', () => {
console.log('autopan start')
this.flag.autoPaning = true
this.mapUnregisterEvent()
this.map.instance.once('moveend', () => {
console.log('autopan end')
this.flag.autoPaning = false
this.mapRegisterEvent()
})
})
this.initRecord.mapInit.value = true
} catch (error) {
console.error('mapInit error: ', error)
this.$Message(`${
this.$t('gisMap.map.error.init')}: ${
error}`, 'error')
this.initRecord.mapInit.value = false
this.initRecord.mapInit.result = error
throw error
}
},
// 在线地图
const tile = new L.tileLayer(
'webrd0{s}.is.autonavi.com/appmaptile?&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
{
subdomains: [ '1', '2', '3', '4' ], format:'image/png'})
tile .addTo(地图实例)
// 离线地图
const wms = new L.tileLayer.wms(
url,// wms地址
options // 参数
)
wms.addTo(地图实例)
async mapLoadTile() {
try {
switch (this.mapParams.useMapType) {
case 'Offline':
if (!this.mapParams.mapTileOptions['layers'])
this.$Message(
`'MapTileOptions.layers' ${
this.$t(
'gisMap.map.warning.noCfg'
)}`,
'warning'
)
this.map.tileLayer = new L.tileLayer.wms(
this.mapParams.getUrl(this.lang),
this.mapParams.getOptions()
)
break
case 'Online':
if (!this.mapParams.mapTileOptions['subdomains']) {
this.$Message(`'MapTileOptions.subdomains' ${
this.$t( 'gisMap.map.warning.noCfg')}`,'warning')
}
this.mapParams.mapTileOptions.format = this.mapParams.mapTileOptions
.format
? this.mapParams.mapTileOptions.format
: 'image/png'
this.map.tileLayer = new L.tileLayer(
// 直接替换注释即可
// '//webrd0{s}.is.autonavi.com/appmaptile?&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
this.mapParams.getUrl(this.lang),
// { subdomains: [ '1', '2', '3', '4' ], format:'image/png'}
this.mapParams.getOptions()
)
break
default:
throw `Unknow UseMapType '${
this.mapParams.useMapType}'\r\nOnly support: 'Offline','Online','Custom'`
}
// 添加到地图
this.map.tileLayer.addTo(this.map.instance)
this.initRecord.tile.value = true
} catch (error) {
this.initRecord.tile.value = false
if (error) {
this.initRecord.tile.result = error
this.$Message(
`${
this.$t('gisMap.map.error.loadTile')}: ${
error}`,
'error'
)
}
throw error
}
},
// 为地图加载遮罩,只显示默认区域
async mapLoadMask() {
try {
const re = await districtApi.getPolyline(this.mapParams.adCode)
// 内多边形数组
var boundaries = JSON.parse(re)
// 外多边形数组
var outer = [
[90, -360],
[-90, -360],
[-90, 360],
[90, 360]
]
var pathArray = [outer]
pathArray.push.apply(pathArray, boundaries)
// https://leafletjs.com/reference-1.6.0.html#polyline
var polygon = new L.polygon(pathArray, {
// 线条颜色,使用16进制颜色代码赋值。默认值为#006600
color: 'rgb(122,122,122)',
// 线条宽度
weight: 2,
// 轮廓线透明度,取值范围[0,1],0表示完全透明,1表示不透明。默认为0.9
opacity: 0.8,
// 是否用颜色填充路径
fill: true,
// 多边形填充颜色,使用16进制颜色代码赋值,如:#FFAA00
fillColor: 'rgba(250, 250, 250, 0.95)',
// 多边形填充透明度,取值范围[0,1],0表示完全透明,1表示不透明。默认为0.9
fillOpacity: 1
// 轮廓线样式,实线:solid,虚线:dashed
//strokeStyle: 'dashed',
// 勾勒形状轮廓的虚线和间隙的样式,此属性在strokeStyle 为dashed 时有效, 此属性在
// ie9+浏览器有效 取值:
// 实线:[0,0,0]
// 虚线:[10,10] ,[10,10] 表示10个像素的实线和10个像素的空白(如此反复)组成的虚线
// 点画线:[10,2,10], [10,2,10] 表示10个像素的实线和2个像素的空白 + 10个像素的实
// 线和10个像素的空白 (如此反复)组成的虚线
// strokeDasharray: [0, 0, 0]
})
polygon.addTo(this.map.instance)
console.log('蒙版绘制polygon完成')
this.map.maskLayer = polygon
this.initRecord.mask.value = true
} catch (error) {
this.initRecord.mask.value = false
if (error) {
this.initRecord.mask.result = error
this.$Message(
`${
this.$t('gisMap.map.error.loadMask')}: ${
error}`,
'error'
)
} else {
this.$Message(this.$t('gisMap.map.error.loadMask'), 'error')
}
throw error
} finally {
this.loading = false
}
},
this.map.instance.on('move', (e) => {
if (this.map.maskLayer)
// 会损失性能,自己斟酌把
this.map.maskLayer._renderer._update() //扒对象实例扒到的,_renderer是渲染出来的path
})
mapRegisterEvent() {
this.map.instance.on('moveend', this.mapViewChange)
this.map.instance.on('zoomend', this.mapViewChange)
},
mapUnregisterEvent() {
this.map.instance.off('moveend', this.mapViewChange)
this.map.instance.off('zoomend', this.mapViewChange)
},
async mapViewChange() {
const zoom = this.map.instance.getZoom() // 获取当前地图缩放级别
const center = this.map.instance.getCenter() // 获取当前地图中心位置
const boud = this.map.instance.getBounds()
this.map.otherLayer.clearLayers()
console.log('当前缩放级别:', zoom)
console.log('当前中心位置:', center)
console.log('当前边界:', boud)
if (this.mapParams.searchDistance === 0) {
...
} else if (this.mapParams.searchDistance === -1) {
...
} else if (this.flag.clickMarker && this.flag.autoPaning) {
return
} else if (
this.lastCenter.lat &&
this.lastCenter.lng &&
this.map.instance.distance(center, this.lastCenter) <=
this.mapParams.minMoveDistance
) {
console.log('移动的距离小于' + this.mapParams.minMoveDistance)
return
}
this.fillMarkerDeb()
},
import _markerItem from '../components/markerItem'
const markerItem = Vue.extend(_markerItem)
// ##标记点相关
createMarker(deviceInfo) {
// https://leafletjs.com/reference-1.6.0.html#marker
const marker = new L.marker([deviceInfo.lat, deviceInfo.lng], {
title: deviceInfo.name,
// 鼠标在marker上方时,是否置顶
riseOnHover: true
})
marker.data = deviceInfo
marker.props = {
isTop: false,
loading: false,
animationName: 'uiot-map-marker_add'
}
marker.setAnimation = function (name) {
// if (this.props.animationName) {
// this._icon.classList.remove(this.props.animationName)
// }
this.props.animationName = `uiot-map-marker_${
name}`
// this._icon.classList.add(this.props.animationName)
}
marker.setLoading = function (val) {
// console.log(this._icon)
this.props.loading = val
}
marker.setTitle = function (title) {
this._icon.setAttribute('title', title)
}
marker.show = function () {
this._icon.style.display = ''
}
marker.hide = function () {
this._icon.style.display = 'none'
}
marker.setTop = function () {
if (this._map?.$lastTopMarker) {
if (this._map.$lastTopMarker._leaflet_id === this._leaflet_id) {
console.log('setTop 不用置顶', this._map.$lastTopMarker)
return
} else {
console.log('setTop 还原', this._map.$lastTopMarker)
this._map.$lastTopMarker.setZIndexOffset(0)
}
}
this.setZIndexOffset(240)
this._map.$lastTopMarker = this
}
const markerVue = new MarkerConstructor({
propsData: {
marker: marker
}
}).$mount()
marker._vue = markerVue
marker.setIcon(
new L.divIcon({
html: markerVue.$el
})
)
marker.on('click', this.markerClick)
marker.addTo(this.map.markerLayer)
return marker
},
marker.setTitle = function (title) {
//_icon就是图标的dom节点
this._icon.setAttribute('title', title)
}
<template>
<div :class="['marker__wrap',marker.props.animationName]"
v-loading="loading"
ref="panel">
<img :id="marker.data.id"
:class="['marker-icon']"
:src="markerIcon" />
</div>
</template>
export default {
name: 'MarkerItem',
props: ['marker'],
mounted() {
// setTimeout(() => {
// if (this.marker.props.animationName === 'uiot-map-marker_add')
// this.marker.props.animationName = 'uiot-map-marker_none'
// }, 500)
},
computed: {
loading() {
return this.marker.props.loading
},
markerIcon() {
return getMarkerIcon(this.marker.data)
}
}
}
.leaflet-div-icon {
margin: 0 !important;
width: auto !important;
height: auto !important;
background: transparent !important;
border: none !important;
.marker-icon-panel {
float: left;
display: flex;
// IE需要设置宽度或者最小宽度,不然显示不出来
height: auto;
width: auto;
min-width: 22px;
.marker-icon {
flex: auto;
}
}
}
// 代码见3.1的setTop方法
marker.setTop = function () {
if (this._map?.$lastTopMarker) {
if (this._map.$lastTopMarker._leaflet_id === this._leaflet_id) {
console.log('setTop 不用置顶', this._map.$lastTopMarker)
return
} else {
console.log('setTop 还原', this._map.$lastTopMarker)
this._map.$lastTopMarker.setZIndexOffset(0)
}
}
this.setZIndexOffset(240)
this._map.$lastTopMarker = this
}
.uiot-map-marker_none {
animation: none;
}
.uiot-map-marker_flashing {
animation: flashing 400ms infinite;
animation-fill-mode: forwards;
}
.uiot-map-marker_bounce {
animation: bounce 1000ms infinite;
animation-fill-mode: forwards;
}
let timeout = this.getAnimationTime(animation)
this.dicMarker[id].setAnimation(animation)
console.log('开始动画', this.dicMarker[id])
this.lastJumping.timer = setTimeout(() => {
this.lastJumping.clear()
console.log('取消动画', this.dicMarker[id])
this.dicMarker[id].setAnimation('none')
this.flag.jumpMarker = false
//this.mapRegisterEvent()
this.showMarker(this.dicMarker[id].data)
}, timeout)
marker实例.setLoading(false or true)
createInfoWindow() {
// https://blog.csdn.net/qq_39512863/article/details/90483781
// https://leafletjs.com/reference-1.6.0.html#popup
this.mapInfoWindow = new L.popup({
// 是否自动调整窗体到视野内(当信息窗体超出视野范围时,通过该属性设置是否自动平移地图,使信息窗体完全显示)
autoPaning: true,
// 开启keepInView,在切后台时可能会导致一直触发autupandstart事件,建议关闭
// keepInView: true,
// 弹出位置偏移量,可根据标记点图标大小修改
offset: new L.point(10, 0)
})
console.log('createInfoWindow', this.$refs.infowindow)
this.mapInfoWindow.setContent(this.$refs.infowindow.$el)
// this.mapInfoWindow.on('popupclose', this.infoWindowClosed)
this.map.instance.on('popupclose', this.infoWindowClosed)
},
async showMarker(info, latlng) {
if (info && info.id) {
if (
this.dicMarker[info.id] &&
this.dicMarker[info.id].props.loading === false
) {
this.dicMarker[info.id].setLoading(true)
this.mapInfoWindow.setLatLng(latlng ? latlng : [info.lat, info.lng])
try {
var extend = await markerApi.queryProps(info.id)
this.showDeviceInfo.error = false
this.showDeviceInfo.extend = extend ? extend : {
}
} catch (error) {
console.error('showMarker error: ', error)
this.showDeviceInfo.error = true
} finally {
this.showDeviceInfo.baseInfo = info
if (this.dicMarker[info.id]) {
this.dicMarker[info.id].setLoading(false)
}
this.$nextTick(() => {
// 如果直接open, leaflet获取不到infowindow的实际高度的(获取到也是上一次的)
// 所以一定要加上nextTick
this.mapInfoWindow.update()
this.mapInfoWindow.openOn(this.map.instance)
})
}
}
}
},
文章浏览阅读1.4k次。1. 基本功能函数使用讲解import torchvision# root 数据集位置,train 训练集或测试集,download 是否下载train_set = torchvision.datasets.CIFAR10( root ="./dataset",train=True,download=True)test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True)print(t._torchvision annfile
文章浏览阅读746次。【ML&Py】×阿里云天池Python训练营(day4打卡)——1.字符串、2.字典一、学习概览1.1 学习地址:[阿里云天池python训练营](https://tianchi.aliyun.com/specials/promotion/aicamppython)1.2 思维导图二、具体学习内容2.1 字符串2.1.1 字符串的定义2.1.2 字符串的切片与拼接2.1.3 字符串的常用内置方法2.1.4 字符串格式化2.2 字典2.2.1 可变类型与不可变类型2.2.2 字典的定义2.2.3 创建_阿里云天池python训练营,学习打卡 day5
文章浏览阅读1.6k次。 题目描述: AVL树是一种自平衡二叉搜索树。在AVL树中,任意节点的两个子树的高度最多相差1。如果在任何时候它们的差超过1,则会进行重新平衡以恢复此属性。旋转规则如下图所示。 现给定一个插入序列,需要得到的AVL树的根。 输入格式: 每个输入文件包含一个测试用例。 对于每种情况,第一行包含一个正整数N(⩽\leqslant⩽ 20),为要插入的元素的总数。 然后在下一行给出N个不同的整数元素。 一行中的所有数字都用空格隔开。 输出格式: 对于_在avl树中,任何节点的两个子树的高度最多相差1;如果它们高度相差不止1,则需要重新
文章浏览阅读7.2k次,点赞13次,收藏74次。分别来用keras实现通道注意力模块和空间注意力模块。#通道注意力机制def channel_attention(input_feature, ratio=8): channel_axis = 1 if K.image_data_format() == "channels_first" else -1 channel = input_feature._keras_shape[channel_axis] shared_layer_one = Dense(channel//rat....._kernel_initializer='he_normal
文章浏览阅读2.3k次。在业务中会遇到同一个项目需要使用多个数据源来读取数据,这种情况下就要更改Mybatis的相关配置,本篇将介绍如何去引入多数据源,同时其中会遇到的一些坑也会指出。同时也会说一下如何使用Mybatis Generator。找到配置文件,配置第二个数据源配置system_config_dev.properties文件可能不同 不过大同小异############## dataSource..._mybatis generrator 配置多个db
文章浏览阅读3.9w次,点赞23次,收藏59次。最近在折腾Ubuntu,安装的是17.04版本的。想安装PHP7.X最新版本,但是要先升级。利用sudo apt-get update命名后,出现了以下报错:忽略:1 http://cn.archive.ubuntu.com/ubuntu zesty InRelease忽略:2 http://cn.archive.ubuntu.com/ubuntu zesty-updates InRelease忽_ubuntu 17.04 update
文章浏览阅读3.7k次。 课件下载 : 方式1:本节课件下载地址: https://pan.baidu.com/s/1D-MvbRcJRoyiA456xsTvMQ 密码:rzlr方式2:或点击此处下载 效果图: 代码示例:Sub tongji()Dim i, k, l, m As IntegerFor i = 2 ..._application.worksheetfunction.countif
文章浏览阅读2.4w次,点赞15次,收藏91次。4.4 数据的寻址方式4.4.1 指令和数据的寻址方式4.4.2 数据寻址方式说明4.4.3 立即寻址4.4.4 直接寻址4.4.1 指令和数据的寻址方式寻址方式:确定本条指令的数据地址或下一条要执行的指令地址的方法。4.4.2 数据寻址方式说明目的操作数和源操作数均可采用不同的寻址方式;两个操作数的类型必须一致。AX表示16位寄存器,AH、AL表示其高低字节,可单独使用。4.4.3 立即寻址操作数就在指令中,紧跟在操作码后面,作为指令一部分存放在内存的代码段中,该操作数为立即数,这种寻址_存储器间接寻址
文章浏览阅读4.4k次,点赞8次,收藏42次。好久没更新了。这几天研究了DPLL提取位同步时钟的FPGA实现。DPLL和PLL一样,由鉴相器、环路滤波器和数控振荡器组成。下面就是DPLL的基本框图。1.超前-滞后性数字鉴相器鉴相器的功能是检测本地估量信号和输入信号sigIn的相位关系。但只提取输入信号sigIn边沿处的相位关系。所以我们先由D触发器和异或门获得携带输入信号边沿信息的脉冲序列。在输入信号sigIn边沿处,如果本地
文章浏览阅读1.2k次。第一个Hyperledger项目达到2.0里程碑,提高了企业区块链的标准新版本针对分散式链码功能,私有数据增强功能和改进的性能进行了生产部署优化加利福尼亚州旧金山–(2020年1月30日)–Hyperledger是一项旨在促进跨行业区块链技术的开源协作成果,今天宣布Hyperledger Fabric 2.0全面上市。Hyperledger Fabric的主要版本是一种分布式账本框架,..._hyperledger fabric2.0 是什么
文章浏览阅读515次。基础知识1:UIWebView是iOS内置的浏览器控件,系统自带的Safari浏览器就是通过UIWebView实现的.UIWebView不但能加载远程的网页资源,还能加载绝⼤部分的常见文件 html\htm pdf、doc、ppt、txt mp4 ......MIME的英文全称是“Multipurpose Internet Mail Extensions” 多用途互联网邮件扩展,是一个互联网标准..._uiwebview 去掉bottom_height
文章浏览阅读1k次。给定N个点的一维数组 的离散傅里叶变换对由下面两式给出:离散傅里叶变换是将离散信号分解为多个离散三角函数,并能给出每个三角函数的幅值 、频率 、初相位 .即找一批函数形如:来叠加出任意给定的离散信号.只要知道了 ,这个三角函数就完全知道了.下面用具体的程序说明这个两个公式的具体含义及用法,本文演示所用的编程语言为python3.首先导入一些必要的包,以及定义一个方波信号,并画出一段时间的图像:..._离散数据集变成傅里叶表达式