Skip to content

Instantly share code, notes, and snippets.

@adczk
Created February 22, 2024 14:45
Show Gist options
  • Save adczk/641de556c2bf0826e101eac8a97d15a7 to your computer and use it in GitHub Desktop.
Save adczk/641de556c2bf0826e101eac8a97d15a7 to your computer and use it in GitHub Desktop.
crude solution to use device's camera with upload filed in Forminator
<?php
// based partially on https://webrtc.github.io/samples/src/content/getusermedia/gum/
/* USE
1. upload as MU plugin
2. make sure there is upload field on the form
3. upload field must be set to "single" type upload
4. and it has to have custom class "csup" added in styling
6. visit form and click on "use camera instead" button, you should see your video
7. click on "take photo now" and you should see still photo frame added
8. you can submit the form now
Note: solution requires also some CSS styling
*/
# add controls
add_filter( 'forminator_field_file_markup', 'forminator_desktop_photo_controls', 90, 1);
function forminator_desktop_photo_controls( $html ) {
$vstream = '<video id="formiv_video" width="500" height="500" autoplay playsinline"></video>';
$vcamera = '<p id="formiv_start-camera">Use Camera instead</p>';
$vphoto = '<p id="formiv_click-photo">TAKE PHOTO NOW</p>';
$vcanvas = '<canvas id="formiv_canvas" width="500" height="500"></canvas>';
$verror = '<div id="formiv_errorMsg"></div>';
$html = $html . $verror . $vstream . $vcamera . $vphoto . $vcanvas;
return $html;
}
add_action( 'wp_footer', 'forminator_desktop_photo_js', 99 );
function forminator_desktop_photo_js() {
?>
<script type="text/javascript">
const constraints = window.constraints = {
audio: false,
video: true
};
function handleSuccess(stream) {
const video = document.querySelector('#formiv_video');
const videoTracks = stream.getVideoTracks();
console.log('Got stream with constraints:', constraints);
console.log(`Using video device: ${videoTracks[0].label}`);
window.stream = stream; // make variable available to browser console
video.srcObject = stream;
}
function handleError(error) {
if (error.name === 'OverconstrainedError') {
const v = constraints.video;
errorMsg(`The resolution ${v.width.exact}x${v.height.exact} px is not supported by your device.`);
} else if (error.name === 'NotAllowedError') {
errorMsg('Permissions have not been granted to use your camera and ' +
'microphone, you need to allow the page access to your devices in ' +
'order for the demo to work.');
}
errorMsg(`getUserMedia error: ${error.name}`, error);
}
function errorMsg(msg, error) {
const errorElement = document.querySelector('#formiv_errorMsg');
errorElement.innerHTML += '<p>${msg}</p>';
if (typeof error !== 'undefined') {
console.error(error);
}
}
async function init(e) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
e.target.disabled = true;
} catch (e) {
handleError(e);
}
}
document.querySelector('#formiv_start-camera').addEventListener('click', e => init(e));
let click_button = document.querySelector("#formiv_click-photo");
let canvas = document.querySelector("#formiv_canvas");
let xvideo = document.querySelector("#formiv_video");
click_button.addEventListener('click', function() {
canvas.getContext('2d').drawImage(xvideo, 0, 0, canvas.width, canvas.height);
let image_data_url = canvas.toDataURL("image/jpeg");
let fileInputElement = document.querySelector(".csup input");
let container = new DataTransfer();
var dataURL = canvas.toDataURL();
var blob = dataURItoBlob(dataURL);
let ufile = new File([blob], "test.jpg",{type:"image/jpeg", lastModified:new Date().getTime()});
container.items.add(ufile);
fileInputElement.files = container.files;
console.log(fileInputElement.files);
});
// helper function (source: https://stackoverflow.com/a/12300351)
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
var ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;
}
</script>
<?php
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment