Use some icons
continuous-integration/drone/push Build is passing Details

main
Clément FRÉVILLE 1 year ago
parent 6a904b705a
commit fdf0919333

@ -11,9 +11,11 @@
}, },
"dependencies": { "dependencies": {
"gif.js": "^0.2.0", "gif.js": "^0.2.0",
"unplugin-icons": "^0.18.5",
"vue": "^3.3.11" "vue": "^3.3.11"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/octicon": "^1.1.52",
"@types/gif.js": "^0.2.5", "@types/gif.js": "^0.2.5",
"@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/eslint-plugin": "^6.21.0",
"@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue": "^5.0.3",

@ -1,6 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import * as GIF from 'gif.js'; import * as GIF from 'gif.js';
import { downloadBlob } from '../download.ts';
import IconPlus from '~icons/octicon/feed-plus-16';
import IconPlay from '~icons/octicon/play-16';
defineEmits<{ defineEmits<{
selected: [image: HTMLImageElement] selected: [image: HTMLImageElement]
@ -31,12 +34,7 @@ function onAnimateClick(): void {
}); });
images.value.forEach((img) => gif.addFrame(img, { delay: 200 })); images.value.forEach((img) => gif.addFrame(img, { delay: 200 }));
gif.on('finished', (blob: Blob) => { gif.on('finished', (blob: Blob) => {
const url = URL.createObjectURL(blob); downloadBlob(blob, 'animation.gif')
const a = document.createElement('a');
a.href = url;
a.download = 'animation.gif';
a.click();
URL.revokeObjectURL(url);
}); });
gif.render(); gif.render();
} }
@ -49,12 +47,16 @@ defineExpose({
<template> <template>
<div class="file-column"> <div class="file-column">
<input id="file-upload" type="file" @change="onFileChange"> <input id="file-upload" type="file" @change="onFileChange">
<label for="file-upload" class="button">Add</label> <label for="file-upload" class="button">
Add
<icon-plus />
</label>
<div v-for="(img, idx) in images" :key="idx" class="image-file"> <div v-for="(img, idx) in images" :key="idx" class="image-file">
<img :src="img.src" width="64" height="64" alt="" draggable="true" @click="$emit('selected', img)" @dragstart="onDragStart($event, idx)" /> <img :src="img.src" width="64" height="64" alt="" draggable="true" @click="$emit('selected', img)" @dragstart="onDragStart($event, idx)" />
</div> </div>
<button v-if="images.length" @click="onAnimateClick"> <button v-if="images.length" @click="onAnimateClick">
Animate Animate
<icon-play />
</button> </button>
</div> </div>
</template> </template>

@ -4,6 +4,8 @@ import { blackAndWhite, grayScale } from '../processing/gray-scale.ts';
import ImageCollection from './ImageCollection.vue'; import ImageCollection from './ImageCollection.vue';
import { mergeImages } from '../processing/merge.ts'; import { mergeImages } from '../processing/merge.ts';
import { drawOffscreen } from '../processing/offscreen.ts'; import { drawOffscreen } from '../processing/offscreen.ts';
import { download } from '../download.ts';
import IconDownload from '~icons/octicon/download-16';
const canvas = ref<HTMLCanvasElement | null>(null); const canvas = ref<HTMLCanvasElement | null>(null);
const collection = ref<typeof ImageCollection>(); const collection = ref<typeof ImageCollection>();
@ -102,6 +104,10 @@ function onDrop(event: DragEvent) {
function onDragLeave() { function onDragLeave() {
overlay.value = null; overlay.value = null;
} }
function downloadImage() {
download(canvas.value!.toDataURL('image/png'), 'image.png');
}
</script> </script>
<template> <template>
@ -115,6 +121,9 @@ function onDragLeave() {
<button @click="grayScaleApply"> <button @click="grayScaleApply">
Gray-scale Gray-scale
</button> </button>
<button @click="downloadImage">
Download <icon-download />
</button>
</div> </div>
<div class="inner"> <div class="inner">
<input v-model="currentHeight" type="range" min="5" max="200" value="100" orient="vertical" @change="onChangeSlideHeight"> <input v-model="currentHeight" type="range" min="5" max="200" value="100" orient="vertical" @change="onChangeSlideHeight">

@ -0,0 +1,13 @@
export function download(value: string, filename: string): void {
const a = document.createElement('a');
a.href = value;
a.download = filename;
a.click();
a.remove();
}
export function downloadBlob(blob: Blob, filename: string): void {
const url = URL.createObjectURL(blob);
download(url, filename);
URL.revokeObjectURL(url);
}

@ -79,7 +79,7 @@ button:focus-visible,
a:hover { a:hover {
color: #747bff; color: #747bff;
} }
button { button, .button {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
} }
@ -108,3 +108,7 @@ button:focus-visible,
height: 50%; height: 50%;
top: 50%; top: 50%;
} }
svg {
vertical-align: middle;
}

@ -4,6 +4,7 @@
"useDefineForClassFields": true, "useDefineForClassFields": true,
"module": "ESNext", "module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"], "lib": ["ES2020", "DOM", "DOM.Iterable"],
"types": ["vite/client", "unplugin-icons/types/vue"],
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */

@ -1,7 +1,8 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue(), Icons({ compiler: 'vue3' })],
}) })

Loading…
Cancel
Save