实现
接着上篇文章写(,这次会完整的实现截图的功能
首先要放个地图,直接参照
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><linkrel="stylesheet"href=""type="text/css"><title>Document</title><styletype="text/css">html, body{margin: 0;padding: 0;}#screenshot{border: 2px solid black;}.map{width: 100%;height: 600px;}</style><scriptsrc=""></script></head><body><divid="map"class="map"></div></body><script>const map =newol.Map({
target:'map',
layers:[newol.layer.Tile({
source:newol.source.OSM()})],
view:newol.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)constmoveEvent=(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>
我这里代码是直接在上次的代码基础上写的,看看效果
<button id="screen-button">截图</button>...
document.getElementById('screen-button').addEventListener('click',(e)=>{constmousedownEvent=(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)constmoveEvent=(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上,在鼠标松开时移除这些事件
现在我们在网页中测试能够发现,当我们截图时鼠标移动也会拖动地图移动,这样没办法很好的截图,解决这个问题有很多思路,可以在初始化地图的时候拿到拖动地图的事件进行控制,我之前在写地图色块提取的时候有用过透明遮罩的办法,自己权衡。这里采用前一种,参考:
let pan
map.getInteractions().forEach(function(element,index,array){if(element instanceofol.interaction.DragPan) pan = element;})
在事件开始和结尾处加上相应的代码即可
functiongetMapImg(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 matrixconst matrix = transform
.match(/^matrix\(([^(]*)\)$/)[1].split(',').map(Number)// Apply the transform to the export map contextCanvasRenderingContext2D.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)constmoveEvent=(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就是图片地址,可以直接在浏览器中打开,现在我们测试效果
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><linkrel="stylesheet"href=""type="text/css"><title>Document</title><styletype="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><scriptsrc=""></script></head><body><divid="map"class="map"></div><buttonid="screen-button">截图</button><divid="photo-window"class="hide"><imgid="photo"src=""alt="#"/></div></body><script>const map =newol.Map({
target:'map',
layers:[newol.layer.Tile({
source:newol.source.OSM()})],
view:newol.View({
center: ol.proj.fromLonLat([37.41,8.82]),
zoom:4})})let dataUrl
let pan
map.getInteractions().forEach(function(element,index,array){if(element instanceofol.interaction.DragPan) pan = element;})
document.getElementById('screen-button').addEventListener('click',(e)=>{constmousedownEvent=(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)constmoveEvent=(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)})functiongetMapImg(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 matrixconst matrix = transform
.match(/^matrix\(([^(]*)\)$/)[1].split(',').map(Number)// Apply the transform to the export map contextCanvasRenderingContext2D.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()}functiongenerateWindow(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>

发布评论