html2canvas+百度地图(定位,折线)svg导出图片

2,582 阅读2分钟

工具介绍

功能介绍

将弹出框里面的内容导出成图片格式保存在本地。弹出框中使用了百度地图,并且绘制了坐标点和线段链接功能。

html2canvas导出图片遇到问题

百度地图点坐标定位的原生图片跨域问题,线段链接(svg)导出失效

解决问题

百度地图原生图片跨域问题

方法1

  • html2canvas原生配置应该可以解决跨域问题,就和vue.config.js差不多,会的教我一下,感谢。

方法2

  • 不使用原生的定位图标图片,使用本地的
    let marker = new BMap.Marker(point, {
       icon: new BMap.Icon(
         require("../../../assets/weizhia.png"),//图片大小30px*30px
         new BMap.Size(30, 30),
         {
           anchor: new BMap.Size(15, 30),
         }
       ),
     });
     this.map.addOverlay(marker);

百度地图线段链接(svg)导出失效

方法逻辑解释

  • 使用Canvg把百度地图中的线段(svg)转为canvas
  • 将canvas定位到svg的位置,删除svg
    //target弹出框元素
    svgToCanvas(target) {
      const svgElems = Array.from(target.getElementsByTagName("svg"));
      svgElems.forEach(async (el) => {
        const parentNode = el.parentNode;
        const canvas = document.createElement("canvas");
        canvas.style.zIndex = "0";
        if (el.tagName === "svg") {
          //这一行注意!网上搜的一般都不带.querySelector("path")
          //但是百度地图的svg(线段)就需要(不是百度地图的svg我也不清楚,谁试过能说说最好)。
          const svg = el.querySelector("path").outerHTML.trim();

          const { width, height } = el.getBoundingClientRect();
          canvas.width = width;
          canvas.height = height;
          const ctx = canvas.getContext("2d");
          //CSS颜色,渐变,或图案,默认设置是#000000(黑色)
          // ctx.fillStyle = "red";
          //x-横坐标 y-纵坐标 w-宽 h-高
          // ctx.fillRect(0, 0, 200, 200);
          //工具方法
          const v = await Canvg.from(ctx, svg);
          v.start();

          if (el.style.position) {
            canvas.style.position = 999;
            // canvas.style.position = el.style.position;
            // canvas.style.left = el.style.left;
            // canvas.style.top = el.style.top;
          }
        }
        parentNode.appendChild(canvas);
        parentNode.removeChild(el);
      });

      return target;
    },
  • html2canvas导出
    saveImage(divText, imgText) {
      let canvasID = this.$refs[divText];
      let that = this;
      let a = document.createElement("a");
      this.svgToCanvas(canvasID);

      setTimeout(() => {
        html2canvas(canvasID, {
          useCORS: true,
          onclone: () => {
            // this.svgToCanvas(canvasID);
          },
        }).then((canvas) => {
          let dom = document.body.appendChild(canvas);
          dom.style.display = "none";
          a.style.display = "none";
          document.body.removeChild(dom);
          let blob = that.dataURLToBlob(dom.toDataURL("image/png"));
          a.setAttribute("href", URL.createObjectURL(blob));
          //这块是保存图片操作  可以设置保存的图片的信息
          a.setAttribute("download", imgText + ".png");
          document.body.appendChild(a);
          a.click();
          URL.revokeObjectURL(blob);
          document.body.removeChild(a);
        });
      }, 0);
    },
    //转成blob?这一步有啥用我不太清楚,维护时候就带这部分内容的。
    dataURLToBlob(dataurl) {
      let arr = dataurl.split(",");
      let mime = arr[0].match(/:(.*?);/)[1];
      let bstr = atob(arr[1]);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },
提醒
  1. 导出时候必须要让Canvg(svg->canvas)走完才能导出,所以使用了setTimeout包裹住
  2. 不要在html2canvas中的onclone方法运行(svg->canvas)的方法。没用!按照html2canvas的官方文档我感觉应该可以的!这样就不需要使用setTimeout包裹住了啊。为啥?!(凑合用吧)
  3. 一般需要配着jsPDf导出为pdf文档的,需要裸跑 this.svgToCanvas(canvasID)方法