diff --git a/components/content/RefseqDb.vue b/components/content/RefseqDb.vue
index df52203508334192b04f2dc5d4b9d94be15fcf87..da1cea371a9f7c0713775b46ae109a45ef43a5ee 100644
--- a/components/content/RefseqDb.vue
+++ b/components/content/RefseqDb.vue
@@ -5,6 +5,10 @@ import { useDisplay } from "vuetify";
import type { SortItem } from "@/components/ServerDbTable.vue"
import { ServerDbTable } from "#components"
import { useSerialize } from "@/composables/useSerialize";
+import { useRasterize } from "@/composables/useRasterize";
+import { useDownloadBlob } from '@/composables/useDownloadBlob';
+
+
import type { ComponentPublicInstance } from 'vue'
const sortBy: Ref<SortItem[]> = ref([{ key: 'type', order: "asc" }])
@@ -14,6 +18,8 @@ const scaleTransform: Ref<string[]> = ref([])
const { serialize } = useSerialize()
+const { rasterize } = useRasterize()
+const { download } = useDownloadBlob()
const facets = ref([
"replicon",
@@ -259,8 +265,19 @@ const systemsDistributionPlot = ref<ComponentPublicInstance | null>(null)
const taxonomicDistributionPlot = ref<ComponentPublicInstance | null>(null)
const heatmapPlot = ref<ComponentPublicInstance | null>(null)
function downloadSvg(component: ComponentPublicInstance | null, filename: string) {
- serialize(toValue(component), filename)
+ const blob = toValue(serialize(toValue(component)))
+ if (blob !== undefined) {
+ download(blob, filename)
+ }
}
+
+async function downloadPng(component: ComponentPublicInstance | null, filename: string) {
+ const blob = await rasterize(toValue(component), filename)?.then((blob) => {
+ download(blob, filename)
+ })
+
+}
+
</script>
<template>
@@ -289,9 +306,27 @@ function downloadSvg(component: ComponentPublicInstance | null, filename: string
<v-card variant="flat">
<v-toolbar density="compact" color="transparent">
<v-spacer></v-spacer>
- <v-btn variant="text" size="x-small"
- @click="downloadSvg(systemsDistributionPlot, 'systems-distribution.svg')">export
- to svg</v-btn>
+
+ <v-menu>
+ <template v-slot:activator="{ props }">
+ <v-btn color="primary" prepend-icon="md:download" v-bind="props">
+ export
+ </v-btn>
+ </template>
+ <v-list>
+ <v-list-item value="svg">
+ <v-list-item-title
+ @click="downloadSvg(systemsDistributionPlot, 'df-systems-distribution.svg')">to
+ svg</v-list-item-title>
+
+ </v-list-item>
+ <v-list-item value="png">
+ <v-list-item-title
+ @click="downloadPng(systemsDistributionPlot, 'df-systems-distribution.png')">to
+ png</v-list-item-title>
+ </v-list-item>
+ </v-list>
+ </v-menu>
</v-toolbar>
<PlotFigure ref="systemsDistributionPlot"
@@ -302,10 +337,26 @@ function downloadSvg(component: ComponentPublicInstance | null, filename: string
<v-card variant="flat">
<v-toolbar density="compact" color="transparent">
<v-spacer></v-spacer>
- <v-btn variant="text" size="x-small"
- @click="downloadSvg(taxonomicDistributionPlot, 'taxonomic-distribution.svg')">export
- to
- svg</v-btn>
+ <v-menu>
+ <template v-slot:activator="{ props }">
+ <v-btn color="primary" prepend-icon="md:download" v-bind="props">
+ export
+ </v-btn>
+ </template>
+ <v-list>
+ <v-list-item value="svg">
+ <v-list-item-title
+ @click="downloadSvg(taxonomicDistributionPlot, 'df-taxonomic-distribution.svg')">to
+ svg</v-list-item-title>
+
+ </v-list-item>
+ <v-list-item value="png">
+ <v-list-item-title
+ @click="downloadPng(taxonomicDistributionPlot, 'df-taxonomic-distribution.png')">to
+ png</v-list-item-title>
+ </v-list-item>
+ </v-list>
+ </v-menu>
</v-toolbar>
<PlotFigure ref="taxonomicDistributionPlot" defer
:options="unref(computedDistriTaxoOptions)"></PlotFigure>
@@ -333,15 +384,31 @@ function downloadSvg(component: ComponentPublicInstance | null, filename: string
label="Select taxonomic rank" hide-details="auto" class="mx-2"></v-select>
</v-toolbar>
- <v-card variant="flat">
+ <v-card v-if="toValue(binPlotDataOptions) !== null" variant="flat">
<v-toolbar density="compact" color="transparent">
<v-spacer></v-spacer>
- <v-btn variant="text" size="x-small"
- @click="downloadSvg(heatmapPlot, 'heatmap-systems-taxonomic.svg')">export to
- svg</v-btn>
+ <v-menu>
+ <template v-slot:activator="{ props }">
+ <v-btn color="primary" prepend-icon="md:download" v-bind="props">
+ export
+ </v-btn>
+ </template>
+ <v-list>
+ <v-list-item value="svg">
+ <v-list-item-title
+ @click="downloadSvg(heatmapPlot, 'df-heatmap-systems-taxonomy.svg')">to
+ svg</v-list-item-title>
+
+ </v-list-item>
+ <!-- <v-list-item value="png">
+ <v-list-item-title
+ @click="downloadPng(heatmapPlot, 'df-heatmap-systems-taxonomy.png')">to
+ png</v-list-item-title>
+ </v-list-item> -->
+ </v-list>
+ </v-menu>
</v-toolbar>
- <PlotFigure ref="heatmapPlot" v-if="toValue(binPlotDataOptions) !== null"
- :options="unref(binPlotDataOptions)" defer>
+ <PlotFigure ref="heatmapPlot" :options="unref(binPlotDataOptions)" defer>
</PlotFigure>
</v-card>
</v-card>
diff --git a/composables/useRasterize.ts b/composables/useRasterize.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8fa51ebb5b8c693c30bd491b13f4bc0ea58ac5df
--- /dev/null
+++ b/composables/useRasterize.ts
@@ -0,0 +1,40 @@
+import { useDownloadBlob } from './useDownloadBlob';
+import { useSerialize } from './useSerialize';
+const { serialize } = useSerialize()
+
+export function useRasterize() {
+
+ function rasterize(component: MaybeRef<ComponentPublicInstance | null>, filename: MaybeRef<string>) {
+ const toValueCompo = toValue(component)
+ if (toValueCompo !== null) {
+ let resolve, reject;
+ const promise: Promise<Blob> = new Promise((y, n) => (resolve = y, reject = n));
+ const image = new Image;
+ image.onerror = reject;
+
+ const svg = toValueCompo.$el.firstChild
+ console.log(svg)
+ image.onload = () => {
+ const rect = svg.getBoundingClientRect();
+ const canvas = document.createElement("canvas");
+ canvas.width = rect.width
+ canvas.height = rect.height
+ const ctx = canvas.getContext("2d")
+
+
+ if (ctx !== null) {
+ ctx.drawImage(image, 0, 0, rect.width, rect.height);
+ ctx.canvas.toBlob(resolve);
+ }
+ }
+ const blob = toValue(serialize(component))
+ if (blob !== undefined) {
+ image.src = URL.createObjectURL(blob);
+ }
+ return promise;
+ }
+
+ }
+ return { rasterize }
+
+}
\ No newline at end of file
diff --git a/composables/useSerialize.ts b/composables/useSerialize.ts
index b24ce7a0db1139429b8d2d4545bed9ed384d750a..0f0520e15d695b725185e7606893ea65cea59e51 100644
--- a/composables/useSerialize.ts
+++ b/composables/useSerialize.ts
@@ -1,19 +1,15 @@
-import { useDownloadBlob } from './useDownloadBlob';
-const { download } = useDownloadBlob()
export function useSerialize() {
const xmlns = ref("http://www.w3.org/2000/xmlns/");
const xlinkns = ref("http://www.w3.org/1999/xlink");
const svgns = ref("http://www.w3.org/2000/svg");
- const blob = ref()
+ const blob = ref<Blob>()
- function serialize(compo: MaybeRef<ComponentPublicInstance | null>, filename: MaybeRef<string>) {
- console.log(compo)
+ function serialize(compo: MaybeRef<ComponentPublicInstance | null>) {
const toValueCompo = toValue(compo)
if (toValueCompo !== null) {
const svg = toValueCompo.$el.firstChild
- console.log(svg)
const clonedSvg = svg.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(svg, NodeFilter.SHOW_ELEMENT);
@@ -29,7 +25,7 @@ export function useSerialize() {
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(clonedSvg);
blob.value = new Blob([string], { type: "image/svg+xml" });
- download(blob, filename)
+ return blob
}
}
return { serialize }