diff --git a/src/assets/css/4-modules/preview.css b/src/assets/css/4-modules/preview.css
index e83324a..3bc2a1c 100644
--- a/src/assets/css/4-modules/preview.css
+++ b/src/assets/css/4-modules/preview.css
@@ -49,6 +49,10 @@
content: none;
}
+.preview--flip {
+ transform: scaleX(-1);
+}
+
.preview-visual {
position: absolute;
top: 0;
diff --git a/src/services/camera.js b/src/services/camera.js
new file mode 100644
index 0000000..8b2f2d8
--- /dev/null
+++ b/src/services/camera.js
@@ -0,0 +1,29 @@
+export async function getCamera (shouldFaceUser) {
+ const facingModeList = shouldFaceUser
+ ? ['user', 'environment']
+ : ['environment', 'user']
+
+ const [preferredFacingMode] = facingModeList
+
+ const constraintsList = [
+ ...facingModeList.map(facingMode => ({ exact: facingMode })),
+ preferredFacingMode
+ ].map(facingModeConstraint => ({ video: { facingMode: facingModeConstraint } }))
+
+ for (let constraints of constraintsList) {
+ try {
+ console.log(constraints)
+ return {
+ mediaStream: await navigator.mediaDevices.getUserMedia(constraints),
+ facingMode: constraints.video.facingMode.exact ? constraints.video.facingMode.exact : 'unknow'
+ }
+ } catch (error) {
+ console.log(error)
+ if (error.name !== 'OverconstrainedError' && error.constraint === 'facingMode') {
+ throw error
+ }
+ }
+ }
+
+ throw new Error('Overconstrained')
+}
diff --git a/src/services/capture.js b/src/services/capture.js
index c507b96..97937f4 100644
--- a/src/services/capture.js
+++ b/src/services/capture.js
@@ -8,7 +8,7 @@ import {
GIF_FRAME_RATE
} from '/constants.js'
-export function capture (mediaStream, duration) {
+export function capture (mediaStream, duration, facingMode) {
const emitter = new EventEmitter()
Promise.resolve().then(async () => {
@@ -33,9 +33,15 @@ export function capture (mediaStream, duration) {
canvas.width = GIF_WIDTH
canvas.height = GIF_HEIGHT
- const canvasContext = canvas.getContext('2d')
const destinationRectangle = makeRectangle(0, 0, canvas.width, canvas.height)
+ const canvasContext = canvas.getContext('2d')
+
+ if (facingMode === 'user' || facingMode === 'unknow') {
+ canvasContext.translate(destinationRectangle.width, 0)
+ canvasContext.scale(-1, 1)
+ }
+
const video = document.createElement('video')
video.setAttribute('playsinline', '')
video.setAttribute('webkit-playsinline', '')
diff --git a/src/store.js b/src/store.js
index 361cd8f..c5a95cc 100644
--- a/src/store.js
+++ b/src/store.js
@@ -1,6 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
+import { getCamera } from '/services/camera.js'
import { capture } from '/services/capture.js'
import { encode } from '/services/encode.js'
@@ -11,6 +12,7 @@ export default new Vuex.Store({
state: {
welcomed: false,
mediaStream: null,
+ facingMode: null,
timer: {
selected: 2,
list: [2, 3, 5]
@@ -34,8 +36,9 @@ export default new Vuex.Store({
updateWelcomed (state, welcome) {
state.welcomed = welcome
},
- startCamera (state, mediaStream) {
+ startCamera (state, { mediaStream, facingMode }) {
state.mediaStream = mediaStream
+ state.facingMode = facingMode
},
stopCamera (state) {
if (state.mediaStream) {
@@ -43,6 +46,10 @@ export default new Vuex.Store({
}
state.mediaStream = null
+ state.facingMode = null
+ },
+ updateFacingMode (state, facingMode) {
+ state.facingMode = facingMode
},
inverseFacingMode (state) {
state.capturing.shouldFaceUser = !state.capturing.shouldFaceUser
@@ -84,37 +91,28 @@ export default new Vuex.Store({
}
},
actions: {
- requestCamera ({ state, commit }, inverseFacingMode) {
+ async requestCamera ({ state, commit }, inverseFacingMode) {
+ commit('stopCamera')
+
const shouldFaceUser = inverseFacingMode
? !state.capturing.shouldFaceUser
: state.capturing.shouldFaceUser
- const constraints = {
- video: {
- facingMode: shouldFaceUser ? 'user' : 'environment'
- },
- audio: false
+ try {
+ commit('startCamera', await getCamera(shouldFaceUser))
+
+ if (inverseFacingMode) {
+ commit('inverseFacingMode')
+ }
+ } catch (error) {
+ console.error(error)
+ window.alert('You haven\'t allowed to use your camera.\n\nOr maybe your browser is not compatible :(')
+ commit('updateWelcomed', false)
}
-
- commit('stopCamera')
-
- navigator.mediaDevices.getUserMedia(constraints)
- .then(mediaStream => {
- commit('startCamera', mediaStream)
-
- if (inverseFacingMode) {
- commit('inverseFacingMode')
- }
- })
- .catch(error => {
- console.error(error)
- window.alert('You haven\'t allowed to use your camera.\n\nOr maybe your browser is not compatible :(')
- commit('updateWelcomed', false)
- })
},
capture ({ state, commit, dispatch }) {
commit('startCapture')
- const capturing = capture(state.mediaStream, state.timer.selected * 1000)
+ const capturing = capture(state.mediaStream, state.timer.selected * 1000, state.facingMode)
capturing.once('error', error => console.error(error))
diff --git a/src/views/screens/capture.vue b/src/views/screens/capture.vue
index 7af007f..a4abc22 100644
--- a/src/views/screens/capture.vue
+++ b/src/views/screens/capture.vue
@@ -6,7 +6,7 @@