2023-07-27 05:31:52 +00:00
|
|
|
<!--
|
2024-02-13 15:59:27 +00:00
|
|
|
SPDX-FileCopyrightText: syuilo and misskey-project
|
2023-07-27 05:31:52 +00:00
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
-->
|
|
|
|
|
2022-06-29 12:22:15 +00:00
|
|
|
<template>
|
2023-05-24 08:50:15 +00:00
|
|
|
<div ref="rootEl" :class="$style.root">
|
|
|
|
<canvas :id="idForCanvas" ref="canvasEl" style="display: block;" :width="width" height="300" @contextmenu.prevent="() => {}"></canvas>
|
|
|
|
<div :id="idForTags" ref="tagsEl" :class="$style.tags">
|
2022-06-29 12:22:15 +00:00
|
|
|
<ul>
|
|
|
|
<slot></slot>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2023-12-07 05:42:09 +00:00
|
|
|
import { onMounted, watch, onBeforeUnmount, ref, shallowRef } from 'vue';
|
2022-06-29 12:22:15 +00:00
|
|
|
import tinycolor from 'tinycolor2';
|
|
|
|
|
|
|
|
const loaded = !!window.TagCanvas;
|
|
|
|
const SAFE_FOR_HTML_ID = 'abcdefghijklmnopqrstuvwxyz';
|
|
|
|
const computedStyle = getComputedStyle(document.documentElement);
|
2023-07-25 10:46:52 +00:00
|
|
|
const idForCanvas = Array.from({ length: 16 }, () => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join('');
|
|
|
|
const idForTags = Array.from({ length: 16 }, () => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join('');
|
2023-12-07 05:42:09 +00:00
|
|
|
const available = ref(false);
|
|
|
|
const rootEl = shallowRef<HTMLElement | null>(null);
|
|
|
|
const canvasEl = shallowRef<HTMLCanvasElement | null>(null);
|
|
|
|
const tagsEl = shallowRef<HTMLElement | null>(null);
|
|
|
|
const width = ref(300);
|
2022-06-29 12:22:15 +00:00
|
|
|
|
2023-12-07 05:42:09 +00:00
|
|
|
watch(available, () => {
|
2022-07-20 11:00:35 +00:00
|
|
|
try {
|
|
|
|
window.TagCanvas.Start(idForCanvas, idForTags, {
|
|
|
|
textColour: '#ffffff',
|
|
|
|
outlineColour: tinycolor(computedStyle.getPropertyValue('--accent')).toHexString(),
|
|
|
|
outlineRadius: 10,
|
|
|
|
initial: [-0.030, -0.010],
|
|
|
|
frontSelect: true,
|
|
|
|
imageRadius: 8,
|
|
|
|
//dragControl: true,
|
|
|
|
dragThreshold: 3,
|
|
|
|
wheelZoom: false,
|
|
|
|
reverse: true,
|
|
|
|
depth: 0.5,
|
|
|
|
maxSpeed: 0.2,
|
|
|
|
minSpeed: 0.003,
|
|
|
|
stretchX: 0.8,
|
|
|
|
stretchY: 0.8,
|
|
|
|
});
|
2022-07-23 05:31:54 +00:00
|
|
|
} catch (err) {}
|
2022-06-29 12:22:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
onMounted(() => {
|
2024-01-30 10:53:53 +00:00
|
|
|
if (rootEl.value) width.value = rootEl.value.offsetWidth;
|
2022-06-30 01:13:27 +00:00
|
|
|
|
2022-06-29 12:22:15 +00:00
|
|
|
if (loaded) {
|
2023-12-07 05:42:09 +00:00
|
|
|
available.value = true;
|
2022-06-29 12:22:15 +00:00
|
|
|
} else {
|
|
|
|
document.head.appendChild(Object.assign(document.createElement('script'), {
|
|
|
|
async: true,
|
|
|
|
src: '/client-assets/tagcanvas.min.js',
|
2023-12-07 05:42:09 +00:00
|
|
|
})).addEventListener('load', () => available.value = true);
|
2022-06-29 12:22:15 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
2022-07-20 11:00:35 +00:00
|
|
|
if (window.TagCanvas) window.TagCanvas.Delete(idForCanvas);
|
2022-06-29 12:22:15 +00:00
|
|
|
});
|
2022-06-30 01:13:27 +00:00
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
update: () => {
|
|
|
|
window.TagCanvas.Update(idForCanvas);
|
|
|
|
},
|
|
|
|
});
|
2022-06-29 12:22:15 +00:00
|
|
|
</script>
|
|
|
|
|
2023-05-24 08:50:15 +00:00
|
|
|
<style lang="scss" module>
|
|
|
|
.root {
|
2022-06-29 12:22:15 +00:00
|
|
|
position: relative;
|
2022-07-13 12:41:06 +00:00
|
|
|
overflow: clip;
|
2022-06-29 12:22:15 +00:00
|
|
|
display: grid;
|
|
|
|
place-items: center;
|
2023-05-24 08:50:15 +00:00
|
|
|
}
|
2022-06-29 12:22:15 +00:00
|
|
|
|
2023-05-24 08:50:15 +00:00
|
|
|
.tags {
|
|
|
|
position: absolute;
|
|
|
|
top: 999px;
|
|
|
|
left: 999px;
|
2022-06-29 12:22:15 +00:00
|
|
|
}
|
|
|
|
</style>
|