ngx-image-cropper: сбросить исходное изображение до ранее обрезанного изображения

Я использую библиотеку ngx-image-cropper для обрезки изображений в моем Angular. 8 проект.

Что я хочу сделать, так это:

  • Я хочу показать обрезку внутри модального окна при выборе файла.
  • В модальном окне есть кнопка обрезки, при нажатии которой изображение будет обрезано (без автообрезки), и кнопка отмены, которую можно использовать для закрытия модального окна без обрезки изображения.
  • После того, как изображение будет обрезано, модальное окно будет закрыто, и появится кнопка редактирования, которую можно использовать для повторного кадрирования изображения (при нажатии на кадрирование я по существу обрезаю изображение и скрываю модальное окно. Поэтому при нажатии на редактирование я просто показываю снова скрытый модальный.).
  • Если из входных файлов выбран другой файл, модальное окно будет показано с новым изображением. Пользователь может обрезать или отменить. Если он отменен, я хочу сбросить исходное изображение обрезки на предыдущее изображение. Как я могу это сделать?

Я пробовал следующее, но не работает:


    lastCropperPosition: CropperPosition;
    lastCroppedImage: any;

    crop() {
        this.imageCropper.crop();
        this.lastCropperPosition = this.getCurrentCropperPosition();
        this.lastCroppedImage = new ElementRef(
          this.imageCropper.sourceImage.nativeElement
        );
        this.logoModal.hide();
    }

    cancelCrop() {
        if (this.lastCroppedImage) {
          this.imageCropper.sourceImage = this.lastCroppedImage;
        }

        if (this.lastCropperPosition) {
          this.imageCropper.cropper = this.getLastCropperPosition();
        }

        this.logoModal.hide();
    }

    getCurrentCropperPosition() {
        return {
          x1: this.imageCropper.cropper.x1,
          x2: this.imageCropper.cropper.x2,
          y1: this.imageCropper.cropper.y1,
          y2: this.imageCropper.cropper.y2
        };
    }

    getLastCropperPosition() {
        return {
          x1: this.lastCropperPosition.x1,
          x2: this.lastCropperPosition.x2,
          y1: this.lastCropperPosition.y1,
          y2: this.lastCropperPosition.y2
        };
    }

HTML-код:

    <div bsModal #logoModal="bs-modal" class="modal fade" tabindex="-1"
      role="dialog" aria-labelledby="logoModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h4 class="modal-title">Crop Image</h4>
          </div>
          <div class="modal-body">
            <image-cropper
              [imageChangedEvent]="imageChangedEvent"
              [maintainAspectRatio]="true"
              [aspectRatio]="rules.logo.maxWidth / rules.logo.maxHeight"
              [cropperMinWidth]="rules.logo.minWidth"
              [resizeToWidth]="rules.logo.maxWidth"
              [autoCrop]="false"
              onlyScaleDown="true"
              outputType="both"
              (imageCropped)="imageCropped($event)"
              (imageLoaded)="imageLoaded()"
              (cropperReady)="cropperReady()"
              (loadImageFailed)="loadImageFailed()"></image-cropper>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-sm btn-secondary"
              (click)="cancelCrop()">Cancel</button>
            <button type="button" class="btn btn-sm btn-primary"
              (click)="crop()">Crop</button>
          </div>
        </div>
      </div>
    </div>

Является ли использование свойства sourceImage правильным способом делать то, что я хочу? Я меняю this.lastCroppedImage только внутри метода урожая(). Но, похоже, он меняется всякий раз, когда во входном файле выбирается новое изображение. Почему это происходит?

PS: я уже пытался назначить sourceImage напрямую, не создавая новый ElementRef. Это тоже не работает.

Пример Stackblitz: https://stackblitz.com/edit/image-cropper-r5pyqh

Шаги для воспроизведения в Stackblitz:

Browse and crop an image.
Browse again and select new image.
Click cancel in the crop window.
Click recrop. Observe that the image in crop window is the second one. Instead I want the first one.

