diff --git a/src/App.vue b/src/App.vue index db530e7..0740659 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,14 +2,31 @@ import { ref } from 'vue'; import VueDraw from './components/VueDraw.vue' import type { Settings, Crop } from './types' +import { toCanvas } from './utils/toCanvas'; +import { toImgSrc } from './utils/toImgSrc'; + const settings = ref() +const crop = ref() +const canvasRef = ref() +const imgSrc = ref() +const vueDrawRef = ref() + function onCrop(crop: Crop | undefined) { console.log(crop) } + +async function save() { + imgSrc.value = await toImgSrc(vueDrawRef.value.svgRef, crop.value) + toCanvas(vueDrawRef.value.svgRef, canvasRef, crop.value) +} + \ No newline at end of file diff --git a/src/components/VueDraw.vue b/src/components/VueDraw.vue index 066efe8..1b188f7 100644 --- a/src/components/VueDraw.vue +++ b/src/components/VueDraw.vue @@ -8,6 +8,7 @@ import SvgShape from './SvgShape.vue'; const emit = defineEmits<{ (e: 'crop', crop: Crop | undefined): void }>() + const settings = defineModel("settings", { default: () => ({ tool: "line", @@ -23,6 +24,12 @@ const crop = defineModel("crop", { default: undefined }) const container = ref() const svgRef = ref() const activeShape = ref() + +defineExpose({ + svgRef, + container +}) + function updateActiveShape() { if (settings.value.tool === 'rectangle') { activeShape.value = { @@ -130,6 +137,18 @@ const arrowMarkers = computed(() => + + rect, + line { + stroke-linecap: round; + stroke-linejoin: round; + fill-opacity: 0; + } + .overlay { + opacity: 0.7; + fill: #020202; + } +
@@ -153,11 +172,6 @@ svg { z-index: 100; } -.overlay { - opacity: 0.7; - fill: #020202; -} - .toolbar { position: absolute; } diff --git a/src/utils/toCanvas.ts b/src/utils/toCanvas.ts new file mode 100644 index 0000000..bb10724 --- /dev/null +++ b/src/utils/toCanvas.ts @@ -0,0 +1,22 @@ +import type { Crop } from "@/types"; +import { unref, type MaybeRef } from "vue"; +import { toImgSrc } from "./toImgSrc"; + +// Inspired by https://jsfiddle.net/Wijmo5/h2L3gw88/ +export function toCanvas(svg: MaybeRef, canvas: MaybeRef, crop?: Crop) { + const image64 = toImgSrc(svg) + + // set it as the source of the img element + const img = new Image() + img.onload = () => { + // draw the image onto the canvas + const unreffedCanvas = unref(canvas) + unreffedCanvas.height = crop?.height ?? Number(unref(svg).getAttribute('height')) + unreffedCanvas.width = crop?.width ?? Number(unref(svg).getAttribute('width')) + unreffedCanvas.getContext('2d')?.drawImage(img, + crop?.x ?? 0, crop?.y ?? 0, unreffedCanvas.width, unreffedCanvas.height, + 0, 0, unreffedCanvas.width, unreffedCanvas.height + ); + } + img.src = image64; +} \ No newline at end of file diff --git a/src/utils/toImgSrc.ts b/src/utils/toImgSrc.ts new file mode 100644 index 0000000..c5f8ecf --- /dev/null +++ b/src/utils/toImgSrc.ts @@ -0,0 +1,14 @@ +import { unref, type MaybeRef } from "vue"; + +// Inspired by https://jsfiddle.net/Wijmo5/h2L3gw88/ +export function toImgSrc(svg: MaybeRef) { + // get svg data + const xml = new XMLSerializer().serializeToString(unref(svg)); + + // make it base64 + const svg64 = btoa(xml); + const b64Start = 'data:image/svg+xml;base64,'; + + // prepend a "header" + return b64Start + svg64; +} \ No newline at end of file