当前位置:网站首页>openlayer中实现截图框截图的功能
openlayer中实现截图框截图的功能
2022-08-11 05:25:00 【Mino.66】
实现
接着上篇文章写(https://blog.csdn.net/luoluoyang23/article/details/122653363),这次会完整的实现截图的功能
首先要放个地图,直接参照https://openlayers.org/en/latest/doc/quickstart.html写就行了
<!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">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/[email protected]/en/v6.12.0/css/ol.css" type="text/css">
<title>Document</title>
<style type="text/css"> html, body {
margin: 0; padding: 0; } #screenshot {
border: 2px solid black; } .map {
width: 100%; height: 600px; } </style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/[email protected]/en/v6.12.0/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
</body>
<script> const map = new ol.Map({
target: 'map', layers: [ new ol.layer.Tile({
source: new ol.source.OSM() }) ], view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 }) }) 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>
我这里代码是直接在上次的代码基础上写的,看看效果
改点东西,因为我们截图事件是直接写在windows上面的,这样点地图也会触发,随便加个按钮,把事件挪过去
<button id="screen-button">截图</button>
...
document.getElementById('screen-button').addEventListener('click', (e) => {
const mousedownEvent = (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)
window.removeEventListener("mousedown", mousedownEvent)
})
}
window.addEventListener("mousedown", mousedownEvent)
})
这里直接移进去了,这样点击按钮后才会把截图事件绑定到window上,在鼠标松开时移除这些事件
现在我们在网页中测试能够发现,当我们截图时鼠标移动也会拖动地图移动,这样没办法很好的截图,解决这个问题有很多思路,可以在初始化地图的时候拿到拖动地图的事件进行控制,我之前在写地图色块提取的时候有用过透明遮罩的办法,自己权衡。这里采用前一种,参考:
https://blog.csdn.net/u013323965/article/details/53183532
let pan
map.getInteractions().forEach(function(element,index,array){
if(element instanceof ol.interaction.DragPan) pan = element;
})
在事件开始和结尾处加上相应的代码即可
然后就是获取图片了,在上一篇文章我已经给过相关API的链接地址,可以自己去研究,这里直接贴代码了
function getMapImg(startX, startY, mWidth, mHeight) {
map.once('rendercomplete', () => {
const mapCanvas = document.createElement('canvas')
mapCanvas.width = mWidth
mapCanvas.height = mHeight
const mapContext = mapCanvas.getContext('2d')
Array.prototype.forEach.call(
document.querySelectorAll('.ol-layer canvas'),
function (canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity)
const transform = canvas.style.transform
// Get the transform parameters from the style's transform matrix
const matrix = transform
.match(/^matrix\(([^(]*)\)$/)[1]
.split(',')
.map(Number)
// Apply the transform to the export map context
CanvasRenderingContext2D.prototype.setTransform.apply(
mapContext,
matrix
)
mapContext.drawImage(canvas, -startX, -startY)
}
}
)
if (navigator.msSaveBlob) {
// link download attribute does not work on MS browsers
navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png')
} else {
dataUrl = mapCanvas.toDataURL()
console.log(dataUrl)
}
})
map.renderSync()
}
四个参数,分别是截图范围的起点xy坐标,截图框的宽高。这就是我们写截图框代码的目的。这四个参数就从上面拿就行了,这里也直接写在之前的代码中获取,为了大家方便查看,这里直接贴出整体的代码
let [canvasX, canvasY] = [startX, startY]
let canvasWidth, canvasHeight
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'
canvasWidth = moveX
} else {
divDom.style.width = -moveX + 'px'
divDom.style.left = e.clientX + 'px'
canvasWidth = -moveX
canvasX = e.clientX
}
if (moveY > 0) {
divDom.style.height = moveY + 'px'
canvasHeight = moveY
} else {
divDom.style.height = -moveY + 'px'
divDom.style.top = e.clientY + 'px'
canvasHeight = -moveY
canvasY = e.clientY
}
}
在截图结束的地方调用getMapImg()
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", moveEvent)
window.removeEventListener("mousedown", mousedownEvent)
pan.setActive(true)
getMapImg(canvasX, canvasY, canvasWidth, canvasHeight)
})
在getMapImg中最后几行的dataUrl就是图片地址,可以直接在浏览器中打开,现在我们测试效果
可以看到我们成功实现了效果,接下来就是一些优化截图表现效果的代码了。具体效果可以按照自己喜欢的来,我这里走比较常规的套路,在截图结束时清除截图框,在窗口中间增加一个预览截图的效果
这部分写得比较随意,下面时完整代码
<!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">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/[email protected]/en/v6.12.0/css/ol.css" type="text/css">
<title>Document</title>
<style type="text/css"> html, body {
margin: 0; padding: 0; } #screenshot {
border: 3px solid black; } .map {
width: 100%; height: 600px; } #photo-window {
position: absolute; border: 25px solid rgba(0, 0, 0, 0.5); overflow: hidden; } .hide {
display: none; } </style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/[email protected]/en/v6.12.0/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<button id="screen-button">截图</button>
<div id="photo-window" class="hide">
<img id="photo" src="" alt="#" />
</div>
</body>
<script> const map = new ol.Map({
target: 'map', layers: [ new ol.layer.Tile({
source: new ol.source.OSM() }) ], view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 }) }) let dataUrl let pan map.getInteractions().forEach(function(element,index,array){
if(element instanceof ol.interaction.DragPan) pan = element; }) document.getElementById('screen-button').addEventListener('click', (e) => {
const mousedownEvent = (e) => {
pan.setActive(false) 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" let [canvasX, canvasY] = [startX, startY] let canvasWidth, canvasHeight 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' canvasWidth = moveX } else {
divDom.style.width = -moveX + 'px' divDom.style.left = e.clientX + 'px' canvasWidth = -moveX canvasX = e.clientX } if (moveY > 0) {
divDom.style.height = moveY + 'px' canvasHeight = moveY } else {
divDom.style.height = -moveY + 'px' divDom.style.top = e.clientY + 'px' canvasHeight = -moveY canvasY = e.clientY } } window.addEventListener("mousemove", moveEvent) window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", moveEvent) window.removeEventListener("mousedown", mousedownEvent) pan.setActive(true) getMapImg(canvasX, canvasY, canvasWidth, canvasHeight) document.body.removeChild(divDom) generateWindow() }) } window.addEventListener("mousedown", mousedownEvent) }) function getMapImg(startX, startY, mWidth, mHeight) {
map.once('rendercomplete', () => {
const mapCanvas = document.createElement('canvas') mapCanvas.width = mWidth mapCanvas.height = mHeight const mapContext = mapCanvas.getContext('2d') Array.prototype.forEach.call( document.querySelectorAll('.ol-layer canvas'), function (canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity) const transform = canvas.style.transform // Get the transform parameters from the style's transform matrix const matrix = transform .match(/^matrix\(([^(]*)\)$/)[1] .split(',') .map(Number) // Apply the transform to the export map context CanvasRenderingContext2D.prototype.setTransform.apply( mapContext, matrix ) mapContext.drawImage(canvas, -startX, -startY) } } ) if (navigator.msSaveBlob) {
// link download attribute does not work on MS browsers navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png') } else {
dataUrl = mapCanvas.toDataURL() generateWindow(mWidth, mHeight) } }) map.renderSync() } function generateWindow(width, height) {
document.getElementById('photo').src = dataUrl const boxDom = document.getElementById('photo-window') boxDom.classList.remove('hide') boxDom.style.left = 'calc(50% - ' + (width / 2) + 'px)' boxDom.style.top = 'calc(50% - ' + (height / 2) + 'px)' } </script>
</html>
边栏推荐
- 产品版本号是如何确定的
- Diagnostic Log and Trace——DLT 离线日志存储
- 360°大视野安全帽识别系统-深度学习智能视频分析
- CMT2380F32模块开发6-flash例程
- Ubuntu下安装mysql笔记
- The latest safety helmet wearing recognition system in 2022
- Waymo数据集使用介绍(waymo-open-dataset)
- Diagnostic Log and Trace——开发人员如何使用 DLT
- LiDAR Snowfall Simulation for Robust 3D Object Detection
- 360° large field of view helmet recognition system-deep learning intelligent video analysis
猜你喜欢
AI智能图像识别的工作原理及行业应用
Maykle Studio - HarmonyOS Application Development Third Training
梅科尔工作室-HarmonyOS应用开发第三次培训
aPaaS和iPaaS的区别
STM32-中断优先级管理NVIC
The working principle and industry application of AI intelligent image recognition
Toward a Unified Model
梅科尔工作室-HarmonyOS应用开发第一次培训
安全帽识别系统-解决监管难题
梅科尔工作室-HarmonyOS应用开发第四次培训
随机推荐
安全帽识别算法
目标检测思维导图
Introduction of safety helmet wearing recognition system
红外线应用-红外遥控
KANO模型——确定需求优先级的神器
Hard hat identification
Hard hat recognition algorithm
STM32学习笔记(白话文理解版)—搞懂PWM输出
Use regex to verify whether the file name is legal
The selection points you need to know about the helmet identification system
梅科尔工作室-华为云ModelArts第一次培训
解决jupyter中import torch出错问题
Reconstruction and Synthesis of Lidar Point Clouds of Spray
2022年最新安全帽佩戴识别系统
Node-2.垃圾回收机制
STM32-串口常用寄存器和库函数及配置串口步骤
产品如何拟定优化方案?
OpenPCDet安装最新版:spconv一步到位
梅科尔工作室-DjangoWeb 应用框架+MySQL数据库第四次培训
CMT2380F32模块开发11-RTC例程