Vue.js2+OpenLayers6 五、标绘(添加自定义文字标注)

Vue.js2+OpenLayers6 五、标绘(添加自定义文字标注)

Demo

Github

示例

<template>
	<div id="map-container" style="width:100%;height:100%;">
		<!-- DOM 元素覆盖图层 -->
		<div style="display:none">
			<div ref="positioning" style="width:50px;height:50px;">
				<img :src="positioningUrl" width="100%" alt="" />
			</div>
		</div>
		<!-- DOM 元素覆盖图层 E -->
		<div style="position:absolute;right:50px;top:50px;z-index:999;">
			<button @click="addSymbolMarkers(markersData)">添加标注</button>
			<button @click="clearSymbolMarkers()">清除</button>
			<div>
				点击已添加的标注,视图中心切换到标注位置,并添加覆盖物图层
			</div>
		</div>
	</div>
</template>
<script>
/* eslint-disable no-unused-vars */
import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
import TileWMS from 'ol/source/TileWMS'
import OSM from 'ol/source/OSM'
import { defaults as defaultControls } from 'ol/control'
import ZoomSlider from 'ol/control/ZoomSlider'

import OlFeature from 'ol/Feature'
import OlGeomPoint from 'ol/geom/Point'
import OlLayerVector from 'ol/layer/Vector'
import OlSourceVector from 'ol/source/Vector'
import OlStyleStyle from 'ol/style/Style'
import OlStyleIcon from 'ol/style/Icon'
import OlStyleText from 'ol/style/Text'
import OlStyleFill from 'ol/style/Fill'
import OlStyleStroke from 'ol/style/Stroke'

import OlOverlay from 'ol/Overlay'
import { easeIn, easeOut } from 'ol/easing'

