123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- <template>
- <teleport to="body">
- <div v-if="store.sheetViewModal" class="dialog-container">
- <header class="tw-flex tw-place-content-between tw-items-center">
- <div class="tw-text-2xl ctw-text-base tw-ml-5 tw-my-2">原图</div>
- <div class="tw-flex tw-items-center tw-gap-2 tw-mx-8 tw-flex-grow">
- <span
- v-for="(u, index) in dataUrls"
- :key="index"
- class="image-index hover:tw-bg-gray-300"
- :class="checkedIndex === index && 'tw-bg-gray-300'"
- @click="checkedIndex = index"
- >{{ index + 1 }}</span
- >
- </div>
- <a-button shape="circle" @click="store.sheetViewModal = false">
- <template #icon><CloseOutlined /></template>
- </a-button>
- </header>
- <div>
- <div
- v-for="(url, index) in dataUrls"
- :key="index"
- style="display: none"
- :class="index === checkedIndex && 'show-image'"
- >
- <img :src="url" />
- </div>
- </div>
- </div>
- </teleport>
- </template>
- <script setup lang="ts">
- import { reactive, watch } from "vue";
- import { CloseOutlined } from "@ant-design/icons-vue";
- import { store } from "@/store/store";
- import { loadImage } from "@/utils/utils";
- import type { PictureSlice } from "@/types";
- const dataUrls: string[] = reactive([]);
- watch(
- () => store.sheetViewModal,
- async () => {
- if (!store.sheetViewModal) return;
- dataUrls.splice(0);
- const urls = store.currentTask?.sheetUrls ?? [];
- const images = [];
- for (const url of urls) {
- images.push(await loadImage(url));
- }
- const sheetConfig = store.setting.sheetConfig;
- for (let i = 0; i < images.length; i++) {
- if (sheetConfig.length === 0) {
- dataUrls.push(
- getDataUrlForSheetConfig(
- images[i],
- i % 2 === 0
- ? [
- // 通过-1来标记该用默认遮盖规则
- { i: -1, x: 0, y: 0, w: 0, h: 0 },
- ]
- : []
- )
- );
- } else {
- const scs = sheetConfig.filter((s) => s.i - 1 === i);
- dataUrls.push(getDataUrlForSheetConfig(images[i], scs));
- }
- }
- }
- );
- let checkedIndex = $ref(0);
- function getDataUrlForSheetConfig(
- image: HTMLImageElement,
- sliceConfigs: Array<PictureSlice>
- ) {
- const canvas = document.createElement("canvas");
- canvas.width = image.naturalWidth;
- canvas.height = image.naturalHeight;
- const ctx = canvas.getContext("2d");
- if (!ctx) {
- console.log('canvas.getContext("2d") error');
- return "null";
- }
- // drawImage 画图软件透明色
- ctx?.drawImage(image, 0, 0);
- ctx.fillStyle = "grey";
- for (const sc of sliceConfigs) {
- if (sc.i === -1) {
- ctx.fillRect(0, 0, image.naturalWidth / 2, image.naturalHeight / 3);
- } else if (sc.w === 0 && sc.h === 0) {
- ctx.fillRect(0, 0, image.naturalWidth, image.naturalHeight);
- } else {
- ctx.fillRect(sc.x, sc.y, sc.w, sc.h);
- }
- }
- const dataurl = canvas.toDataURL();
- return dataurl;
- }
- </script>
- <style scoped>
- .dialog-container {
- /* always top */
- z-index: 99999;
- position: absolute;
- background-color: var(--app-container-bg-color);
- top: 0;
- left: 0;
- width: 100vw;
- height: 100vh;
- overflow: auto;
- min-width: var(--app-min-width);
- }
- header {
- color: var(--app-main-text-color);
- border-bottom: 1px solid var(--app-main-bg-color);
- }
- .image-index {
- display: inline-block;
- border: 1px solid grey;
- width: 25px;
- text-align: center;
- border-radius: 5px;
- cursor: pointer;
- }
- .show-image {
- display: block !important;
- }
- </style>
|