Skip to content

Instantly share code, notes, and snippets.

@GitHub30
Last active October 21, 2019 03:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GitHub30/dfb90c3dabd4e7b1498c4d7db35fcd32 to your computer and use it in GitHub Desktop.
Save GitHub30/dfb90c3dabd4e7b1498c4d7db35fcd32 to your computer and use it in GitHub Desktop.
function addScript(src) {
var script = document.createElement("script");
script.src = src;
document.head.appendChild(script);
}
addScript('https://stuk.github.io/jszip/dist/jszip.js')
unsafeWindow.eval(`
function dropFile(file) {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
window.dispatchEvent(new DragEvent('drop', {dataTransfer}));
}
`)
function photographer(fileInput) {
return new Vue({
el: document.createElement('div'),
template: `<div style="margin-bottom: 16px;">
<video autoplay hidden ref="video" @click.left="takePhoto" @click.right.prevent="closeCamera" @keydown.space.prevent="takePhoto"/>
<button @click.prevent="openCamera">カメラ起動</button>
<button @click.prevent="upload" :disabled="!images.length" v-if="!fileInput">Zip圧縮してアップロード</button>
<div>
<a v-for="(image, i) in images" :href="image.src" target="_blank" :title="image.title" style="position: relative;">
<img :src="image.src" :alt="image.title" width="384px">
<button @click.prevent="removeImage(i)" style="position: absolute;bottom: 4px;right: 4px;height: 28px;padding: 8px;font-size: 24px;color: #fff;font-weight: bold;-webkit-text-stroke: 1px #000;line-height: 1;top: auto !important;">削除</button>
</a>
</div>
</div>`,
data: {
images: [],
fileInput,
constraints: {video: {height: 1080, facingMode: "environment"}}
},
mounted() {
document.addEventListener('keydown', e => {
// Ctrl + Shift + C
if (e.key === 'C' && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey) {
if(this.$refs.video.hidden) {
this.openCamera();
} else {
this.closeCamera();
}
e.preventDefault();
}
});
navigator.mediaDevices.addEventListener('devicechange', async () => {
const devices = await navigator.mediaDevices.enumerateDevices()
for (const device of devices) {
if (device.label.includes('C615') && this.$refs.video.srcObject && !this.$refs.video.srcObject.active) {
this.$refs.video.srcObject = await navigator.mediaDevices.getUserMedia(this.constraints);
}
}
});
},
methods: {
async openCamera() {
this.$refs.video.hidden = false;
this.$refs.video.requestFullscreen();
const stream = await navigator.mediaDevices.getUserMedia(this.constraints);
this.$refs.video.srcObject = stream;
this.$refs.video.focus();
this.$refs.video.onfullscreenchange = () => {
if (document.fullscreenElement) return;
this.closeCamera();
};
},
closeCamera() {
if(document.fullscreenElement) {
document.exitFullscreen();
}
this.$refs.video.hidden = true;
if (this.$refs.video.srcObject) {
this.$refs.video.srcObject.getTracks().forEach(track => track.stop());
this.$refs.video.srcObject = null;
}
},
async takePhoto() {
if (!this.$refs.video.srcObject.active) return;
const blob = await takePhoto(this.$refs.video);
this.images.push({title: moment().toISOString(true).replace(/-|:/g, '') + '.jpg', src: URL.createObjectURL(blob), blob});
},
async zipFile(filename=moment().toISOString(true).replace(/-|:/g, '')) {
unsafeWindow.zip = new unsafeWindow.JSZip();
for(const image of this.images) {
// https://github.com/Stuk/jszip/issues/369
unsafeWindow.zip.file(image.title, image.blob);
}
const zipBlob = await unsafeWindow.eval('zip.generateAsync({type: "blob"})');
return new File([zipBlob], filename + ".zip", zipBlob);
},
removeImage(i) {
this.images.splice(i, 1);
},
async upload() {
const filename = prompt('Please input filename without .zip');
if(!filename) {
return;
}
unsafeWindow.dropFile(await this.zipFile(filename));
}
},
watch: {
async images() {
if(fileInput) {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(await this.zipFile());
fileInput.files = dataTransfer.files;
}
}
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment