从类外部访问/传递对象到类方法

时间:2019-03-02 09:41:37

标签: javascript getusermedia dropzone

我为getUserMedia创建了一个类。只要我想将记录的Blob添加到Dropzone中,一切都可以正常工作。

我已经初始化了Dropzone对象,例如:

var threadUpload = $("#thread-upload form").dropzone({...});

初始化的对象UserMediaRecorder如下:

var recorder = new UserMediaRecorder({
    openbutton: '#video-tab',
    containerClass: 'noSwipe noSwipe2',
    constraints: {
        audio: false,
        video: {
            width: { max: 1920 },
            height: { max: 1920 },
            facingMode:"user",
            frameRate: {ideal: 30, min:10},
            aspectRatio : 1920/1080
        }
    },
    limit: 10,
    onfileupload: function(blob, threadUpload){
        console.log(blob);
        threadUpload.addFile(blob);
    }
});

整个课程UserMediaRecorder可以在这里看到:https://jsfiddle.net/igor77/zkqg27eh/31/

我的问题是我无法将blob传递给Dropzone对象threadUpload。我试图将其作为参数传递,但未更改任何内容,但仍显示为未定义。有什么方法可以从其他类内部将blob传递到Dropzone吗?

1 个答案:

答案 0 :(得分:0)

将点击事件侦听器绑定到sendButton上时,您将失去当前作用域。

要解决此问题,请将evenListener中的函数作为类中的方法,然后将其传递给绑定类作用域的eventListener。

例如:

this.sendButton.addEventListener('click', this.sendVideo.bind(this));

,然后在您的班级中添加sendVideo方法:

sendVideo() {
   var blob;
   if (this.sendButton.textContent === 'Send Picture') {
            blob = this.dataURItoBlob(this.canvas.toDataURL( 'image/jpeg' ))
            this.clearCanvas();
            console.log('sending pic');
        }else if(this.sendButton.textContent === 'Send Video'){
            blob = new Blob(this.recordedBlobs, {type: 'video/mp4'});
            console.log('sending vid');
        }
    this.onfileupload(blob);
    this.sendButton.disabled = true;
}

这是完整的代码。请注意,由于安全性限制,它将无法运行,但是可以将其粘贴回您的小提琴中。

