简体   繁体   中英

Can't figure out how to fix this: “Uncaught TypeError (webcam.snap is not a function)” <— javascript

I have a JavaScript script that I am getting an error for that I can't figure out. I am trying to take a picture of the webcam feed using JavaScript

The error is:

Uncaught TypeError: webcam.snap is not a function

I am using webcam.js to take the snapshot.

Here is my JavaScript code:

  <script>
    var video = document.createElement("video");
    var canvasElement = document.getElementById("canvas");
    var canvas = canvasElement.getContext("2d");
    var loadingMessage = document.getElementById("loadingMessage");
    var outputContainer = document.getElementById("output");
    var outputMessage = document.getElementById("outputMessage");
    var outputData = document.getElementById("outputData");
    const jsQR = require("jsqr");

    function drawLine(begin, end, color) {
      canvas.beginPath();
      canvas.moveTo(begin.x, begin.y);
      canvas.lineTo(end.x, end.y);
      canvas.lineWidth = 4;
      canvas.strokeStyle = color;
      canvas.stroke();
    }

    // Use facingMode: environment to attemt to get the front camera on phones
    navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
      video.srcObject = stream;
      video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
      video.play();
      requestAnimationFrame(tick);
    });

    function tick() {
      loadingMessage.innerText = "⌛ Loading video..."
      if (video.readyState === video.HAVE_ENOUGH_DATA) {
        loadingMessage.hidden = true;
        canvasElement.hidden = false;
        outputContainer.hidden = false;

        canvasElement.height = video.videoHeight;
        canvasElement.width = video.videoWidth;
        canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
        var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
        var code = jsQR(imageData.data, imageData.width, imageData.height, {
          inversionAttempts: "invertFirst",
        });
        if (code) {
          drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
          drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
          drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
          drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
          outputMessage.hidden = true;
          outputData.parentElement.hidden = false;
          outputData.innerText = code.data;

          takeSnapShot();
        }

        else {
          outputMessage.hidden = false;
          outputData.parentElement.hidden = true;
        }
      }
      requestAnimationFrame(tick);
    }

    // TAKE A SNAPSHOT.
    takeSnapShot = function () {
        webcam.snap(function (data_uri) {
            downloadImage('video', data_uri);
        });
    }

    // DOWNLOAD THE IMAGE.
    downloadImage = function (name, datauri) {
        var a = document.createElement('a');
        a.setAttribute('download', name + '.png');
        a.setAttribute('href', datauri);
        a.click();
    }

  </script>

This is the first line that causes a problem:

webcam.snap(function (data_uri) {
    downloadImage('video', data_uri);
});

This is the second line that causes a problem:

takeSnapShot();

how do I correct this properly?

****** UPDATE ******

The version of webcam.js I am using is WebcamJS v1.0.26. My application is a Django application that launches the HTML file as defined in main.js .

snap: function(user_callback, user_canvas) {
        // use global callback and canvas if not defined as parameter
        if (!user_callback) user_callback = this.params.user_callback;
        if (!user_canvas) user_canvas = this.params.user_canvas;
        
        // take snapshot and return image data uri
        var self = this;
        var params = this.params;
        
        if (!this.loaded) return this.dispatch('error', new WebcamError("Webcam is not loaded yet"));
        // if (!this.live) return this.dispatch('error', new WebcamError("Webcam is not live yet"));
        if (!user_callback) return this.dispatch('error', new WebcamError("Please provide a callback function or canvas to snap()"));
        
        // if we have an active preview freeze, use that
        if (this.preview_active) {
            this.savePreview( user_callback, user_canvas );
            return null;
        }
        
        // create offscreen canvas element to hold pixels
        var canvas = document.createElement('canvas');
        canvas.width = this.params.dest_width;
        canvas.height = this.params.dest_height;
        var context = canvas.getContext('2d');
        
        // flip canvas horizontally if desired
        if (this.params.flip_horiz) {
            context.translate( params.dest_width, 0 );
            context.scale( -1, 1 );
        }
        
        // create inline function, called after image load (flash) or immediately (native)
        var func = function() {
            // render image if needed (flash)
            if (this.src && this.width && this.height) {
                context.drawImage(this, 0, 0, params.dest_width, params.dest_height);
            }
            
            // crop if desired
            if (params.crop_width && params.crop_height) {
                var crop_canvas = document.createElement('canvas');
                crop_canvas.width = params.crop_width;
                crop_canvas.height = params.crop_height;
                var crop_context = crop_canvas.getContext('2d');
                
                crop_context.drawImage( canvas, 
                    Math.floor( (params.dest_width / 2) - (params.crop_width / 2) ),
                    Math.floor( (params.dest_height / 2) - (params.crop_height / 2) ),
                    params.crop_width,
                    params.crop_height,
                    0,
                    0,
                    params.crop_width,
                    params.crop_height
                );
                
                // swap canvases
                context = crop_context;
                canvas = crop_canvas;
            }
            
            // render to user canvas if desired
            if (user_canvas) {
                var user_context = user_canvas.getContext('2d');
                user_context.drawImage( canvas, 0, 0 );
            }
            
            // fire user callback if desired
            user_callback(
                user_canvas ? null : canvas.toDataURL('image/' + params.image_format, params.jpeg_quality / 100 ),
                canvas,
                context
            );
        };
        
        // grab image frame from userMedia or flash movie
        if (this.userMedia) {
            // native implementation
            context.drawImage(this.video, 0, 0, this.params.dest_width, this.params.dest_height);
            
            // fire callback right away
            func();
        }
        else if (this.iOS) {
            var div = document.getElementById(this.container.id+'-ios_div');
            var img = document.getElementById(this.container.id+'-ios_img');
            var input = document.getElementById(this.container.id+'-ios_input');
            // function for handle snapshot event (call user_callback and reset the interface)
            iFunc = function(event) {
                func.call(img);
                img.removeEventListener('load', iFunc);
                div.style.backgroundImage = 'none';
                img.removeAttribute('src');
                input.value = null;
            };
            if (!input.value) {
                // No image selected yet, activate input field
                img.addEventListener('load', iFunc);
                input.style.display = 'block';
                input.focus();
                input.click();
                input.style.display = 'none';
            } else {
                // Image already selected
                iFunc(null);
            }           
        }
        else {
            // flash fallback
            var raw_data = this.getMovie()._snap();
            
            // render to image, fire callback when complete
            var img = new Image();
            img.onload = func;
            img.src = 'data:image/'+this.params.image_format+';base64,' + raw_data;
        }
        
        return null;
    },

It seems like either:

  1. the webcam's code are missing (not imported)
    • in this case you need to first call the script from the URL and add it with script tag
<script src="WEBCAM_JS_SOURCE">

or

  1. they are imported, but used with typo. From the webcam source code it is defined as :
var Webcam = {
   version: '1.0.26',
   
   // globals
   ...
};

so you should use with a capital one.

Your implementation doesn't need Webcamjs, because you're using navigator media devices.

You can either use WebcamJS by initializing it at first and attaching it to some canvas, like in the following code

Webcam.set({
        width: 320,
        height: 240,
        image_format: 'jpeg',
        jpeg_quality: 90
    });
Webcam.attach( '#my_camera' );

Or you can update your takeSnapShot function to the following :

 takeSnapShot = function () {
        downloadImage('video',canvasElement.toDataURL())
        // Webcam.snap(function (data_uri) {
        //     downloadImage('video', data_uri);
        // });
    }

Here's a working example based on your code https://codepen.io/majdsalloum/pen/RwVKBbK

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM