Angular 7 和 html2Canvas 使用 foreach 迭代数组总是下载最后找到的索引

Angular 7 and html2Canvas iterating an array using foreach always download the last found index

我正在 typescript 中遍历一个数组来拍摄一个 div 的快照,其 id 等于数组的索引并下载一个图像文件。

如果数组有 2 行,则应下载 2 张图像。这是脚本:

public toCanvas() {
    let i = Object.keys(this.array).length;

    Object.keys(this.array).forEach((key, index)=>{
               var elem = document.getElementById(index.toString());

console.log(index)
      html2canvas(elem).then(function(canvas) {
        var generatedImage = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        window.location.href=generatedImage;
      });


    })
  }

使用Object.keys(this.array).forEach((key, index),我正在迭代获取索引,然后找到文档getElementId(index)

问题是它总是下载最后一张图片。

并且在控制台,索引在开始时被控制台,然后图像被下载:

html脚本:

<mat-card [id]="i"  *ngFor="let arrayOfData of array; let i=index; "  class="example-card"  #matCard>

我尝试在 forEach():

中使用 while
public toCanvas() {
    let i = Object.keys(this.array).length;
    Object.keys(this.array).forEach((key, index) => {
      while (i != -1) {
        i--;
        console.log(i)
        var elem = document.getElementById(index.toString());


        html2canvas(elem).then(function (canvas) {
          var generatedImage = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
          window.location.href = generatedImage;
        });
      }

    })
  }

它正在执行相同的行为。它控制索引直到达到 0,然后下载最后检测到的图像 <mat-card>

编辑

这里有一个stackblitz@xyz提供的递归方法

您的实现可能不同,请相应地更改代码。考虑数组中的元素是这样的:array = [0, 1, 2];。而数组中的元素就是你要下载的div个id。所以你的 div 就像:

<div [id]="id" *ngFor="let id of array">
  I am div id: {{id}}
</div>

实施 1 您可以利用 rxjs 按顺序下载 div,让数组成为 Observable 并在开始下一次下载之前处理数组中的每个值(将使用 concatMap这个)。

  public downloadDivs() {
    from(this.array).pipe(
      concatMap((arrayElem) => {
        let docElem = document.getElementById(arrayElem.toString());
        return from(html2canvas(docElem).then(function (canvas) {
          let generatedImage = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
          let a = document.createElement('a');
          a.href = generatedImage;
          a.download = `${arrayElem}.png`;
          a.click();
          return `${arrayElem}.png`;
        }));
      })
    ).subscribe((imageName) => {
      console.log("Image downloaded", imageName);
    }) 
  }

你的 HTML 有这个按钮来触发呼叫:

<button (click)="downloadDivs()">Download divs using rxjs</button>

实施 2 只有在一个 div 下载完成后才调用下一个 div 的下载。为此,我使用了 recursion

public trivialDownload() {
  console.log("Downloading image one by one, without a loop");
  this._download(0, this.array);
}

// this method will keep calling itself until all the elements of the array are scanned
private _download(index, array) {
  if (index >= array.length) {
    console.log("Done!")
  } else {
    let docElem = document.getElementById(array[index].toString());
      html2canvas(docElem).then((canvas) => {
        let generatedImage = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        let a = document.createElement('a');
        a.href = generatedImage;
        a.download = `${array[index]}.png`;
        a.click();
        // at this point, image has been downloaded, then call the next download.
        this._download(index + 1, array)
      });
  }
}

请参阅此 link 以了解实施方式:https://stackblitz.com/edit/download-div-using-canvas?file=src%2Fapp%2Fapp.component.ts