person Nimish David Mathew    schedule 16.12.2019    source источник
comment
не могли бы вы показать HTML-код? или, что еще лучше, не могли бы вы создать пример stackblitz?   -  person StepUp    schedule 16.12.2019
comment
Я добавил рассматриваемый HTML-код. Попробую создать stackblitz.   -  person Nimish David Mathew    schedule 16.12.2019
comment
@StepUp Stackblitz: image-cropper-r5pyqh.stackblitz.io   -  person Nimish David Mathew    schedule 16.12.2019
comment
ссылка дает только изображение, а не код   -  person StepUp    schedule 16.12.2019
comment
@StepUp stackblitz.com/edit/image-cropper-r5pyqh. Обновил ссылку.   -  person Nimish David Mathew    schedule 16.12.2019
comment
`Если отменить, я хочу сбросить исходное изображение кропера на предыдущее изображение`, это уже реализовано. Я пробовал.   -  person StepUp    schedule 16.12.2019
comment
@StepUp Нет. Я упомянул шаги для воспроизведения в конце вопроса. Пожалуйста, проверьте это.   -  person Nimish David Mathew    schedule 17.12.2019
comment
Давайте продолжим это обсуждение в чате.   -  person Nimish David Mathew    schedule 17.12.2019


Ответы (2)


Вы можете создать переменную для хранения предыдущего изображения, и когда вы хотите повторно обрезать, просто назначьте ее src изображения. Позвольте мне показать пример:

ImageCropperComponent.ts:

@Input() imgToBeSet: any;
@Input() showPrevImage: false;
@Output() cropperReady = new EventEmitter<any>();

ngOnChanges(changes: SimpleChanges): void {
    if (this.imgToBeSet && this.showPrevImage){
      console.log('***** set prev image');
      this.safeImgDataUrl = this.imgToBeSet;
    }  
}

AppComponent.ts:

currentImgUrl: any;
recropImage: false;

reCrop() {
    this.logoModal.show();
    this.recropImage = true;
}

cropperReady(eventArgs: any) {
    if (!this.currentImgUrl) {
        this.currentImgUrl = eventArgs.currentImgUrl;
        console.log(`currentImgUrl is`, this.currentImgUrl);
    }
}

AppComponent.html:

<div class="modal-body">
    <image-cropper
    #imageCropper
      [imageChangedEvent]="imageChangedEvent"
      [maintainAspectRatio]="true"
      [aspectRatio]="4 / 3"
      [autoCrop]="false"
      [imgToBeSet] = "currentImgUrl"
      [showPrevImage] = "recropImage"
      onlyScaleDown="true"
      outputType="both"
      (imageCropped)="imageCropped($event)"
      (imageLoaded)="imageLoaded()"
      (cropperReady)="cropperReady($event)"
      (loadImageFailed)="loadImageFailed()"></image-cropper>
  </div>

Полный пример может можно увидеть здесь, на stackblitz.

person StepUp    schedule 17.12.2019
comment
Большое спасибо за ответ. Обратите внимание, что я не могу изменить код в ImageCropperComponent.ts, поскольку он является частью пакета обрезки. Но я думаю, что идея здесь состоит в том, чтобы сохранить safeImgDataUrl предыдущего изображения. После восстановления URL-адреса изображение в окне обрезки изменилось на предыдущее изображение. Но если я обрезаю изображение, обрезка не применяется к предыдущему изображению. Это относится к текущему изображению, которое я только что отменил. Кроме того, когда URL-адрес восстанавливается, запускается imageLoaded(), что приводит к ненужному открытию модального окна обрезки. Любой способ решить эти проблемы? - person Nimish David Mathew; 18.12.2019
comment
@NimishDavidMathew извините, у меня нет времени, и я должен делать свою работу. Вы можете сохранить обрезанное изображение в каком-либо сервисе и проверить, содержит ли сервис предыдущее изображение. Не стесняйтесь голосовать или отмечать ответ, если считаете, что он был вам полезен. - person StepUp; 18.12.2019

Используйте функцию для сброса например:

   resetImage() {
        this.scale = 1;
        this.rotation = 0;
        this.canvasRotation = 0;
        this.transform = {};
    }

Здесь я добавил stackblitz, чтобы вы поняли.

person Manish Patidar    schedule 15.04.2020