Last active
August 5, 2016 08:44
-
-
Save HenryVonfire/9440ee3b6e452dc5e7c3a20e3ccd9f14 to your computer and use it in GitHub Desktop.
Demo: Take a Selfie With JavaScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| const { Component, computed } = Ember; | |
| export default Component.extend({ | |
| didRender(){ | |
| let video = document.querySelector('#camera-stream'), | |
| start_camera = document.querySelector('#start-camera'); | |
| // The getUserMedia interface is used for handling camera input. | |
| // Some browsers need a prefix so here we're covering all the options | |
| navigator.getMedia = ( navigator.getUserMedia || | |
| navigator.webkitGetUserMedia || | |
| navigator.mozGetUserMedia || | |
| navigator.msGetUserMedia); | |
| if(!navigator.getMedia){ | |
| this.displayErrorMessage("Your browser doesn't have support for the navigator.getUserMedia interface."); | |
| } | |
| else{ | |
| // Request the camera. | |
| navigator.getMedia( | |
| { | |
| video: true | |
| }, | |
| // Success Callback | |
| stream => { | |
| // Create an object URL for the video stream and | |
| // set it as src of our HTLM video element. | |
| video.src = window.URL.createObjectURL(stream); | |
| // Play the video element to start the stream. | |
| video.play(); | |
| video.onplay = () => { | |
| this.showVideo(); | |
| }; | |
| }, | |
| // Error Callback | |
| err => { | |
| this.displayErrorMessage("There was an error with accessing the camera stream: " + err.name, err); | |
| } | |
| ); | |
| } | |
| // Mobile browsers cannot play video without user input, | |
| // so here we're using a button to start it manually. | |
| start_camera.addEventListener("click", function(e){ | |
| e.preventDefault(); | |
| // Start video playback manually. | |
| video.play(); | |
| showVideo(); | |
| }); | |
| }, | |
| showVideo(){ | |
| // Display the video stream and the controls. | |
| let video = document.querySelector('#camera-stream'), | |
| controls = document.querySelector('.controls'); | |
| this.hideUI(); | |
| video.classList.add("visible"); | |
| controls.classList.add("visible"); | |
| }, | |
| takeSnapshot(){ | |
| // Here we're using a trick that involves a hidden canvas element. | |
| let video = document.querySelector('#camera-stream'), | |
| hidden_canvas = document.querySelector('canvas'), | |
| context = hidden_canvas.getContext('2d'); | |
| let width = video.videoWidth, | |
| height = video.videoHeight; | |
| if (width && height) { | |
| // Setup a canvas with the same dimensions as the video. | |
| hidden_canvas.width = width; | |
| hidden_canvas.height = height; | |
| // Make a copy of the current frame in the video on the canvas. | |
| context.drawImage(video, 0, 0, width, height); | |
| // Turn the canvas image into a dataURL that can be used as a src for our photo. | |
| return hidden_canvas.toDataURL('image/png'); | |
| } | |
| }, | |
| displayErrorMessage(error_msg, error){ | |
| error = error || ""; | |
| if(error){ | |
| console.error(error); | |
| } | |
| error_message.innerText = error_msg; | |
| this.hideUI(); | |
| document.querySelector('#error-message').classList.add("visible"); | |
| }, | |
| hideUI(){ | |
| // Helper function for clearing the app UI. | |
| document.querySelector('.controls').classList.remove("visible"); | |
| document.querySelector('#start-camera').classList.remove("visible"); | |
| document.querySelector('#camera-stream').classList.remove("visible"); | |
| document.querySelector('#snap').classList.remove("visible"); | |
| document.querySelector('#error-message').classList.remove("visible"); | |
| }, | |
| actions:{ | |
| take_photo(){ | |
| let snap = this.takeSnapshot(); | |
| this.set('snap',snap); | |
| let image = document.querySelector('#snap'), | |
| delete_photo_btn = document.querySelector('#delete-photo'), | |
| download_photo_btn = document.querySelector('#download-photo'), | |
| video = document.querySelector('#camera-stream'); | |
| // Show image. | |
| image.setAttribute('src', snap); | |
| image.classList.add("visible"); | |
| // Enable delete and save buttons | |
| delete_photo_btn.classList.remove("disabled"); | |
| download_photo_btn.classList.remove("disabled"); | |
| // Set the href attribute of the download button to the snap url. | |
| download_photo_btn.href = snap; | |
| // Pause video playback of stream. | |
| video.pause(); | |
| }, | |
| delete_photo(){ | |
| // Hide image. | |
| let image = document.querySelector('#snap'); | |
| image.setAttribute('src', ""); | |
| image.classList.remove("visible"); | |
| // Disable delete and save buttons | |
| document.querySelector('#delete-photo').classList.add("disabled"); | |
| document.querySelector('#download-photo').classList.add("disabled"); | |
| // Resume playback of stream. | |
| document.querySelector('#camera-stream').play(); | |
| } | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Demo: Take a Selfie With JavaScript', | |
| originalSource: 'http://tutorialzine.com/2016/07/take-a-selfie-with-js/?utm_source=codropscollective' | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body { | |
| margin: 12px 16px; | |
| font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; | |
| font-size: 12pt; | |
| } | |
| @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700'); | |
| *{ | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| html{ | |
| background-color: #fff; | |
| font:normal 16px/1.5 sans-serif; | |
| color: #333; | |
| } | |
| h3{ | |
| font: normal 32px/1.5 'Open Sans', sans-serif; | |
| color: #2c3e50; | |
| margin: 50px 0; | |
| text-align: center; | |
| } | |
| .container{ | |
| max-width: 1000px; | |
| margin: 50px auto; | |
| padding: 20px; | |
| background-color: #efefef; | |
| } | |
| .app{ | |
| width: 100%; | |
| position: relative; | |
| } | |
| .app #start-camera{ | |
| display: none; | |
| border-radius: 3px; | |
| max-width: 400px; | |
| color: #fff; | |
| background-color: #448AFF; | |
| text-decoration: none; | |
| padding: 15px; | |
| opacity: 0.8; | |
| margin: 50px auto; | |
| text-align: center; | |
| } | |
| .app video#camera-stream{ | |
| display: none; | |
| width: 100%; | |
| } | |
| .app img#snap{ | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| z-index: 10; | |
| display: none; | |
| } | |
| .app #error-message{ | |
| width: 100%; | |
| background-color: #ccc; | |
| color: #9b9b9b; | |
| font-size: 28px; | |
| padding: 200px 100px; | |
| text-align: center; | |
| display: none; | |
| } | |
| .app .controls{ | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 20; | |
| display: flex; | |
| align-items: flex-end; | |
| justify-content: space-between; | |
| padding: 30px; | |
| display: none; | |
| } | |
| .app .controls a{ | |
| border-radius: 50%; | |
| color: #fff; | |
| background-color: #111; | |
| text-decoration: none; | |
| padding: 15px; | |
| line-height: 0; | |
| opacity: 0.7; | |
| outline: none; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| .app .controls a:hover{ | |
| opacity: 1; | |
| } | |
| .app .controls a.disabled{ | |
| background-color: #555; | |
| opacity: 0.5; | |
| cursor: default; | |
| pointer-events: none; | |
| } | |
| .app .controls a.disabled:hover{ | |
| opacity: 0.5; | |
| } | |
| .app .controls a i{ | |
| font-size: 18px; | |
| } | |
| .app .controls #take-photo i{ | |
| font-size: 32px; | |
| } | |
| .app canvas{ | |
| display: none; | |
| } | |
| .app video#camera-stream.visible, | |
| .app img#snap.visible, | |
| .app #error-message.visible | |
| { | |
| display: block; | |
| } | |
| .app .controls.visible{ | |
| display: flex; | |
| } | |
| @media(max-width: 1000px){ | |
| .container{ | |
| margin: 40px; | |
| } | |
| .app #start-camera.visible{ | |
| display: block; | |
| } | |
| .app .controls a i{ | |
| font-size: 16px; | |
| } | |
| .app .controls #take-photo i{ | |
| font-size: 24px; | |
| } | |
| } | |
| @media(max-width: 600px){ | |
| .container{ | |
| margin: 10px; | |
| } | |
| .app #error-message{ | |
| padding: 80px 50px; | |
| font-size: 18px; | |
| } | |
| .app .controls a i{ | |
| font-size: 12px; | |
| } | |
| .app .controls #take-photo i{ | |
| font-size: 18px; | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "version": "0.10.4", | |
| "EmberENV": { | |
| "FEATURES": {} | |
| }, | |
| "options": { | |
| "use_pods": false, | |
| "enable-testing": false | |
| }, | |
| "dependencies": { | |
| "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js", | |
| "ember": "2.7.0", | |
| "ember-data": "2.7.0", | |
| "ember-template-compiler": "2.7.0" | |
| }, | |
| "addons": {} | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment