起因
前面一段时间一直在写前端地图相关的项目,因为一些原因不让用arcgisJS了,所以开始用openlayer。刚好要做一个截图的功能,因为之前是arcgis的话其实有现成的能用
后面换成openlayer后并没有找到类似的功能(现在有没有不清楚),所以只能自己写一个了。
实现
原理其实很简单,我们把截图功能进行拆分,首先是框选功能,它允许用户选择一个区域。这个其实可以直接用一个div盒子就能实现,盒子大小会随着鼠标位置的移动而改变。第二步就是拿第一步得到的div盒子的位置和大小信息读取地图上对应范围的内容,然后生成一张图片。第二步在openlayer中有相应的API,后面如果有时间我会更新相应内容。这次就先简单地写一下第一步的功能。
上面已经说了,第一步其实就是appendChild一个div盒子,事件的触发应该是点击特定的按钮,我这里只是展示一下原理,就直接写在window上了
window.addEventListener("mousedown", (e) => {})
记录鼠标点下去时的那个点
const [startX, startY] = [e.clientX, e.clientY]
实际在写项目的时候可能有侧边栏这种东西,那么可能就不能直接使用clientPosition了,自己计算一下就行了
然后添加一个div盒子
const divDom = document.createElement("div")
divDom.id = 'screenshot'
divDom.width = '1px'
divDom.height = '1px'
divDom.style.position = "absolute"
divDom.style.top = startY + "px"
divDom.style.left = startX + "px"
document.body.appendChild(divDom)
#screenshot {
border: 2px solid black;
}
然后就是改变盒子的大小了,这时候就还要添加一个mousemove事件了,当鼠标移动的时候改变盒子的大小,这里要分情况讨论
首先就是我们鼠标向右方或者下方移动,这时候mouseevent中的clientX和Y就会大于startX和Y,此时盒子的宽或高就是两者的差值
const moveEvent = (e) => {
const moveX = e.clientX - startX
const moveY = e.clientY - startY
if (moveX > 0) {
divDom.style.width = moveX + 'px'
}
if (moveY > 0) {
divDom.style.height = moveY + 'px'
}
}
window.addEventListener("mousemove", moveEvent)
如果鼠标移动的方向时左上,这时候mouseevent中的clientX和Y就会小于startX和Y,所以这里moveX或Y是负数,我们要在前面加个负号,并且从实现效果上来讲,实际不动的那个点应该在右下方,仅改变盒子大小是不行的,还要改变盒子的位置,此时盒子的位置就要设置为鼠标移动的位置
这部分完整代码
if (moveX > 0) {
divDom.style.width = moveX + 'px'
} else {
divDom.style.width = -moveX + 'px'
divDom.style.left = e.clientX + 'px'
}
if (moveY > 0) {
divDom.style.height = moveY + 'px'
} else {
divDom.style.height = -moveY + 'px'
divDom.style.top = e.clientY + 'px'
}
最后是结束截图,即鼠标松开时触发。
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", moveEvent)
})
这样就写完了,很简单,看一下效果
没有问题,下面是完整的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
#screenshot {
border: 2px solid black;
}
</style>
</head>
<body>
</body>
<script>
window.addEventListener("mousedown", (e) => {
const [startX, startY] = [e.clientX, e.clientY]
const divDom = document.createElement("div")
divDom.id = 'screenshot'
divDom.width = '1px'
divDom.height = '1px'
divDom.style.position = "absolute"
divDom.style.top = startY + "px"
divDom.style.left = startX + "px"
document.body.appendChild(divDom)
const moveEvent = (e) => {
const moveX = e.clientX - startX
const moveY = e.clientY - startY
if (moveX > 0) {
divDom.style.width = moveX + 'px'
} else {
divDom.style.width = -moveX + 'px'
divDom.style.left = e.clientX + 'px'
}
if (moveY > 0) {
divDom.style.height = moveY + 'px'
} else {
divDom.style.height = -moveY + 'px'
divDom.style.top = e.clientY + 'px'
}
}
window.addEventListener("mousemove", moveEvent)
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", moveEvent)
})
})
</script>
</html>
结语
前面已经说了,这个只是实现截图框的功能,很简单。通过这一步我们能够拿到截图框的信息,也就是截图的范围,第二步通过这些信息读取地图上的内容生成图片便可以实现截图的功能,因为opanlayer有现成的API(https://openlayers.org/en/latest/examples/export-map.html),所以其实第二步也非常简单,完整实现:https://blog.csdn.net/luoluoyang23/article/details/122763696