Skip to content

Commit 331f956

Browse files
committed
feat: can paste SVG code
1 parent 540d411 commit 331f956

File tree

1 file changed

+59
-25
lines changed

1 file changed

+59
-25
lines changed

src/components/SvgTo3D.vue

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,6 @@ const inputRefs = ref<(unknown & { focus: () => void } | null)[]>([])
4646
4747
const svgCode = ref('')
4848
49-
watch(svgCode, (newCode) => {
50-
const isNewCodeEmpty = !newCode || newCode.trim() === ''
51-
isDefaultSvg.value = isNewCodeEmpty
52-
53-
if (isNewCodeEmpty || !isValidSvg(newCode)) {
54-
loadDefaultSvg()
55-
return
56-
}
57-
58-
mountSVG(newCode)
59-
})
60-
6149
function mountSVG(svgData: string, customShapes?: (shapes: ShapeWithColor[], index: number) => ShapeWithColor[]) {
6250
isDefaultSvg.value = false
6351
svgShapes.value = createShapesWithColor(svgData, {
@@ -174,6 +162,44 @@ function isValidSvg(code: string) {
174162
&& svgStart < svgEnd
175163
&& (lowerCode.includes('viewbox') || lowerCode.includes('width') || lowerCode.includes('height'))
176164
}
165+
166+
function handleInputSvgCode() {
167+
pasteSvg(svgCode.value)
168+
svgCode.value = ''
169+
}
170+
171+
function pasteSvg(paste: string | undefined) {
172+
if (paste && isValidSvg(paste)) {
173+
fileName.value = 'Pasted file'
174+
mountSVG(paste)
175+
return true
176+
}
177+
return false
178+
}
179+
180+
onMounted(() => {
181+
document.addEventListener('paste', (event) => {
182+
// 检查是否在输入框中粘贴
183+
const target = event.target as HTMLElement
184+
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')
185+
return
186+
187+
const paste = getClipboardData(event)?.getData('text')
188+
189+
if (pasteSvg(paste)) {
190+
event.preventDefault()
191+
}
192+
else {
193+
console.warn('not a svg')
194+
}
195+
})
196+
})
197+
198+
function getClipboardData(event: ClipboardEvent): DataTransfer | null {
199+
return (event.clipboardData || (window as any).clipboardData)
200+
}
201+
202+
const isLoaded = computed(() => svgShapes.value.length && !isDefaultSvg.value)
177203
</script>
178204

179205
<template>
@@ -213,31 +239,39 @@ function isValidSvg(code: string) {
213239
</div>
214240
<div flex="~ col gap-2">
215241
<FileDropZone
216-
v-if="!svgCode"
242+
v-if="!svgCode || isLoaded"
217243
v-model:filename="fileName"
218244
:accept="['image/svg+xml']"
219245
default-text="Click or drop SVG file"
220246
@file-selected="handleFileSelected"
221247
/>
222-
<div v-if="!svgCode && !fileName" flex="~ gap-2 items-center">
248+
<div v-if="!svgCode && !isLoaded" flex="~ gap-2 items-center">
223249
<hr flex-1>
224250
<p text-center op-80>
225251
OR
226252
</p>
227253
<hr flex-1>
228254
</div>
229-
<textarea
230-
v-if="!fileName"
231-
v-model="svgCode"
232-
name="svg-code"
233-
placeholder="Paste SVG code here"
234-
bg="black/10 dark:white/20 hover:black/20 dark:hover:white/30"
235-
p2
236-
border
237-
rounded
238-
/>
255+
<template v-if="!isLoaded">
256+
<textarea
257+
v-model="svgCode"
258+
name="svg-code"
259+
placeholder="Paste SVG code here"
260+
bg="black/10 dark:white/20 hover:black/20 dark:hover:white/30"
261+
p2
262+
border
263+
rounded
264+
/>
265+
<button
266+
v-if="svgCode && isValidSvg(svgCode)"
267+
class="text-xl p2 text-center rounded bg-blue flex-1 w-full block cursor-pointer"
268+
@click="handleInputSvgCode()"
269+
>
270+
Convert
271+
</button>
272+
</template>
239273
</div>
240-
<template v-if="svgShapes.length && !isDefaultSvg">
274+
<template v-if="isLoaded">
241275
<div flex="~ gap-2 items-center">
242276
<IconInput
243277
v-model:value="size"

0 commit comments

Comments
 (0)