jhuckaby / webcamjs

HTML5 Webcam Image Capture Library with Flash Fallback
MIT License
2.5k stars 1.11k forks source link

TypeError: Object doesn't support property or method '_snap' #290

Open mkaisercross opened 5 years ago

mkaisercross commented 5 years ago

I am trying to get basic webcam functionality in IE11. I have tried the Flash demo and it is working fine for me. However when I try to embed the webcamjs object into a React application I am getting an error in IE11.

TypeError; Object doesn't support property or method '_snap'.

I stepped through the code in the IE11 Debugger and it appears the _snap, _configure, and _releaseCamera are all shown as a property (not method) in the DOM element returned from getMovie however the values are all null.

Below is a minimal example React component for reproducing the issue. Any idea why this might be failing inside a React container?

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Webcam from '../../../lib/webcamjs/webcam'

export default class FlashWebcam extends Component {
    static defaultProps = {
    className: '',
    height: 480,
    imageSmoothing: true,
    onError: (name, description) => {
        console.log("FlashError: " + name + " " + description)
    },
    screenshotFormat: 'image/webp',
    width: 640,
    screenshotQuality: 0.92,
    cropResolution: [-1,-1]
    };

    static propTypes = {
    onError: PropTypes.func,
    height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    screenshotFormat: PropTypes.oneOf([
        'image/webp',
        'image/png',
        'image/jpeg',
    ]),
    style: PropTypes.object,
    className: PropTypes.string,
    screenshotQuality: PropTypes.number,
    minScreenshotWidth: PropTypes.number,
    minScreenshotHeight: PropTypes.number,
    audioConstraints: PropTypes.object,
    videoConstraints: PropTypes.object,
    imageSmoothing: PropTypes.bool,
    cropResolution: PropTypes.arrayOf(PropTypes.number) 
    };

    constructor(props) {
    super(props)
        this.webcamRef = React.createRef();
    Webcam.set({
        width: this.props.width,
        height: this.props.height,
        dest_width: this.resolution[0],
        dest_height: this.resolution[1],
        image_format: 'image/jpeg',
        jpeg_quality: 92,
        enable_flash: true,
        force_flash: true,
        swfURL: "path/to/webcam.swf"
    });
    }

    shouldComponentUpdate(previous, next) {
        return false
    }

    componentDidMount() {
    Webcam.attach(this.webcamRef.current)
    }

    screenshot() {
    return new Promise(function(resolve, reject) {
        Webcam.snap(function(data_uri, canvas, context) {
                     if (data_uri.length > 0) resolve('data:image/jpeg;base64,' + data_uri)
                     else reject("Cannot capture image from camera (Flash)")
        })
    })
    }

    render() {
    return (
        <div ref={this.webcamRef}></div>
    )
    }
}

Also I have tried replacing document.getElementById with the function below and changing the id attributes to class attributes for the object and embed elements. Same issue.

export default function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}