Files
graphfx/ui/Components/Value/Image.vue

170 lines
4.5 KiB
Vue

<template>
<div
class="image-value"
@click="onClick"
@mouseenter="isPreviewVisible = true"
@mouseleave="isPreviewVisible = false"
>
<canvas class="image-value__thumb" ref="thumb" />
<canvas class="image-value__preview" ref="preview" />
</div>
</template>
<script>
import {paintToCanvas, mediaSize} from '../../../src/nodes/canvas.js'
import _ from 'lodash';
export default {
props: {
io: {
type: null,
required: true,
},
value: {
type: null,
required: true,
},
direction: {
type: String,
required: true,
}
},
data() {
return {
isRunning: true,
isPreviewVisible: false,
/*redrawThumb: _.throttle(() => {
console.log('redrawThum')
}, 500, {leading: true, trailing: true}),*/
redrawThumb: _.throttle(() => this.redrawCanvas(this.$refs.thumb), 500, {leading: true, trailing: true}),
};
},
mounted() {
this.$nextTick(() => {
this.redraw();
this.io.onchange(this.onChange);
})
},
watch: {
isPreviewVisible(isVisible) {
if (isVisible) {
this.redraw();
}
},
isRunning: {
handler() {
this.redraw();
}
}
},
beforeDestroy() {
this.isRunning = false;
if (this.io) {
this.io.offchange(this.onChange)
}
},
methods: {
onChange() {
this.redraw();
},
redrawCanvas(canvas) {
const value = this.io.value;
/** @type {HTMLCanvasElement} */
const ctx = canvas.getContext('2d');
if (!value) {
canvas.width = 1;
canvas.height = 1;
ctx.clearRect(0, 0, 1, 1);
} else {
const {width, height} = mediaSize(value);
canvas.width = width;
canvas.height = height;
paintToCanvas(canvas, value, {
top: 0,
left: 0,
width, height,
});
}
},
redraw() {
if (this.isRunning) {
this.redrawThumb();
// this.redrawCanvas(this.$refs.thumb);
if (this.isPreviewVisible) {
this.redrawCanvas(this.$refs.preview)
}
}
},
onClick() {
if (this.direction === 'output') {
this.download();
} else {
this.selectFile();
}
},
selectFile() {
const input = document.createElement('input');
window.$$input = input;
input.type = 'file';
input.accept = 'image/*';
input.onchange = (event) => {
const files = event.target.files;
if (files.length) {
const fr = new FileReader()
fr.onload = (event) => {
const image = new Image();
image.onload = () => {
this.$emit('change', image);
this.onChange();
}
image.src = event.target.result;
}
fr.readAsDataURL(files[0]);
}
}
input.click();
},
download() {
const a = document.createElement('a');
a.href = this.$refs.preview.toDataURL();
a.download = 'sample.png';
a.click();
console.log('download');
}
}
}
</script>
<style>
.image-value {
position: relative;
}
.image-value__thumb, .image-value__preview {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJ0lEQVQoU2NsaGj4z4AG6uvr0YUYGIeCwv///2N4prGxEdMzQ0AhAChTL3KV95+lAAAAAElFTkSuQmCC);
background-repeat: repeat;
}
.image-value__thumb {
width: 50px;
height: 50px;
object-fit: contain;
box-shadow: 0 0 6px;
}
.image-value__preview {
display: none;
position: absolute;
top: 0;
left: 0;
width: 30vw;
height: 30vh;
object-fit: contain;
background-color: black;
pointer-events: none;
z-index: 1;
}
.image-value__thumb:hover ~ .image-value__preview {
display: block;
}
</style>