class UserMediaRecorder {
    constructor(options) {
        this.openbutton = '#openRecordPanel';
        if (typeof options.openbutton !== 'undefined'){
            this.openbutton = options.openbutton;
        }
        this.lengthSeconds = false;
        if (typeof options.limit !== 'undefined'){
            this.lengthSeconds = options.limit;
        }
        this.msecondsLeft;
        this.isPaused = false;
        this.constraints = {audio: true, video: true};
        if (typeof options.constraints !== 'undefined'){
            this.constraints = options.constraints;
        }
        this.containerClass = '';
        if (typeof options.containerClass !== 'undefined'){
            this.containerClass = options.containerClass;
        }
        if (typeof options.onfileupload !== 'undefined'){
            this.onfileupload = options.onfileupload.bind(this);
        }
        
        this.openVideoPanelButton = document.querySelector(this.openbutton);
        this.openVideoPanelButton.addEventListener('click', async (e) => {
            e.preventDefault();
            this.openVideoPanel();
        });
        
        console.log('initialized');
    }
    async bindElements(){
        this.closeVideoPanelButton = this.overlay.querySelector('button.close-record-panel');
        this.video = this.overlay.querySelector('video');
        this.canvas = window.canvas = this.overlay.querySelector('canvas');
        this.switchCameraButton = this.overlay.querySelector('button.switch-camera');
        this.stopButton = this.overlay.querySelector('button.stop-recording');
        this.recordButton = this.overlay.querySelector('button.start-recording');
        this.snapshotButton = this.overlay.querySelector('button.snapshot');
        this.sendButton = this.overlay.querySelector('button.send-recording');
        this.counterBlock = this.overlay.querySelector('div.counter');
        console.log('elements defined');
    }
    async bindEvents(){
        this.closeVideoPanelButton.addEventListener('click', () => {
            this.closeVideoPanel();
        });
        this.switchCameraButton.addEventListener('click', async () => {
            this.switchCamera();
        });
        this.stopButton.addEventListener('click', () => {
            this.stopRecording();
        });
        this.recordButton.addEventListener('click', (e) => {
            if (this.recordButton.textContent === 'Start') {
                this.canvas.style.display = "none";
                this.startRecording();
            }else if(this.recordButton.textContent === 'Pause'){
                this.pauseRecording();
            }else if(this.recordButton.textContent === 'Resume'){
                this.resumeRecording();
            }
        });
        this.snapshotButton.addEventListener('click', () => {
            if (this.snapshotButton.textContent === 'Snapshot') {
                this.canvas.style.display = "block";
                this.canvas.width = this.video.videoWidth;
                this.canvas.height = this.video.videoHeight;
                this.canvas.getContext('2d').drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
                this.snapshotButton.textContent = 'Cancel';
                this.sendButton.disabled = false;
                this.sendButton.textContent = 'Send Picture';
            }else if(this.snapshotButton.textContent === 'Cancel'){
                this.clearCanvas();
            }
        });
        this.sendButton.addEventListener('click', this.sendVideo.bind(this));
        window.addEventListener('onfileupload', this.onfileupload.bind(this));
        console.log('events bound');
    }
    sendVideo() {
        var blob;
        if (this.sendButton.textContent === 'Send Picture') {
            blob = this.dataURItoBlob(this.canvas.toDataURL( 'image/jpeg' ))
            this.clearCanvas();
            console.log('sending pic');
        }else if(this.sendButton.textContent === 'Send Video'){
            blob = new Blob(this.recordedBlobs, {type: 'video/mp4'});
            console.log('sending vid');
        }
        this.onfileupload(blob);
        this.sendButton.disabled = true;
    }
    async openVideoPanel(){
        this.overlay = document.createElement('div');
        this.overlay.style.cssText = 'position:fixed;top:0;bottom:0;left:0;right:0;background:rgba(0,0,0,.3);z-index:1100;';
        document.body.appendChild(this.overlay);
        
        this.overlay.innerHTML = '<div class="' + this.containerClass + '" style="width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;">' +
        '<div style="position:relative">' +
        '<video autoplay playsinline muted style="max-width:100vw;max-height:100vh"></video>' +
        '<canvas style="position:absolute;top:0;left:0;max-width:100vw;max-height:100vh;display:none"></canvas>' +
        '<div style="position:absolute;width:100%;top:auto;bottom:20px;display:flex;flex-wrap: wrap;justify-content:center;">' +
        '<div style="width:auto"><button class="switch-camera">Switch Camera</button></div>' +
        '<div style="width:auto"><button class="stop-recording" disabled>Stop</button></div>' +
        '<div style="width:auto"><button class="start-recording">Start</button></div>' +
        '<div style="width:auto"><button class="snapshot">Snapshot</button></div>' +
        '<div style="width:auto"><button class="send-recording" disabled>Send</button></div>' +
        '<div class="counter" style="width: 100%;text-align: center;">00:00:00</div>' +
        '</div>' +
        '</div>' +
        '<button class="close-record-panel" style="position:absolute;top:20px;left:auto;right:20px;">Close</button>' +
        '</div>';
        await this.bindElements();
        await this.bindEvents();
        await this.initStream();
        console.log('opened');
    }
    closeVideoPanel() {
        if (this.stream) {
            this.stream.getTracks().forEach(track => {
                track.stop();
            });
        }
        this.overlay.remove();
    }
    async initStream() {
        try {
            this.stream = await navigator.mediaDevices.getUserMedia(this.constraints);
            this.handleSuccess(this.stream);
        } catch (e) {
            console.error('navigator.getUserMedia error:', e);
        }
    }
    handleSuccess() {
        window.stream = this.stream;
        this.video.srcObject = this.stream;
    }
    async switchCamera() {
        console.log('getUserMedia() switching camera:', this.stream);
        if(this.constraints.video.facingMode === "user"){
            this.constraints.video.facingMode = "environment";
        }else{
            this.constraints.video.facingMode = "user";
        }
        console.log('Camera changed to ' + this.constraints.video.facingMode);
        await this.initStream(this.constraints);
    }
    startRecording() {
        this.snapshotButton.disabled = true;
        this.sendButton.disabled = true;
        this.stopButton.disabled = false;
        this.recordButton.textContent = 'Pause';
        
        this.recordedBlobs = [];
        let options = {mimeType: 'video/webm;codecs=vp9'};
        if (!MediaRecorder.isTypeSupported(options.mimeType)) {
            console.error(`${options.mimeType} is not Supported`);
            options = {mimeType: 'video/webm;codecs=vp8'};
            if (!MediaRecorder.isTypeSupported(options.mimeType)) {
                console.error(`${options.mimeType} is not Supported`);
                options = {mimeType: 'video/webm'};
                if (!MediaRecorder.isTypeSupported(options.mimeType)) {
                    console.error(`${options.mimeType} is not Supported`);
                    options = {mimeType: ''};
                }
            }
        }
        try {
            this.mediaRecorder = new MediaRecorder(window.stream, options);
        } catch (e) {
            console.error('Exception while creating MediaRecorder:', e);
            return;
        }
        
        console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options);
        this.mediaRecorder.onstop = (event) => {
            console.log('Recorder stopped: ', event);
        };
        console.log(this);
        this.mediaRecorder.ondataavailable = (event) => {
            if (event.data && event.data.size > 0) {
                this.recordedBlobs.push(event.data);
            }
        };
        this.mediaRecorder.start(10); // collect 10ms of data
        console.log('MediaRecorder started', this.mediaRecorder);
        this.startTimer();
        return this.recordedBlobs;
    }
    stopRecording() {
        this.mediaRecorder.stop();
        this.stopTimer();
        this.recordButton.textContent = 'Start';
        this.snapshotButton.disabled = false;
        this.sendButton.disabled = false;
        this.sendButton.textContent = 'Send Video';
        this.stopButton.disabled = true;
        console.log('Recorded Blobs: ', this.recordedBlobs);
    }
    pauseRecording(){
        this.mediaRecorder.pause();
        this.pauseTimer();
        this.recordButton.textContent = 'Resume';
    }
    resumeRecording(){
        this.mediaRecorder.resume();
        this.resumeTimer();
        this.recordButton.textContent = 'Pause';
    }
    clearCanvas(){
        this.snapshotButton.textContent = 'Snapshot';
        this.canvas.style.display = 'none';
        this.canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
        this.sendButton.disabled = true;
    }
    dataURItoBlob(dataURI) {
        var byteString, 
        mimestring 
        if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
            byteString = atob(dataURI.split(',')[1])
        } else {
            byteString = decodeURI(dataURI.split(',')[1])
        }
        mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]
        var content = new Array();
        for (var i = 0; i < byteString.length; i++) {
            content[i] = byteString.charCodeAt(i)
        }
        return new Blob([new Uint8Array(content)], {type: mimestring});
    }
    startTimer(){
        if (!this.isPaused && this.lengthSeconds){
            this.msecondsLeft = this.lengthSeconds * 100;
        }else if(!this.lengthSeconds){
            this.msecondsLeft = 1;
        }
        var that = this;
        var counter = function(){
            if (that.msecondsLeft > 0){
                if(!that.lengthSeconds){
                    that.msecondsLeft++;
                }else{
                    that.msecondsLeft--;
                }
                var ms = that.msecondsLeft % 100;
                if(ms < 10){ ms = "0" + ms}
                var s = ((that.msecondsLeft - ms) / 100) % 60;
                if(s < 10){ s = "0" + s}
                var m = ((that.msecondsLeft - ms - (s * 100)) / 100) /60;
                if(m < 10){ m = "0" + m}
                that.counterBlock.innerHTML = m + ":" + s + ":" + ms;
            }else{
                that.stopRecording();
                that.isPaused = false;
            }
        };
        this.timer = setInterval(counter,10);
    }
    resumeTimer(){
        this.isPaused = true;
        this.startTimer();
    }
    pauseTimer(){
        this.isPaused = true;
        this.stopTimer();
    }
    stopTimer(){
        clearInterval(this.timer);
    }
}

var recorder = new UserMediaRecorder({
    openbutton: '#openRecordPanel',
    containerClass: 'noSwipe noSwipe2',
    constraints: {
        audio: false,
        video: {
            width: { max: 1920 },
            height: { max: 1920 },
            facingMode:"user",
            frameRate: {ideal: 30, min:10},
            aspectRatio : 1920/1080
        }
    },
    limit: 10,
    onfileupload: function(blob){
        console.log(blob);
        //		threadUpload.addFile(blob);
    }
});