export default {
	name: '',
	data() {
		return {
			positioningUrl: require('@/assets/images/positioning.gif'),
			markersData: [
				{
					address: 'marker1',
					x: 116.40182752977934,
					y: 39.92476619935702,
					type: 1,
				},
				{
					address: 'marker2',
					x: 116.42764915596571,
					y: 39.949683921105375,
					type: 2,
				},
				{
					address: 'marker3',
					x: 116.48107607733336,
					y: 39.88376327014636,
					type: 2,
				},
				{
					address: 'marker4',
					x: 116.34883914958563,
					y: 39.96384062028598,
					type: 3,
				},
				{
					address: 'marker5',
					x: 116.3174412108573,
					y: 39.86192606545161,
					type: 3,
				},
			],
			map: null,
		}
	},
	mounted() {
		this.initMap()
	},
	methods: {
		/**
		 * @name: 清除标注
		 */
		clearSymbolMarkers() {
			this.removeOverLay('定位')
			this.removeLayerByName('矢量标注图层')
		},

		/**
		 * @name: 切换中心点
		 * @param {centerPoint} Array 中心点
		 */
		changeCenterPoint(centerPoint) {
			this.map.getView().animate({
				center: centerPoint,
				duration: 500,
				easing: easeOut,
			})
		},

		/**
		 * @name: 清除覆盖图层
		 * @param {ID} String 覆盖图层 ID
		 */
		removeOverLay(ID) {
			const layer = this.getOverlays(ID)
			this.map.removeOverlay(layer)
		},

		/**
		 * @name: 获取覆盖图层
		 * @param {ID} String
		 */
		getOverlays(ID) {
			if (ID) {
				// 获取指定 ID 的覆盖物图层
				const overlay = this.map.getOverlayById(ID)
				return overlay
			} else {
				// 获取所有覆盖物图层
				const layers = this.map.getOverlays().getArray()
				return layers
			}
		},

		/**
		 * @name: 添加覆盖图层
		 * @param {point} Array
		 * @param {layerName} String 自定义覆盖图层的 ID,用于清除图层
		 */
		addOverlayFun(point, layerID) {
			const id = layerID || ''
			this.removeOverLay(id)
			const marksDOM = this.$refs.positioning
			const overlay = new OlOverlay({
				id: id,
				position: point,
				positioning: 'center-center',
				element: marksDOM,
				stopEvent: false,
				className: 'positioning',
			})
			this.map.addOverlay(overlay)
		},

		/**
		 * @name: 根据图层名移除图层
		 * @param {layername} 图层名称
		 */
		removeLayerByName(layerName) {
			this.getLayerByName(layerName)
			const layer = this.getLayerByName(layerName)
			layer.forEach(item => {
				this.map.removeLayer(item)
			})
		},

		/**
		 * @name: 根据图层名获取图层
		 * @param {layerName} 图层名称
		 */
		getLayerByName(layerName) {
			const allLayers = this.getAllLayers()
			const layer = allLayers.filter(item => {
				return item.get('name') === layerName
			})
			return layer
		},

		/**
		 * @name: 获取所有图层
		 */
		getAllLayers() {
			const layers = this.map.getLayers().getArray()
			return layers
		},

		/**
		 * @name: 设置标注文字样式
		 * @param {text}
		 * @param {img}
		 */
		setSymbolStyle(text, img) {
			const Styles = []
			Styles.push(
				new OlStyleStyle({
					// 设置图标
					image: new OlStyleIcon({
						src: img,
						anchor: [0.5, 1],
						scale: 0.5,
					}),
					// 设置图片下面显示字体的样式和内容
					text: new OlStyleText({
						font: '14px sans-serif', // 设置字体
						maxAngle: 30,
						offsetx: 10, // 设置文字偏移量
						offsetY: 10,
						text: text, // 文字描述
						fill: new OlStyleFill({
							// 字体颜色
							color: '#000',
						}),
						stroke: new OlStyleStroke({
							// 文字描边
							color: '#fff',
							width: 5,
						}),
					}),
				})
			)
			return Styles
		},

		/**
		 * @name: 添加自定义矢量标注
		 * @param {data} Array
		 */
		addSymbolMarkers(data) {
			let img = ''
			const vectorLayer = new OlLayerVector({
				source: new OlSourceVector(),
				zIndex: 9,
				name: '矢量标注图层',
			})
			this.map.addLayer(vectorLayer)
			const features = []
			for (let i = 0; i < data.length; i++) {
				if (data[i].type === 1) {
					img = require('@/assets/images/ico01.png')
				} else if (data[i].type === 2) {
					img = require('@/assets/images/ico02.png')
				} else {
					img = require('@/assets/images/ico03.png')
				}
				// 创建 Feature
				const feature = new OlFeature({
					geometry: new OlGeomPoint([data[i].x, data[i].y]),
					data: data[i], // 数据存储到 feature 中用来做点击事件
				})
				feature.setStyle(this.setSymbolStyle(data[i].address, img)) // 设置样式
				features.push(feature)
			}
			vectorLayer.getSource().addFeatures(features)
		},

		/**
		 * @name: 地图单击事件
		 */
		singleClickFun() {
			this.map.on('singleclick', event => {
				console.log(event)
				const feature = this.map.forEachFeatureAtPixel(
					event.pixel,
					// eslint-disable-next-line no-unused-vars
					(feature, layer) => {
						return feature
					}
				)
				if (feature) {
					// 点击到标注
					const symbolData = feature.get('data')
					const centerPoint = [symbolData.x, symbolData.y]
					this.changeCenterPoint(centerPoint)
					this.addOverlayFun(centerPoint, '定位')
				}
			})
		},

		/**
		 * @name: 初始化地图
		 */
		initMap() {
			const view = new View({
				projection: 'EPSG:4326',
				center: [116.395645038, 39.9299857781],
				zoom: 12,
			})
			const layer = new TileLayer({
				source: new OSM(),
				visible: true,
				zIndex: 1,
				name: 'OSM',
			})
			this.map = new Map({
				layers: [],
				target: 'map-container',
				view: view,
				controls: defaultControls().extend([new ZoomSlider()]),
			})
			this.map.addLayer(layer)
			this.singleClickFun()
		},
	},
}
</script>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vtk.js是一个用于可视化的JavaScript库。它基于WebGL和HTML5 Canvas,可以用于在Web浏览器中创建复杂的3D可视化场景。vtk.js提供了许多强大的功能,包括创建和编辑3D模型、应用纹理和光照、执行体积渲染和交互式操作等。使用vtk.js,开发人员可以轻松地构建逼真的3D可视化应用程序,以满足各种领域的需求,如科学研究、医学图像处理和计算机辅助设计等。 Vue.js是一个用于构建用户界面的前端框架。它的核心特是响应式的数据绑定和组件化的架构。Vue.js采用了基于HTML模板的开发方式,使得开发人员可以更简单地构建高效、可复用的用户界面。Vue.js支持双向数据绑定和组件化的开发风格,使得开发人员可以更容易地管理和维护复杂的前端应用程序。Vue.js也提供了丰富的生态系统,包括路由、状态管理、构建工具等,使得开发人员可以更高效地开发出高质量的前端应用程序。 XML是一种可扩展标记语言,用于描述和传输结构化数据。XML使用标签来标识数据的结构和内容,并且是一种纯文本格式,具有良好的跨平台和跨语言的特性。XML可以被用于各种应用场景,如数据交换、配置文件、Web服务等。XML具有可扩展性,可以自定义标签和数据结构,适用于复杂的数据模型和数据交互需求。同时,XML也可以通过解析器进行解析和处理,使得开发人员可以方便地操作和处理XML数据。在Web开发中,XML通常与相关技术如XSLT、XPath和SOAP等一起使用,用于数据传输、样式表转换和WebService调用等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值