Angular 7 и html2Canvas итерируют массив, используя foreach, всегда загружают последний найденный индекс - PullRequest
0 голосов
/ 17 декабря 2018

Я перебираю массив в машинописи, чтобы сделать снимок div с идентификатором, равным индексу массива, и загрузить файл изображения.

Если в массиве было 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).

Проблема в том, что он всегда загружаетпоследнее изображение.

И в консоли индексы утешаются, в начале, а затем загружается изображение:

enter image description here

Сценарий html:

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

Я пытался использовать while внутри forEach():

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.

1 Ответ

0 голосов
/ 18 декабря 2018

Ваша реализация может отличаться, измените код соответствующим образом.Учет элементов в массиве выглядит так: array = [0, 1, 2];.И элементы в массиве - это идентификаторы div, которые вы хотите загрузить.Таким образом, ваши div'ы выглядят так:

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

Реализация 1 Вы можете использовать rxjs для загрузки div в последовательности, позволяя сделать массив наблюдаемым и работать с каждым значением вмассив перед началом следующей загрузки (будет использовать 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)
      });
  }
}

Смотрите эту ссылку для реализации: https://stackblitz.com/edit/download-div-using-canvas?file=src%2Fapp%2Fapp.component.ts

...