onreadystatechange / blogs

主要记录项目中的重难点,以及如何攻克,有一定的借鉴意义,主要写在Issues
3 stars 0 forks source link

笔记导出Word 核心代码(也可以是任何一段dom导出成word) #5

Open onreadystatechange opened 5 years ago

onreadystatechange commented 5 years ago

解决promise并行执行问题与canvas访问img跨域问题

onreadystatechange commented 5 years ago
async exportWORD() {
    //拿到当前编辑器的文档流
    var contentDocument = window.CurrentTinymceEditor.editor.getDoc();
    //拿到编辑器的html
    var outerHTML = contentDocument.documentElement.outerHTML;
    //对Html进行转换 当前主要转换为将Html里所有图片转为Base64格式
    outerHTML = await this.convertImagesToBase64(outerHTML);
    const { node } = this.props;

    var content = `<!DOCTYPE html><html>${outerHTML}</html>`;
    //拿到文件流
    var converted = window.htmlDocx.asBlob(content, { orientation: 'portrait' });
    //使用html-to-doc方法将笔记内容输出为doc文件
    window.saveAs(converted, `${node.title}.docx`);
  }

  //将字符串转换为dom
  parseDom(arg) {
    var objE = document.createElement('div');
    objE.innerHTML = arg;
    return objE.childNodes[0];
  }
  //将dom转为字符串
  nodeToString(node) {
    var tmpNode = document.createElement('div');
    tmpNode.appendChild(node.cloneNode(true));
    var str = tmpNode.innerHTML;
    tmpNode = node = null; // prevent memory leaks in IE
    return str;
  }
  //多个promise并行
  async queue(promiseArr) {
    let res = null;
    for (let promise of promiseArr) {
      res = await promise;
    }
    return await res;
  }
  convertImagesToBase64(outerHTML) {
    return new Promise((resolve, reject) => {
      //拿到文档流中所有img标签
      var regularImages = window.CurrentTinymceEditor.editor.getDoc().querySelectorAll('img');
      //根据字符串生成dom
      const documentcreateRange = document.createRange().createContextualFragment(outerHTML);
      let outerDomImgs = documentcreateRange.querySelectorAll('img');
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      var _this = this;
      var promiseArr = [];
      //当img加载完毕后拿到img对象转为base
      function loadImage(imgElement, index) {
        var img = new Image();
        img.width = imgElement.width;
        img.height = imgElement.height;
        //设置img属性 canvas访问不到不设置会跨域
        img.setAttribute('crossOrigin', 'anonymous'); // works for me
        imgElement.setAttribute('crossOrigin', 'anonymous'); // works for me
        img.src = imgElement.src;
        return promiseArr.push(
          new Promise((resolve, reject) => {
            //当img加载完成
            img.onload = function() {
              try {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                canvas.width = this.width;
                canvas.height = this.height;
                ctx.drawImage(this, 0, 0, this.width, this.height);
                var dataURL = canvas.toDataURL();
                //设置img的src为canvas转换后的base64
                outerDomImgs[index].setAttribute('src', dataURL);
                outerDomImgs[index].setAttribute('crossOrigin', 'anonymous');
                resolve(1);
              } catch (error) {
                resolve(1);
              }
            };
            img.onerror = e => {
              resolve(1);
            };
          })
        );
      }

      [].forEach.call(regularImages, function(imgElement, index) {
        return loadImage(imgElement, index);
      });
      this.queue(promiseArr)
        .then(data => {
          canvas.remove();
          outerHTML = _this.nodeToString(documentcreateRange);
          resolve(outerHTML);
        })
        .catch(e => {
          console.log(e);
        });
    });
  }