serratus / quaggaJS

An advanced barcode-scanner written in JavaScript
https://serratus.github.io/quaggaJS/
MIT License
5.04k stars 978 forks source link

Can Qugga be restarted? #149

Open cdarrigo opened 7 years ago

cdarrigo commented 7 years ago

I am writing an angular 2 app, when the component initializes,I run Quagga.init(), but do not call Quagga.Start() as part of the init callback. Instead, when the user clicks a"scan barcode" button, I call Quagga.start(). When a code is detected, I call Quagga.pause().

The next time the user clicks "scan barcode", and I call Quagga.start() again, I immediately get the onDetected callback firing again, for the old barcode.

Is there someway to reset the state, so I can scan a second barcode?

here's my current ng2 TS code ` @Component({ selector: 'barcodescanner', templateUrl: './barcodescanner.component.html', styleUrls: ['./barcodescanner.component.css', './colors.css', './fonts.css', './styles.css'] }) export class BarcodescannerComponent implements OnInit, OnDestroy {

@ViewChild('childModal') public childModal: ModalDirective; @Output() codeScanned: EventEmitter = new EventEmitter();

constructor() {}

ngOnInit() { var thisdialog = this;

Quagga.init({
  inputStream: {
    name: "Live",
    type: "LiveStream",
    // target: document.querySelector('#interactive')    // Or '#yourElement' (optional)
  },
  decoder: {
    readers: ["upc_reader"]
  }
}, function (err) {
  if (err) {
    console.log(err);
    return
  }
  console.log("Initialization finished. Ready to start");
  Quagga.onProcessed(function (result) {
    var drawingCtx = Quagga.canvas.ctx.overlay,
      drawingCanvas = Quagga.canvas.dom.overlay;

    if (result) {
      if (result.boxes) {
        drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
        result.boxes.filter(function (box) {
          return box !== result.box;
        }).forEach(function (box) {
          Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
        });
      }

      if (result.box) {
        Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
      }

      if (result.codeResult && result.codeResult.code) {
        Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
      }
    }
  });

  Quagga.onDetected(function (result) {
    thisdialog.onCodeScanned( result.codeResult.code);
  });
  Quagga.pause();

});

}

ngOnDestroy() { Quagga.stop() }

onCodeScanned(code: string) { Quagga.pause(); this.hideDialog(); this.codeScanned.emit(code); }

showDialog() { this.childModal.show(); Quagga.start(); }

onCancel() { Quagga.pause(); this.hideDialog(); }

public hideDialog(): void { this.childModal.hide(); } }`

eight-molecules commented 7 years ago

Tick your Angular app with @angular/ApplicationRef.tick();

I have an Angular 2 project that I just finished integrating QuaggaJS into, this is the first step I had in getting them to play nicely. Without it the callback doesn't return properly. You also must use an arrow function so that scope sticks around, e.g. Quagga.onDetected((result) => this.logCode(result));

There's some issue with Zones and both the constructor and ngOnInit hook in Angular 2 right now which means that Quagga, being instantiated in one of those two, doesn't get hit by change detection properly for some reason. The Angular2 guys have an issue listed but manual ticks and manual zoning are the only ways to handle it currently.