标题一、shpjs将.zip文件转成geoJson
一、npm install shpjs
二、import shp from 'shpjs'
三、
async setLayerSource() {
const geoJsonData = await shp(dataUrl)
}
一直报错:是因为Buffer这个插件一直没找到
Uncaught Error: nodebuffer is not supported by this browser
解决办法
npm install node-polyfill-webpack-plugin
vue.config.js
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
module.exports = {
configureWebpack: (config) => {
config.plugins.push(new NodePolyfillPlugin())
}
}
标题二、source加载 url + format加载图层,获取source数据::source.on('change')
标题三、加载点图层时使用图片::,可设置 new Icon({anchor:[0.5,0.5]})默认是图片中心点和位置点点吻合
标题四、
kml格式的数据,设置的图层样式未生效::有个new KML({extractStyles: true})属性,是否使用kml文件中的样式。默认是true
四 、
根据title获取图层数组后,执行删除后,图层未被删除
removeLayers (title) {
const layers = this.getLayers({ title })
for (let i = 0; i < layers.length; i++) {
if (layers[i]) {
layers[i]?.getSource()?.clear()
this.map.removeLayer(layers[i])
}
}
// 使用forEach循环删除,是不生效的 layers.forEach(layer => map.removeLayer(layer))
// 修改为 for循环进行图层删除
}
五、将地图导出成图片:1.获取地图上得图层canvas 2.html2canvas将图例等自行写得dom转成canvas
遇到得问题:1.在屏幕做了缩放后,图例dom位置不对 2. 标题等打印出来后,文字底部不全
解决方法:1.根据屏幕缩放比重新计算dom得top、left位置 2. 更换html2canvas版本
其他问题:
1. 文字样式丢失且都变成为最小号字体。
解决方案: 需要截图的节点根样式添加font-variant: normal;
2. 文字向下偏移。
解决方案: 指定html2canvas的版本号为1.0.0-alpha.12
3. 不完整,缺失,留白。
出现情况: 当截图区域超过视图高度,且滚动条未处在顶部时,会出现。
解决方案: 截图之前控制滚动条至顶部。
4. 模糊,不清晰。
出现情况: 通常是图片设置为背景的情况下,截图会比较模糊。
解决方案: 将背景图通过img标签加定位的方式实现
// 地图图层、标题、比例尺、图例导出
exportMapLayers(config = {}) {
let { exportImgName, titleDomId, titleLeft, titleTop, legendDomId, legendLeft, legendTop, isExportScale, scaleLeft, scaleTop } = config
this.map.once('postrender', () => {
// openayer做了适配屏幕分辨率,我只取图层类得canvas
let canvasDom = document.querySelectorAll('.mapContainerClass > .ol-viewport > .ol-layers > .ol-layer > canvas')
if (canvasDom?.length) {
let newCanvas = document.createElement('canvas')
newCanvas.width = canvasDom[0].width
newCanvas.height = canvasDom[0].height
newCanvas.backgroundColor = 'rgba(0,0,0,0)'
for (let i = 0; i < canvasDom.length; i++) {
if (canvasDom[i]) {
newCanvas.getContext('2d').drawImage(canvasDom[i], 0, 0)
}
}
let promiseArr = []
// 动态图标使用overlay实现的,也许导出,还有其他需要导出的overlay,人为加一个class进行区分
let cloneOverlayDoms = document.querySelector('.ol-overlaycontainer-stopevent').cloneNode(true)
let cloneChildNodes = cloneOverlayDoms.childNodes
if (cloneChildNodes?.length) {
let removeList = []
cloneChildNodes.forEach((node) => {
if (!node.classList.contains(exportOverlayStr)) {
removeList.push(node)
}
})
for (let i = 0; i < removeList.length; i++) {
cloneOverlayDoms.removeChild(removeList[i])
}
document.body.appendChild(cloneOverlayDoms)
let overlayPromise = this.createPromiseDomToCanvas(cloneOverlayDoms, 0, 0, newCanvas, 'overlay')
promiseArr.push(overlayPromise)
}
if (titleDomId) {
let titleDom = document.getElementById(titleDomId) // titleId
if (titleDom) {
let titlePromise = this.createPromiseDomToCanvas(titleDom, titleLeft, titleTop, newCanvas)
promiseArr.push(titlePromise)
}
}
if (legendDomId) {
let legendDom = document.getElementById(legendDomId)
if (legendDom) {
let legendPromise = this.createPromiseDomToCanvas(legendDom, legendLeft, legendTop, newCanvas)
promiseArr.push(legendPromise)
}
}
if (isExportScale) {
let scaleLineDom = document.querySelector('.ol-scale-line')
if (scaleLineDom) {
let scalePromise = this.createPromiseDomToCanvas(scaleLineDom, scaleLeft, scaleTop, newCanvas)
promiseArr.push(scalePromise)
}
}
if (promiseArr.length) {
Promise.all(promiseArr).then(() => {
this.canvasToImage(newCanvas, exportImgName)
})
} else {
this.canvasToImage(newCanvas, exportImgName)
}
}
})
this.map.renderSync()
},
// 将dom元素转成canvas
createPromiseDomToCanvas(dom, domLeft, domTop, newCanvas,type) {
let tp = document.documentElement.clientTop
let lt = document.documentElement.clientLeft
//屏幕缩放比
const screenScale = getScreenScale()
return new Promise((resolve) => {
html2canvas(dom, { backgroundColor: null, allowTaint: true, useCORS: true, scrollY: 0, scrollX: 0 }).then((domCanvas) => {
let ctx = newCanvas.getContext('2d')
domCanvas.backgroundColor = 'rgba(0,0,0,0)'
if (type === 'overlay') {
ctx.drawImage(domCanvas, 0, 0)
document.body.removeChild(dom)
} else {
let mapDomBounding = document.querySelector('.mapContainerClass')?.getBoundingClientRect()
let mapTopToView = mapDomBounding?.top || 0 // 地图元素距离视窗顶部的的距离
let mapLeftToView = mapDomBounding?.left || 0 // 地图元素左边框距离视窗左边的的距离
let domRect = dom?.getBoundingClientRect()
let domTopToView = domRect?.top // 元素上边框距离视窗顶部的的距离
let domLeftToView = domRect?.left // 元素左边框距离视窗左边的的距离
let finalX = (isNullText(domLeft) ? domLeftToView - lt - mapLeftToView : domLeft) * screenScale
let finalY = (isNullText(domTop) ? domTopToView - tp - mapTopToView : domTop) * screenScale
ctx.drawImage(domCanvas, finalX, finalY)
}
resolve('success')
})
})
},
// 将canvas元素转成图片
canvasToImage(newCanvas, exportImgName) {
var url = newCanvas.toDataURL('image/jpeg')
var a = document.createElement('a')
a.href = url
var event = new MouseEvent('click')
// 指定下载图片的名称
a.download = exportImgName || new Date().getTime() + '.jpg'
a.dispatchEvent(event)
},
utils.js
//获取屏幕缩放比例
export const getScreenScale = () => {
var screenScale = 1
var screen = window.screen
var ua = navigator.userAgent.toLowerCase()
//设备像素比
if (window.devicePixelRatio !== undefined) {
screenScale = window.devicePixelRatio
//IE11以下版本浏览器
} else if (ua.indexOf('msie') > -1) {
if (screen.deviceXDPI && screen.logicalXDPI) {
screenScale = screen.deviceXDPI / screen.logicalXDPI
}
//浏览器自身缩放
} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
screenScale = window.outerWidth / window.innerWidth
}
if (screenScale) {
screenScale = Math.round(screenScale * 100) / 100
}
return screenScale
}
六、增加一个指南针图片,图片旋转跟地图旋转做联动
data() {
return {
isMovingMouse: false, // 鼠标是否在移动
originPoint: {}, // 旋转前的点位置
finalPoint: {}, // 旋转后的点位置
rotateCount: 0
}
}
mounted(){
this.map.on(
'moveend',
debounce((evt) => {
this.mapMoveEnd(evt)
}, 600),
this
)
// 点击了openlayer得controls中rotate,角度复位后触发得
let rotateIconDom = document.querySelector('.ol-rotate-reset')
if (rotateIconDom) {
rotateIconDom.addEventListener('click', () => {
this.setCompassIconRotateDeg(0)
})
}
}
methods:{
// 地图移动/zoom变化结束
mapMoveEnd(evt) {
if (evt.dragging) {
return
}
let mapRotation = this.map?.getView()?.getRotation() // 为数值,单位不是度,180度对应数值PI
let compassIconDeg = (mapRotation / Math.PI) * 180
this.setCompassIconRotateDeg(compassIconDeg)
},
// 按下图标
handleIconDown(e) {
e.preventDefault()
e.stopPropagation()
this.isMovingMouse = true
if (this.rotateCount < 1) {
this.originPoint = {
x: e.pageX,
y: e.pageY
}
this.rotateCount++
}
document.onmousemove = (event) => {
event.preventDefault()
event.stopPropagation()
if (this.isMovingMouse) {
this.finalPoint = {
x: event.pageX,
y: event.pageY
}
let allRotateDeg = (Math.atan2(this.finalPoint.y - this.originPoint.y, this.finalPoint.x - this.originPoint.x) * 180) / Math.PI
if (this.setCompassIconRotateDeg(allRotateDeg)) {
let mapRotation = (allRotateDeg / 180) * Math.PI
this.map.getView().setRotation(mapRotation)
}
}
}
},
// 鼠标从指北针图标上抬起
handleIconUp() {
this.isMovingMouse = false
},
// 设置指北针图标的旋转角度
setCompassIconRotateDeg(deg) {
let compassIconDom = document.querySelector('.compassIcon')
if (compassIconDom) {
compassIconDom.style.transform = 'rotate(' + deg + 'deg)'
}
return compassIconDom
}
}