Context.drawImage не работает после image.onload - PullRequest
0 голосов
/ 09 мая 2020

Я пытаюсь создать приложение для рисования от руки с использованием элемента html холста, поэтому я пытаюсь реализовать функцию «Отменить», которая в основном делает снимок текущего состояния холста, а затем сохраняет это в каком-то списке, когда пользователь dr aws что-то на холсте, и когда пользователь нажимает кнопку отмены, он выводит последнее сохраненное состояние и dr aws на холсте. Я пробовал позвонить context.drawImage() после image.onload, как показано, но все равно бесполезно.

export class WhiteboardScreenComponent implements OnInit, AfterViewInit {
  @ViewChild('myCanvas')
  myCanvas: ElementRef<HTMLCanvasElement>;
  painting: boolean = false;
  strokeWidth: number = 2;
  strokeColor: string = this.colors[this.selectedColor];
  lineStyle: CanvasLineCap = 'round';
  ctx: CanvasRenderingContext2D;
  undoHistory: any[] = [];


  constructor() { }

  ngOnInit(): void { }

  ngAfterViewInit(): void {
    this.ctx = this.myCanvas.nativeElement.getContext('2d');
    this.resizeCanvas();
    this.myCanvas.nativeElement.addEventListener('mousedown', this.startPainting);
    this.myCanvas.nativeElement.addEventListener('mouseup', this.finishPainting);
    this.myCanvas.nativeElement.addEventListener('mousemove', this.draw);
  }

  startPainting = (e) => {
    this.painting = true;
    this.ctx.beginPath();
    this.ctx.moveTo(e.clientX, e.clientY);
  }

  //saving the state of the canvas here 
  finishPainting = (e) => {
    let src = this.myCanvas.nativeElement.toDataURL("image/png");
    this.undoHistory.push(src);
    this.ctx.closePath();
    this.painting = false;
  }

  draw = (e) => {
    if (!this.painting) return;
    this.setProperties();
    this.ctx.lineTo(e.clientX, e.clientY);
    this.ctx.stroke();
  }

  setProperties(): void {
    this.ctx.lineWidth = this.strokeWidth;
    this.ctx.lineCap = this.lineStyle;
    this.ctx.strokeStyle = this.strokeColor;
  }

    //fetching the last saved state and drawing it onto the canvas
    undo(): void {
    if (this.undoHistory.length > 0) {
      let image = new Image();
      image.onload = () => {
         this.ctx.drawImage(image, 0, 0);
      };
      image.src = this.undoHistory.pop();
    }
  }
}

Ответы [ 2 ]

0 голосов
/ 13 июня 2020

Перед вызовом метода drawImage() вы должны очистить экран, что можно сделать, просто изменив размер холста, чтобы перерисовать его, или вызвав clearRect().

0 голосов
/ 09 мая 2020

Ваш лог c здоров и работает на обычном html:

<canvas id="canvas" width=400></canvas>

<script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    function draw() {
        ctx.beginPath();
        x = Math.random() * canvas.width
        y = Math.random() * canvas.height
        ctx.arc(x, y, 10, 0, 2 * Math.PI)
        ctx.stroke();
    }

    function takeSnap() {
        src = canvas.toDataURL("image/png");
        for (i = 0; i < 5; i++) {
            ctx.fillRect(50 * i, 20 * i, 50, 10);
        }
    }

    function undo() {
        clearInterval(inter)
        let img = new Image();
        img.onload = () => {
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            ctx.drawImage(img, 0, 0);
        };
        img.src = src;
    }

    inter = setInterval(draw, 100);
    setTimeout(takeSnap, 2000);
    setTimeout(undo, 4000);
</script>

Вам просто нужно отладить на своей стороне, чтобы убедиться, что undoHistory содержит правильные данные, только думаю, что я вижу, что ваш this.myCanvas.nativeElement.toDataURL выглядит подозрительно ...

...