Not closing camera in zxing

2k Views Asked by At

In the Zxing library, I want to close the camera when the user clicks cancel. So I used a button and add onclick event to it. it is calling resetReader method. I called this method after gets a barcode value or in the cancel button onclick event.If it is getting barcode values, this resetReader method works perfectly. if we cancel, the camera doesn't stop. Am I missing something?

const codeReader = new BrowserMultiFormatReader(hints);

const resetReader = () => {
    codeReader.reset();
    codeReader.stopContinuousDecode();
  };
2

There are 2 best solutions below

0
On

for those who haven't figured it out yet? I have found a solution to this problem. Harendrra's solution didn't work for me, but this one did in combination with usestate. For my project the code uses Bootstrap. So when I click on a button the Modal appears. The camera loads. When I click on the Close button the camera disappears. Hope this is a solutions for everyone, enjoy ;-)

export default function Example(props) {
  // codeReader
  const [codeReader, setReader] = useState(new BrowserMultiFormatReader());
  const [videoInputDevices, setVideoInputDevices] = useState([]);
  const [selectedVideoDevice, selectVideoDevice] = useState('');

  useEffect(() => {
    (async () => {
        const videoInputDeviceList = await codeReader.listVideoInputDevices();
        setVideoInputDevices(videoInputDeviceList);
        if (videoInputDeviceList.length > 0 && selectedVideoDevice == null) {
            selectVideoDevice(videoInputDeviceList[0].deviceId);
        }
    })();
  }, [codeReader, selectedVideoDevice]);

  const handleShow = () => {
    setBrand('');
    // Open modal.
    setShow(true);

    codeReader.decodeFromVideoDevice(selectedVideoDevice, 'videoElement', (res) => {
        setCanClose(true);
        if (res) {
            const rawText = res.getText();
            axios
                .get(`https://world.openfoodfacts.org/api/v0/product/${rawText}.json`)
                .then((result) => {
                    // set data
                    setBrand(result.data.product.brands);
                    // close modal
                    setShow(false);
                    // codeReader reset
                    codeReader.reset();
                })
                .catch((err) => console.log('error', err));
          }
      });
  };

  const handleClose = () => {
    // codeReader reset.
    setReader(codeReader.reset());
    // Close modal
    setShow(false);
    // Set new codeReader.
    // The solution for the error messages after the codeReader reset.
    // This will build the codeReader for the next time.
    setReader(new BrowserMultiFormatReader(hints));
  };

  return (
    <Fragment>
      <div className='py-2'>
        <div>Brand: {brand}</div>
        <Button variant='primary' onClick={handleShow}>
          Launch static backdrop modal
        </Button>

        <Modal show={show} onHide={handleClose} backdrop='static' keyboard={false} centered id='scanProductModal'>
          <Modal.Body>
            <div
              onChange={(event) => {
                const deviceId = event.target.value;
                selectVideoDevice(deviceId);
              }}
            >
              <div className='button-group-top'>
                <select className='form-select form-select-sm' aria-label='Default select example'>
                  {videoInputDevices &&                                          
                    videoInputDevices.map((inputDevice, index) => {
                      return (
                        <option value={inputDevice.deviceId} key={index}>
                          {inputDevice.label || inputDevice.deviceId}
                        </option>
                      );
                  })}
                </select>
              </div>
             
              <video id='videoElement' width='600' height='400' />
              <Button className='btn btn-danger' onClick={handleClose}>
                Close
              </Button>
            </div>
          </Modal.Body>
        </Modal>
      </Fragment>
    );
  }
0
On

Yes, I resolved. You have to create codeReader object at the top of the Class. Try this code.

import "../App.css";
import { BrowserBarcodeReader } from "@zxing/library";

class Barcode extends React.Component {
   codeReader = new BrowserBarcodeReader();
  constructor(props) {
    super(props);
    this.state = { reader: {}, selectedDevice: "" };
    this.startButton = this.startButton.bind(this);
    this.resetButton = this.resetButton.bind(this);
    this.getBarcode = this.getBarcode.bind(this);
  }
  componentDidMount() {
    this.getBarcode();
  }

  startButton() {
    console.log("start", this.codeReader);
    this.codeReader
      .decodeOnceFromVideoDevice(this.state.selectedDevice, "video")
      .then(result => {
        document.getElementById("result").textContent = result.text;
      })
      .catch(err => {
        console.error(err.toString());
        document.getElementById("result").textContent = err;
      });
    console.log(
      `Started continous decode from camera with id ${this.state.selectedDevice}`
    );
  }

  resetButton() {
    this.codeReader && this.codeReader.reset();
    document.getElementById("result").textContent = "";
  }

  getBarcode() {
    let selectedDeviceId;
   
    return this.codeReader.getVideoInputDevices().then(videoInputDevices => {
        const sourceSelect = document.getElementById("sourceSelect");
        selectedDeviceId = videoInputDevices[0].deviceId;
        if (videoInputDevices.length > 1) {
          videoInputDevices.forEach(element => {
            const sourceOption = document.createElement("option");
            sourceOption.text = element.label;
            sourceOption.value = element.deviceId;
            sourceSelect.appendChild(sourceOption);
          });

          sourceSelect.onchange = () => {
            selectedDeviceId = sourceSelect.value;
          };

          const sourceSelectPanel = document.getElementById(
            "sourceSelectPanel"
          );
          sourceSelectPanel.style.display = "block";
        }
        this.setState({
          selectedDevice: selectedDeviceId
        });
      })
      .catch(err => {
        alert(err);
      });
  }

  render() {
    return (
      <div>
        <h2>Barcode</h2>
        {Object.keys(this.codeReader).length > 0 && (
          <div>
            <div>
              <button
                className="button"
                id="startButton"
                onClick={this.startButton}
              >
                Start
              </button>
              <button
                className="button"
                id="resetButton"
                onClick={this.resetButton}
              >
                Reset
              </button>
            </div>

            <div>
              <video
                id="video"
                width="600"
                height="400"
                style={{ border: "1px solid gray" }}
              ></video>
            </div>

            <label>Result:</label>
            <pre>
              <code id="result"></code>
            </pre>
          </div>
        )}
      </div>
    );
  }
}

export default Barcode; ```