使用html2canvas、jQuery结合Canvg绘制canvas图并下载

使用html2canvas、jQuery结合Canvg绘制canvas图并下载

需求如下:
在这里插入图片描述
这是一个画布,使用jsPlumb绘制图进行连线,现在需要点击下载的按钮将这个画布上绘制的图保存到本地。节点是使用svg绘制的,线是使用jsPlumb绘制的,因此需要重新绘制成canvas。在整个需求完成的过程中遇到了以下几个问题:
1、需要区分节点svg和线,线需要使用canvas重新绘图,节点不需要
2、绘制完成之后如何下载到本地
3、下载并保存到本地的功能实现之后发现,下载成功之后去移动节点,连线会进行错乱。像如下这样
在这里插入图片描述
直接附上代码,具体实现都在代码中注释了

	// 保存图片
    saveChartImg () {
    
      //  flowContent是画布的容器
      var statemachinediv = document.getElementById("flowContent");
      //  获取并遍历所有的svg
      var svgList = $(statemachinediv).find("svg");
      svgList.each(function (index, value) {
        try {
          var svgExample = this;
          var serializer = new XMLSerializer();
          // XMLSerializer.serializeToString() 把一个 XML 文档或节点转换为一个字符串
          var svgMarkup = serializer.serializeToString(svgExample);
          //  线的位置都是有定位的,因此根据是否有定位判断是否为连线
          if (value.style.position) {
            var parentNode = value.parentNode;
            let svg = value.outerHTML.trim();
            let canvas = document.createElement("canvas");
            let ctx = canvas.getContext("2d");
            let v = Canvg.fromString(ctx, svgMarkup);
            v.start();
            canvas.style.position += value.style.position;
            canvas.style.left += value.style.left;
            canvas.style.top += value.style.top;
            //  将绘制的canvas的线加入到DOM元素中
            parentNode.appendChild(canvas);
          }
        } catch (err) {
          console.log("error in print: " + err);
        }
      });
      const canvas = document.createElement("canvas");
      // canvas width
      canvas.width = obj.width.substring(0, obj.width.length - 2) * 1;
      // canvas height
      canvas.height = obj.height.substring(0, obj.height.length - 2) * 1;
      
      //  这里使用html2canvas将所有的绘制成一张canvas图
      html2canvas(statemachinediv, {
        width: canvas.width,
        canvas: canvas,
        heigth: canvas.height,
        useCORS: true // Enable cross-domain configuration
      }).then(canvas => {
        let that = this
        // 这句话加上之后,下载完成之后画布上会多出来一份绘制的canvas
        // statemachinediv.appendChild(canvas);
        var image = canvas
          .toDataURL("image/png")
          .replace("image/png", "image/octet-stream");
        var saveFile = function (data, filename) {
          let _that = that
          var save_link = document.createElementNS(
            "http://www.w3.org/1999/xhtml",
            "a"
          );
          save_link.href = data;
          save_link.download = filename;

          var event = document.createEvent("MouseEvents");
          event.initMouseEvent(
            "click",
            true,
            false,
            window,
            0,
            0,
            0,
            0,
            0,
            false,
            false,
            false,
            false,
            0,
            null
          );
          save_link.dispatchEvent(event);
          _that.clearDom()
        };

        // // 下载后的问题名
        var filename = "下载.png";
        // download
        saveFile(image, filename);
      });
    },
    // 清除DOM元素中无用的元素
    // 这里就是为了解决上面的第三个问题,是为了将绘制添加进去的连线的canvas给从DOM元素中去除,否则每条线都会有重复的一条,出现错乱的情况
    clearDom () {
      var domFlowChange = document.getElementById("flowContent");
      var canvasList = $(domFlowChange).find("canvas");
      canvasList.each(function (index, value) {
        try {
          var can = this
          let parentNode2 = value.parentNode;
          parentNode2.removeChild(value);
        } catch (err) {
          console.log("error in print: " + err);
        }
      });
    },

感谢这篇文章,对于dom的操作给了一定的提示。
JS删除DOM元素的两种方法
这里是文章中的内容:
在这里插入图片描述

发布了25 篇原创文章 · 获赞 2 · 访问量 3742

猜你喜欢

转载自blog.csdn.net/heixiuheixiu666/article/details/104226666