首页 > 解决方案 > 为什么即使使用属性绑定 [src],图像 src 也不会更新?

问题描述

我正在尝试使用捕获屏幕getDisplayMedia()(我使用了外部 js,getDisplayMedia()因为我猜 angular 4 不支持它)。在第一次点击事件时,它会显示准确的截图图像,但之后它不会从第二次点击事件开始更新图像。

我试过:

app.component.ts

import { Component, HostListener } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { TranslateService } from '@ngx-translate/core';
import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';
import { NotificationService } from './primary/services/notification.service';
import { AppConstants } from './shared/AppConstants';
import { CookieService } from './primary/services/cookie-service';
import {DialogboxService} from './primary/services/dialogbox.service';

//Core javascript classes.
declare var MediaRecorder: any;
declare var getStream: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  // _navigator:any = null;
  displayPopup: boolean = false;
  msgs: any;
  subscription: Subscription;
  flag: any;
  stream = null;
  shadowRoot = null;
  videoplayer = null;
  chunks = [];
  mediaRecorder = null;
  status = 'Inactive';
  recording = null;
  screenshot = null;
  validNavigation = 0;
  contx = null;
  canvas = null;

  constructor(public notifyer: NotificationService, private translate: TranslateService,
              public _cookieService:CookieService, private dialogboxService:DialogboxService,
              private sanitizer: DomSanitizer) {

    AppConstants.LANGUAGE = 'en';
    translate.setDefaultLang(AppConstants.LANGUAGE);
    translate.use(AppConstants.LANGUAGE);
    this.subscription = this.notifyer.notificationChange
      .subscribe(msgs => {
        this.msgs = msgs;
      });
  }

  ngOnInit(){
    this.videoplayer = document.getElementById("invisibleVideo")
    this.canvas = document.getElementById("myCanvas");
    this.canvas.width = window.innerWidth; //document.width is obsolete
    this.canvas.height = window.innerHeight;
  }

  //to take timeout
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async _takeScreenshot(){
    this.stream = await getStream();
    this.mediaRecorder = new MediaRecorder(this.stream, {mimeType: 'video/webm'});
    this.mediaRecorder.addEventListener('dataavailable', event => {
      if (event.data && event.data.size > 0) {
        this.chunks.push(event.data);
      }
    });
    this.mediaRecorder.start(100);
    await this.sleep(1200);
    this.mediaRecorder.stop();
    this.mediaRecorder = null;
    this.stream.getTracks().forEach(track => track.stop());
    this.stream = null;
    //allow dynamic source base64 URL
    this.recording = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(new Blob(this.chunks, {type: 'video/webm'})));
    await this.sleep(600);
    this.contx = this.canvas.getContext("2d")
    this.contx.drawImage(this.videoplayer,0,0)
    //allow dynamic source base64 URL
    this.screenshot = this.sanitizer.bypassSecurityTrustUrl(this.canvas.toDataURL('image/png'))
    this.canvas.width = window.innerWidth; //document.width is obsolete
    this.canvas.height = window.innerHeight;
    this.displayPopup = true;
  }

  takeSelfie(){
    this._takeScreenshot();
  }
}

app.component.html

<script src="../assets/adapter.js"></script>
<style>
  video {
    --video-width: 100%;
    width: var(--video-width);
    height: calc(var(--video-width) * (16 / 9));
  }
</style>
<p-dialog [positionTop]="40" (onHide)="displayPopup=false" [styleClass]="'popup_width'"
  header='Report Bug' [(visible)]="displayPopup" modal="modal" [responsive]="true">
  <div id="ssDiv">
    <img [src]="screenshot" id="ssImg" class="ssImg">
  </div>
  <div id="container">
    <canvas id="myCanvas"></canvas>
    <div id="vDiv">
      <video style="display:none" controls="true" id="invisibleVideo" playsinline
              autoplay loop muted [src]="recording ? recording : ''"></video>
    </div>
  </div>
  </p-dialog>
<button class="report-bug-button" (click)="takeSelfie()">
  <i class="fa fa-camera" aria-hidden="true" style="color:white;font-size: 25px;"></i>
</button>

适配器.js

var getStream = function getStream(){
  if (navigator.getDisplayMedia) {
    return navigator.getDisplayMedia({video: true});
  } else if (navigator.mediaDevices.getDisplayMedia) {
    return navigator.mediaDevices.getDisplayMedia({video: true});
  } else {
    return navigator.mediaDevices.getUserMedia({video: {mediaSource: 'screen'}});
  }
}

我希望每次单击事件发生时,图像都应该使用新的屏幕截图进行更新,而不是停留在旧屏幕截图上。

标签: angularasync-awaithtml5-canvas

解决方案


新记录的屏幕数据块被附加到数组中。this.chunks.push(event.data);

每当视频播放器开始播放录制时,它总是从开始时录制的内容开始。因此,屏幕截图始终是从初始帧中截取的。这是实际的错误。解决方案是清除内部的块数组_takeScreenshot

this.chunks = []


推荐阅读