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>

posted @   槑孒  阅读(238)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示