aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/index.ts8
-rw-r--r--src/tools/svg-placeholder-generator/index.ts11
-rw-r--r--src/tools/svg-placeholder-generator/svg-placeholder-generator.vue89
3 files changed, 107 insertions, 1 deletions
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 5a218f3..6f30200 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -25,6 +25,7 @@ import { tool as qrCodeGenerator } from './qr-code-generator';
import { tool as randomPortGenerator } from './random-port-generator';
import { tool as romanNumeralConverter } from './roman-numeral-converter';
import { tool as sqlPrettify } from './sql-prettify';
+import { tool as svgPlaceholderGenerator } from './svg-placeholder-generator';
import { tool as textStatistics } from './text-statistics';
import { tool as tokenGenerator } from './token-generator';
import { tool as urlEncoder } from './url-encoder';
@@ -53,7 +54,12 @@ export const toolsByCategory: ToolCategory[] = [
{
name: 'Web',
icon: LockOpen,
- components: [urlEncoder, htmlEntities, qrCodeGenerator, urlParser, deviceInformation, basicAuthGenerator],
+ components: [urlEncoder, htmlEntities, urlParser, deviceInformation, basicAuthGenerator],
+ },
+ {
+ name: 'Images',
+ icon: LockOpen,
+ components: [qrCodeGenerator, svgPlaceholderGenerator],
},
{
name: 'Development',
diff --git a/src/tools/svg-placeholder-generator/index.ts b/src/tools/svg-placeholder-generator/index.ts
new file mode 100644
index 0000000..d676294
--- /dev/null
+++ b/src/tools/svg-placeholder-generator/index.ts
@@ -0,0 +1,11 @@
+import { ImageOutlined } from '@vicons/material';
+import { defineTool } from '../tool';
+
+export const tool = defineTool({
+ name: 'SVG placeholder generator',
+ path: '/svg-placeholder-generator',
+ description: 'Generate svg images to use as placeholder in your applications.',
+ keywords: ['svg', 'placeholder', 'generator', 'image', 'size', 'mockup'],
+ component: () => import('./svg-placeholder-generator.vue'),
+ icon: ImageOutlined,
+});
diff --git a/src/tools/svg-placeholder-generator/svg-placeholder-generator.vue b/src/tools/svg-placeholder-generator/svg-placeholder-generator.vue
new file mode 100644
index 0000000..33c0f69
--- /dev/null
+++ b/src/tools/svg-placeholder-generator/svg-placeholder-generator.vue
@@ -0,0 +1,89 @@
+<template>
+ <div>
+ <n-form label-placement="left" label-width="100">
+ <n-space item-style="flex:1 1 0">
+ <n-form-item label="Width (in px)">
+ <n-input-number v-model:value="width" placeholder="SVG width..." min="1" />
+ </n-form-item>
+ <n-form-item label="Background">
+ <n-color-picker v-model:value="bgColor" :modes="['hex']" />
+ </n-form-item>
+ </n-space>
+ <n-space item-style="flex:1 1 0">
+ <n-form-item label="Height (in px)">
+ <n-input-number v-model:value="height" placeholder="SVG height..." min="1" />
+ </n-form-item>
+ <n-form-item label="Text color">
+ <n-color-picker v-model:value="fgColor" :modes="['hex']" />
+ </n-form-item>
+ </n-space>
+ <n-space item-style="flex:1 1 0">
+ <n-form-item label="Font size">
+ <n-input-number v-model:value="fontSize" placeholder="Font size..." min="1" />
+ </n-form-item>
+ <n-form-item label="Custom text">
+ <n-input v-model:value="customText" :placeholder="`Default is ${width}x${height}`" />
+ </n-form-item>
+ </n-space>
+ <n-form-item label="Use exact size" label-placement="left">
+ <n-switch v-model:value="useExactSize" />
+ </n-form-item>
+ </n-form>
+
+ <n-form-item label="SVG HTML element">
+ <textarea-copyable :value="svgString" copy-placement="none" />
+ </n-form-item>
+ <n-form-item label="SVG in Base64">
+ <textarea-copyable :value="base64" copy-placement="none" />
+ </n-form-item>
+
+ <n-space justify="center">
+ <n-button secondary @click="copySVG()">Copy svg</n-button>
+ <n-button secondary @click="copyBase64()">Copy base64</n-button>
+ <n-button secondary @click="download()">Download svg</n-button>
+ </n-space>
+ </div>
+
+ <n-space vertical justify="start">
+ <img :src="base64" alt="Image" />
+ </n-space>
+</template>
+
+<script setup lang="ts">
+import TextareaCopyable from '@/components/TextareaCopyable.vue';
+import { useCopy } from '@/composable/copy';
+import { useDownloadFileFromBase64 } from '@/composable/downloadBase64.js';
+import { computed, ref } from 'vue';
+
+const width = ref(600);
+const height = ref(350);
+const fontSize = ref(26);
+const bgColor = ref('#cccccc');
+const fgColor = ref('#333333');
+const useExactSize = ref(true);
+const customText = ref('');
+const svgString = computed(() => {
+ const w = width.value;
+ const h = height.value;
+ const text = customText.value.length > 0 ? customText.value : `${w}x${h}`;
+ const size = useExactSize.value ? ` width="${w}" height="${h}"` : '';
+
+ return `
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${w} ${h}"${size}>
+ <rect width="${w}" height="${h}" fill="${bgColor.value}"></rect>
+ <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="monospace" font-size="${fontSize.value}px" fill="${fgColor.value}">${text}</text>
+</svg>
+ `.trim();
+});
+const base64 = computed(() => 'data:image/svg+xml;base64,' + window.btoa(svgString.value));
+
+const { copy: copySVG } = useCopy({ source: svgString });
+const { copy: copyBase64 } = useCopy({ source: base64 });
+const { download } = useDownloadFileFromBase64({ source: base64 });
+</script>
+
+<style lang="less" scoped>
+.n-input-number {
+ width: 100%;
+}
+</style>