💄 材料支持分享

This commit is contained in:
目棃
2024-10-05 11:55:11 +08:00
parent cc121d6f9f
commit c66d04c398
4 changed files with 66 additions and 32 deletions

View File

@@ -19,18 +19,20 @@
</div> </div>
</div> </div>
</div> </div>
<TwoMaterial :data="curData" v-model="showOverlay"> <Suspense>
<template #left> <TwoMaterial :data="curData" v-model="showOverlay">
<div class="card-arrow left" @click="switchMaterial(false)"> <template #left>
<img src="../../assets/icons/arrow-right.svg" alt="right" /> <div class="card-arrow left" @click="switchMaterial(false)">
</div> <img src="../../assets/icons/arrow-right.svg" alt="right" />
</template> </div>
<template #right> </template>
<div class="card-arrow" @click="switchMaterial(true)"> <template #right>
<img src="../../assets/icons/arrow-right.svg" alt="right" /> <div class="card-arrow" @click="switchMaterial(true)">
</div> <img src="../../assets/icons/arrow-right.svg" alt="right" />
</template> </div>
</TwoMaterial> </template>
</TwoMaterial>
</Suspense>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from "vue"; import { ref } from "vue";

View File

@@ -3,9 +3,12 @@
<div v-if="props.data" class="twom-container"> <div v-if="props.data" class="twom-container">
<slot name="left"></slot> <slot name="left"></slot>
<div class="twom-box"> <div class="twom-box">
<div class="twom-share">
Material {{ props.data.id }} | Render By TeyvatGuide v{{ version }}
</div>
<div class="twom-top"> <div class="twom-top">
<img :src="`/icon/material/${props.data.id}.webp`" alt="icon" class="twom-left" /> <img :src="`/icon/material/${props.data.id}.webp`" alt="icon" class="twom-left" />
<div class="twom-name">{{ props.data.name }}</div> <div class="twom-name" @click="shareMaterial()">{{ props.data.name }}</div>
<div class="twom-type">{{ props.data.type }}</div> <div class="twom-type">{{ props.data.type }}</div>
</div> </div>
<div class="twom-bottom"> <div class="twom-bottom">
@@ -23,8 +26,10 @@
</TOverlay> </TOverlay>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getVersion } from "@tauri-apps/api/app";
import { computed } from "vue"; import { computed } from "vue";
import { generateShareImg } from "../../utils/TGShare.js";
import { parseHtmlText } from "../../utils/toolFunc.js"; import { parseHtmlText } from "../../utils/toolFunc.js";
import TOverlay from "../main/t-overlay.vue"; import TOverlay from "../main/t-overlay.vue";
@@ -41,18 +46,26 @@ type TwoMaterialEmits = (e: "update:modelValue", value: boolean) => void;
const props = defineProps<TwoMaterialProps>(); const props = defineProps<TwoMaterialProps>();
const emits = defineEmits<TwoMaterialEmits>(); const emits = defineEmits<TwoMaterialEmits>();
const visible = computed({ const visible = computed<boolean>({
get: () => props.modelValue, get: () => props.modelValue,
set: (val) => emits("update:modelValue", val), set: (val) => emits("update:modelValue", val),
}); });
const iconBg = computed(() => { const iconBg = computed<string>(() => {
if (!props.data) return "url('/icon/bg/0-BGC.webp')"; if (!props.data) return "url('/icon/bg/0-BGC.webp')";
return `url('/icon/bg/${props.data.star}-BGC.webp')`; return `url('/icon/bg/${props.data.star}-BGC.webp')`;
}); });
const version = await getVersion();
function onCancel() { function onCancel() {
visible.value = false; visible.value = false;
} }
async function shareMaterial(): Promise<void> {
const element = <HTMLElement>document.querySelector(".twom-box");
const fileName = `material_${props.data.id}`;
await generateShareImg(fileName, element, 1.2, true);
}
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.twom-container { .twom-container {
@@ -66,13 +79,27 @@ function onCancel() {
position: relative; position: relative;
display: flex; display: flex;
width: 800px; width: 800px;
max-height: 600px;
flex-direction: column; flex-direction: column;
padding: 10px; padding: 10px;
border-radius: 10px; border-radius: 10px;
background: var(--box-bg-1); background: var(--box-bg-1);
overflow-y: auto;
row-gap: 10px; row-gap: 10px;
} }
.twom-share {
position: absolute;
z-index: -1;
top: 0;
left: 0;
display: flex;
width: 100%;
align-items: center;
justify-content: center;
font-size: 12px;
}
.twom-top { .twom-top {
position: relative; position: relative;
display: flex; display: flex;
@@ -98,6 +125,7 @@ function onCancel() {
.twom-name { .twom-name {
color: var(--common-text-title); color: var(--common-text-title);
cursor: pointer;
font-family: var(--font-title); font-family: var(--font-title);
font-size: 30px; font-size: 30px;
} }
@@ -111,10 +139,7 @@ function onCancel() {
.twom-bottom { .twom-bottom {
display: flex; display: flex;
max-height: 400px;
flex-direction: column; flex-direction: column;
padding-right: 10px;
overflow-y: auto;
row-gap: 10px; row-gap: 10px;
} }

View File

@@ -54,18 +54,20 @@
<div class="twm-item-id">{{ item.id }}</div> <div class="twm-item-id">{{ item.id }}</div>
</div> </div>
</div> </div>
<TwoMaterial v-model="visible" :data="curMaterial"> <Suspense>
<template #left> <TwoMaterial v-model="visible" :data="curMaterial">
<div class="card-arrow left" @click="switchMaterial(false)"> <template #left>
<img src="../../assets/icons/arrow-right.svg" alt="right" /> <div class="card-arrow left" @click="switchMaterial(false)">
</div> <img src="../../assets/icons/arrow-right.svg" alt="right" />
</template> </div>
<template #right> </template>
<div class="card-arrow" @click="switchMaterial(true)"> <template #right>
<img src="../../assets/icons/arrow-right.svg" alt="right" /> <div class="card-arrow" @click="switchMaterial(true)">
</div> <img src="../../assets/icons/arrow-right.svg" alt="right" />
</template> </div>
</TwoMaterial> </template>
</TwoMaterial>
</Suspense>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";

View File

@@ -1,7 +1,7 @@
/** /**
* @file utils/TGShare.ts * @file utils/TGShare.ts
* @description 生成分享截图并保存到本地 * @description 生成分享截图并保存到本地
* @since Beta v0.5.5 * @since Beta v0.6.0
*/ */
import { path } from "@tauri-apps/api"; import { path } from "@tauri-apps/api";
@@ -86,18 +86,22 @@ function getShareImgBgColor(): string {
/** /**
* @description 生成分享截图 * @description 生成分享截图
* @since Beta v0.5.5 * @since Beta v0.6.0
* @param {string} fileName - 文件名 * @param {string} fileName - 文件名
* @param {HTMLElement} element - 元素 * @param {HTMLElement} element - 元素
* @param {number} scale - 缩放比例 * @param {number} scale - 缩放比例
* @param {boolean} scrollable - 是否可滚动,一般为上下滚动
* @returns {Promise<void>} 无返回值 * @returns {Promise<void>} 无返回值
*/ */
export async function generateShareImg( export async function generateShareImg(
fileName: string, fileName: string,
element: HTMLElement, element: HTMLElement,
scale: number = 1.2, scale: number = 1.2,
scrollable: boolean = false,
): Promise<void> { ): Promise<void> {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
const maxHeight = element.style.maxHeight;
if (scrollable) element.style.maxHeight = "100%";
const width = element.clientWidth + 30; const width = element.clientWidth + 30;
const height = element.clientHeight + 30; const height = element.clientHeight + 30;
canvas.width = width * scale; canvas.width = width * scale;
@@ -115,6 +119,7 @@ export async function generateShareImg(
dpi: 350, dpi: 350,
}; };
const canvasData = await html2canvas(element, opts); const canvasData = await html2canvas(element, opts);
if (scrollable) element.style.maxHeight = maxHeight;
const buffer = new Uint8Array( const buffer = new Uint8Array(
atob(canvasData.toDataURL("image/png").split(",")[1]) atob(canvasData.toDataURL("image/png").split(",")[1])
.split("") .split("")