arcgis for js 4.x实现屏幕快照功能
一、官方文档
esri-views-MapView之takeScreenshot
esri-views-SceneView之takeScreenshot
sample之sceneview-screenshot
二、个人示例
globalUtils.js
/*******************全局静态变量**************************/
export const staticParams = {
map: null,
view: null,
eagleEyeView:null,
container:null,
graphicsLayer: null,
featureTable:null,
};
ViewScreenshot.vue
<template>
<div id="viewScreenshot">
<div id="screenshotDiv" class="hide">
<img class="js-screenshot-image" />
<div>
<label>设置要在图像上显示的文本: </label>
<input type="text" placeholder="Image text" id="textInput" autofocus />
</div>
<el-button id="downloadBtn" type="primary" size="mini">下载</el-button>
<el-button @click="CancelBtn" id="closeBtn" type="info" size="mini"
>取消</el-button
>
</div>
<div id="maskDiv" class="hide screenshotCursor"></div>
</div>
</template>
<script>
import { staticParams } from "@/utils/globalUtils";
export default {
watch: {
isScreenshot(val) {
if (val) {
this.startScreenshot();
}
},
},
computed: {
// 屏幕快照对的按钮点击后,vuex会将isScreenshot变为true
isScreenshot() {
return this.$store.state.controls.isScreenshot;
},
},
methods: {
// 开始拍照
startScreenshot() {
document.querySelector("#allContent").style.display = "none";
staticParams.view.container.classList.add("screenshotCursor");
let area = null;
// 侦听拖动事件并计算选定区域
const dragHandler = staticParams.view.on("drag", (event) => {
event.stopPropagation();
if (event.action !== "end") {
// 通过拖动光标计算选定区域的范围
const xmin = clamp(
Math.min(event.origin.x, event.x),
0,
staticParams.view.width
);
const xmax = clamp(
Math.max(event.origin.x, event.x),
0,
staticParams.view.width
);
const ymin = clamp(
Math.min(event.origin.y, event.y),
0,
staticParams.view.height
);
const ymax = clamp(
Math.max(event.origin.y, event.y),
0,
staticParams.view.height
);
area = {
x: xmin,
y: ymin,
width: xmax - xmin,
height: ymax - ymin,
};
// 设置标记选定区域的div元素的位置
setMaskPosition(area);
}
// 当用户停止拖动时
else {
// 从场景视图中删除拖动事件侦听器
dragHandler.remove();
// 将获取所选区域的屏幕截图
staticParams.view
.takeScreenshot({ area: area, format: "png" })
.then((screenshot) => {
// 显示图像的预览
this.showPreview(screenshot);
// 创建要下载的映像
downloadBtn.onclick = () => {
const text = document.getElementById("textInput").value;
// 如果存在文本,则将其添加到图像中
if (text) {
const dataUrl = this.getImageWithText(screenshot, text);
this.downloadImage(`${text}.png`, dataUrl);
}
// 否则,只下载截图
else {
this.downloadImage(`${Date.now()}.png`, screenshot.dataUrl);
}
screenshotDiv.classList.add("hide");
allContent.style.display = "block";
};
// 屏幕截图模式已禁用
staticParams.view.container.classList.remove("screenshotCursor");
this.$store.commit("controls/setIsScreenshot", false);
setMaskPosition(null);
});
}
function setMaskPosition(area) {
if (area) {
maskDiv.classList.remove("hide");
maskDiv.style.left = `${area.x}px`;
maskDiv.style.top = `${area.y}px`;
maskDiv.style.width = `${area.width}px`;
maskDiv.style.height = `${area.height}px`;
} else {
maskDiv.classList.add("hide");
}
}
function clamp(value, from, to) {
console.log(value < from ? from : value > to ? to : value);
return value < from ? from : value > to ? to : value;
}
});
},
// 取消按钮
CancelBtn() {
screenshotDiv.classList.add("hide");
allContent.style.display = "block";
},
// 预览将下载的内容
showPreview(screenshot) {
screenshotDiv.classList.remove("hide");
// 将屏幕截图dataUrl添加为图像元素的src
const screenshotImage = document.getElementsByClassName(
"js-screenshot-image"
)[0];
screenshotImage.width = screenshot.data.width;
screenshotImage.height = screenshot.data.height;
screenshotImage.src = screenshot.dataUrl;
},
// 返回通过向图像添加自定义文本创建的新图像
getImageWithText(screenshot, text) {
const imageData = screenshot.data;
// 为了将文本添加到屏幕快照,我们创建了一个新的canvas元素
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.height = imageData.height;
canvas.width = imageData.width;
// 将屏幕截图数据添加到画布
context.putImageData(imageData, 0, 0);
context.font = "20px Arial";
context.fillStyle = "#000";
context.fillRect(
0,
imageData.height - 40,
context.measureText(text).width + 20,
30
);
// 从textInput元素添加文本
context.fillStyle = "#fff";
context.fillText(text, 10, imageData.height - 20);
return canvas.toDataURL();
},
// 下载图片
downloadImage(filename, dataUrl) {
// 在Microsoft浏览器中,下载的处理方式不同
// 因为不支持<a>元素的下载属性
if (!window.navigator.msSaveOrOpenBlob) {
// 在支持下载属性的浏览器中
// 将创建一个链接,程序单击将触发下载
const element = document.createElement("a");
element.setAttribute("href", dataUrl);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
} else {
// 对于MS浏览器,将dataUrl转换为Blob
const byteString = atob(dataUrl.split(",")[1]);
const mimeString = dataUrl.split(",")[0].split(":")[1].split(";")[0];
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
const blob = new Blob([ab], { type: mimeString });
// 下载文件
window.navigator.msSaveOrOpenBlob(blob, filename);
}
},
},
};
</script>
<style lang="less" scoped>
#viewScreenshot {
#screenshotDiv {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
background-color: rgba(255, 255, 255, 0.8);
img {
border: 10px solid white;
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.5);
}
}
#screenshotDiv > * {
margin: 0.5em;
}
.hide {
display: none;
}
#maskDiv {
position: absolute;
background: rgba(255, 51, 0, 0.1);
border: 2px dashed rgb(255, 51, 0);
}
}
</style>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!