2024-02-23 14:32:33 +08:00
|
|
|
|
<template>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div ref="ExportModal">
|
2024-02-29 17:16:51 +08:00
|
|
|
|
<a-modal
|
2025-06-18 22:57:10 +08:00
|
|
|
|
class="modal_component Export generalModel"
|
|
|
|
|
|
v-model:visible="showUpgradePlan"
|
|
|
|
|
|
:footer="null"
|
|
|
|
|
|
:get-container="() => $refs.ExportModal"
|
|
|
|
|
|
width="78%"
|
|
|
|
|
|
:maskClosable="false"
|
|
|
|
|
|
:centered="true"
|
|
|
|
|
|
:closable="false"
|
|
|
|
|
|
:keyboard="false"
|
|
|
|
|
|
:destroyOnClose="true"
|
2024-02-29 17:16:51 +08:00
|
|
|
|
>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div class="generalModel_btn">
|
|
|
|
|
|
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="46"
|
|
|
|
|
|
height="46"
|
|
|
|
|
|
viewBox="0 0 46 46"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="23" cy="23" r="23" fill="white" fill-opacity="0.3" />
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="32.5063"
|
|
|
|
|
|
y="12"
|
|
|
|
|
|
width="3"
|
|
|
|
|
|
height="29"
|
|
|
|
|
|
rx="1.5"
|
|
|
|
|
|
transform="rotate(45 32.5063 12)"
|
|
|
|
|
|
fill="white"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="34.6274"
|
|
|
|
|
|
y="32.5059"
|
|
|
|
|
|
width="3"
|
|
|
|
|
|
height="29"
|
|
|
|
|
|
rx="1.5"
|
|
|
|
|
|
transform="rotate(135 34.6274 32.5059)"
|
|
|
|
|
|
fill="white"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
2024-02-29 17:16:51 +08:00
|
|
|
|
</div>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="UpgradePlan_content">
|
|
|
|
|
|
<div>{{ $t("exportModel.EditExport") }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div>
|
2024-02-23 14:32:33 +08:00
|
|
|
|
<canvas ref="exportCanvas"></canvas>
|
|
|
|
|
|
</div> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div class="exportCanvasBox">
|
|
|
|
|
|
<div class="exportCanvasBox_left">
|
|
|
|
|
|
<!-- <div class="exportCanvasBox_title">{{ $t('exportModel.CanvasSize') }}</div> -->
|
|
|
|
|
|
|
|
|
|
|
|
<!-- <label style="width: 10%">
|
2024-03-22 12:01:11 +08:00
|
|
|
|
<div>Width:</div>
|
2024-10-20 15:58:29 +08:00
|
|
|
|
<input type="number" @input="setMaxInput('width', 1000)" v-model="canvasWH.width"/>
|
2024-03-26 15:45:32 +08:00
|
|
|
|
</label> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<label style="width: 10%">
|
|
|
|
|
|
<div>{{ $t("exportModel.Height") }}:</div>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
@input="setMaxInput('height', 30000)"
|
|
|
|
|
|
v-model="canvasWH.height"
|
|
|
|
|
|
style="max-width: 50%"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
<div class="exportCanvasBox_title" @click.stop="setCloseNav('nav')">
|
|
|
|
|
|
{{ $t("exportModel.CanvasNav") }}
|
|
|
|
|
|
<div
|
|
|
|
|
|
:class="[
|
|
|
|
|
|
'icon',
|
|
|
|
|
|
'iconfont',
|
|
|
|
|
|
'icon-xiala',
|
|
|
|
|
|
closeNav.nav ? 'icon-rotate' : '',
|
|
|
|
|
|
]"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_imgbor exportCanvasBox_left_item"
|
|
|
|
|
|
:class="{ closeNav: closeNav.nav }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_allItem"
|
|
|
|
|
|
v-for="(item, key) in allBoardData"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'disposeMoodboard'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Entirety Moodboard
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'printboardFiles'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Printboard
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'moodboardFiles'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Moodboard
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'colorBoards'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Color
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'sketchboardFiles'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Sketch
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'likeDesignCollectionList'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Selected Design
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="item[0] && key == 'FinalizeImage'"
|
|
|
|
|
|
class="exportCanvasBox_intro"
|
|
|
|
|
|
>
|
|
|
|
|
|
Selected Product
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="key == 'colorBoards'"
|
|
|
|
|
|
class="exportCanvasBox_item_colorBor"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-for="colorItem in item"
|
|
|
|
|
|
class="exportCanvasBox_item_color"
|
|
|
|
|
|
:class="{ active: colorItem.upScaleChecked }"
|
|
|
|
|
|
draggable="true"
|
|
|
|
|
|
@dragstart="onDragstart(key, colorItem)"
|
|
|
|
|
|
@click.stop="isMoible ? setDragstart(key, colorItem) : ''"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="color_content"
|
|
|
|
|
|
v-if="colorItem.gradient"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
height: '10rem',
|
|
|
|
|
|
'background-image': colorItem?.gradient
|
|
|
|
|
|
? `linear-gradient(${
|
|
|
|
|
|
colorItem?.gradient.angle
|
|
|
|
|
|
}deg,${setGradient(colorItem?.gradient)}`
|
|
|
|
|
|
: 'none',
|
|
|
|
|
|
}"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
<div v-else>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_item_BGcolor"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
'background-color':
|
|
|
|
|
|
'rgb(' +
|
|
|
|
|
|
colorItem.rgbValue.r +
|
|
|
|
|
|
',' +
|
|
|
|
|
|
colorItem.rgbValue.g +
|
|
|
|
|
|
',' +
|
|
|
|
|
|
colorItem.rgbValue.b +
|
|
|
|
|
|
')',
|
|
|
|
|
|
}"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
<div>{{ colorItem.tcx }}</div>
|
|
|
|
|
|
<div>{{ colorItem.name }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="key != 'moodboardPosition' && key != 'colorBoards'"
|
|
|
|
|
|
class="exportCanvasBox_item"
|
|
|
|
|
|
v-for="imgItem in item"
|
|
|
|
|
|
:class="[
|
|
|
|
|
|
key == 'disposeMoodboard'
|
|
|
|
|
|
? 'exportCanvasBox_item_dispose'
|
|
|
|
|
|
: '',
|
|
|
|
|
|
imgItem?.upScaleChecked ? 'active' : '',
|
|
|
|
|
|
]"
|
|
|
|
|
|
draggable
|
|
|
|
|
|
@dragstart="onDragstart(key, imgItem)"
|
|
|
|
|
|
@click.stop="setDragstart(key, imgItem)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="exportCanvasBox_img">
|
|
|
|
|
|
<img
|
|
|
|
|
|
:src="
|
|
|
|
|
|
key == 'likeDesignCollectionList'
|
|
|
|
|
|
? imgItem?.designOutfitUrl
|
|
|
|
|
|
: imgItem?.imgUrl
|
|
|
|
|
|
"
|
|
|
|
|
|
alt=""
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_operation_bor_item exportCanvasBox_left_tool_item_column"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="label_item"
|
|
|
|
|
|
v-show="
|
|
|
|
|
|
operation != 'move' &&
|
|
|
|
|
|
operation != 'eraser' &&
|
|
|
|
|
|
operation != 'texture'
|
|
|
|
|
|
"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div>{{ $t("exportModel.Color") }}</div>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="color"
|
|
|
|
|
|
@input="setPencilColor"
|
|
|
|
|
|
v-model="canvasPencilColor"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div class="labelHover_show exportCanvasBox_imgbor">
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-for="item in colorHistoryList"
|
|
|
|
|
|
:style="{ background: item }"
|
|
|
|
|
|
@click="setColorHistory(item)"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="label_item" v-show="operation != 'move'">
|
|
|
|
|
|
<div>{{ $t("exportModel.Size") }}:</div>
|
|
|
|
|
|
<input
|
|
|
|
|
|
@change="setFontFamily"
|
|
|
|
|
|
type="range"
|
|
|
|
|
|
@input="setPencilWidth"
|
|
|
|
|
|
min="3"
|
|
|
|
|
|
max="50"
|
|
|
|
|
|
v-model="canvasPencilWidth[operation]"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="label_item" v-show="operation == 'pencil'">
|
|
|
|
|
|
<div>{{ $t("exportModel.Brushwork") }}:</div>
|
|
|
|
|
|
<a-select
|
|
|
|
|
|
ref="select"
|
|
|
|
|
|
class="label_select"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model:value="brushworkValue"
|
|
|
|
|
|
style="flex: 1"
|
|
|
|
|
|
@change="brushworkChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-select-option
|
|
|
|
|
|
class="label_select_item"
|
|
|
|
|
|
v-for="item in brushList"
|
|
|
|
|
|
:value="item.value"
|
|
|
|
|
|
>
|
|
|
|
|
|
<img :src="item.url" alt="" />
|
|
|
|
|
|
</a-select-option>
|
|
|
|
|
|
</a-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="label_item texture" v-show="operation == 'texture'">
|
|
|
|
|
|
<div>{{ $t("exportModel.Texture") }}:</div>
|
|
|
|
|
|
<a-select
|
|
|
|
|
|
ref="select"
|
|
|
|
|
|
class="label_select"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model:value="textureValue"
|
|
|
|
|
|
style="flex: 1"
|
|
|
|
|
|
@change="textureValueChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- v-model:value="brushwork" -->
|
|
|
|
|
|
<a-select-option
|
|
|
|
|
|
class="label_select_item"
|
|
|
|
|
|
v-for="item in textureList"
|
|
|
|
|
|
:value="item.value"
|
|
|
|
|
|
>
|
|
|
|
|
|
<img :src="item.url" alt="" />
|
|
|
|
|
|
</a-select-option>
|
|
|
|
|
|
</a-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="label_item"
|
|
|
|
|
|
v-show="
|
|
|
|
|
|
operation != 'pencil' &&
|
|
|
|
|
|
operation != 'eraser' &&
|
|
|
|
|
|
operation != 'move' &&
|
|
|
|
|
|
operation != 'text' &&
|
|
|
|
|
|
operation != 'texture' &&
|
|
|
|
|
|
operation != ''
|
|
|
|
|
|
"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div>{{ $t("exportModel.FillBack") }}:</div>
|
|
|
|
|
|
<div class="exportCanvasBox_left_tool_item leftAlign">
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-tuceng1"
|
|
|
|
|
|
@click="setOperationMode('fill')"
|
|
|
|
|
|
:class="{ active: operationMode == 'fill' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-tuceng"
|
|
|
|
|
|
@click="setOperationMode('border')"
|
|
|
|
|
|
:class="{ active: operationMode == 'border' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="label_item" v-show="operation === 'move'">
|
|
|
|
|
|
<div>{{ $t("exportModel.Layer") }}:</div>
|
|
|
|
|
|
<div class="exportCanvasBox_left_tool_item top">
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-shangyiceng"
|
|
|
|
|
|
@click="setLayerIndex('Front')"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-shangyiceng2"
|
|
|
|
|
|
@click="setLayerIndex('Forward')"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-xiayiceng"
|
|
|
|
|
|
@click="setLayerIndex('Backwards')"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-shangyiceng1"
|
|
|
|
|
|
@click="setLayerIndex('Back')"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div class="label_item" v-show="allSelectWidth > -1 && operation != 'move'">
|
2024-09-11 16:36:08 +08:00
|
|
|
|
<div >{{ $t('exportModel.Width') }}</div>
|
|
|
|
|
|
<input type="number" @input="setAllSelectWidth" v-model="allSelectWidth">
|
2024-09-27 16:31:33 +08:00
|
|
|
|
</div> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="label_item"
|
|
|
|
|
|
v-show="
|
|
|
|
|
|
(operation == '' || operation == 'text' || textDataShow) &&
|
|
|
|
|
|
operation != 'move'
|
|
|
|
|
|
"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div>Font Family</div>
|
|
|
|
|
|
<a-select
|
|
|
|
|
|
ref="select"
|
|
|
|
|
|
class="label_select"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model:value="fontFamily"
|
|
|
|
|
|
style="flex: 1"
|
|
|
|
|
|
@change="setFontFamily"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- v-model:value="brushwork" -->
|
|
|
|
|
|
<a-select-option
|
|
|
|
|
|
class="label_select_item"
|
|
|
|
|
|
v-for="item in textFontFamilyList"
|
|
|
|
|
|
:style="{ 'font-family': item.value }"
|
|
|
|
|
|
:value="item.value"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
|
</a-select-option>
|
|
|
|
|
|
</a-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <label v-show="operation != 'move' && operation != 'eraser' && operation != 'texture'">
|
2024-09-11 16:36:08 +08:00
|
|
|
|
<div >{{ $t('exportModel.Height') }}</div>
|
|
|
|
|
|
<input type="number" @input="setPencilColor" v-model="canvasPencilColor">
|
2024-09-27 16:31:33 +08:00
|
|
|
|
</div> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="shortcutKeys_box">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="gallery_btn white"
|
|
|
|
|
|
@click.stop="setCloseNav('shortcut')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ $t("exportModel.ShortcutKeys") }}
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-xiala"
|
|
|
|
|
|
:class="closeNav.shortcut ? 'icon-rotate-tool' : ''"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="shortcutKeys_list">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="shortcutKeys_list_item"
|
|
|
|
|
|
v-for="item in keysList"
|
|
|
|
|
|
:key="item.name"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="name">{{ item.name }}</div>
|
|
|
|
|
|
<div class="key">
|
|
|
|
|
|
<div v-if="!isWindow">{{ item.macKey }}</div>
|
|
|
|
|
|
<div v-else>{{ item.winDowKey }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- <div class="exportCanvasBox_title" @click.stop="setCloseNav('move')">
|
2024-09-11 16:36:08 +08:00
|
|
|
|
{{ $t('exportModel.More') }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
-->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div @click="toSvg">12312312312</div> -->
|
|
|
|
|
|
<div class="exportCanvasBox_center_box exportCanvasBox_left">
|
|
|
|
|
|
<div class="exportCanvasBox_left_tool exportCanvasBox_title">
|
|
|
|
|
|
<div class="exportCanvasBox_left_tool_item">
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-chehui"
|
|
|
|
|
|
@click="historyState('')"
|
|
|
|
|
|
:title="isWindow ? 'Ctrl+Z' : 'Command+Z'"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-fanchehui"
|
|
|
|
|
|
@click="historyState('reverse')"
|
|
|
|
|
|
:title="isWindow ? 'Ctrl+Shift+Z' : 'Command+Ctrl+Z'"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-move"
|
|
|
|
|
|
@click="setOperation('move')"
|
|
|
|
|
|
:class="{ active: operation == 'move' }"
|
|
|
|
|
|
:title="isWindow ? 'M' : 'M'"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-bianji"
|
|
|
|
|
|
@click="setOperation('pencil')"
|
|
|
|
|
|
:class="{ active: operation == 'pencil' }"
|
|
|
|
|
|
:title="isWindow ? 'B' : 'B'"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-xiangpi_huaban1"
|
|
|
|
|
|
@click="setOperation('eraser')"
|
|
|
|
|
|
:class="{ active: operation == 'eraser' }"
|
|
|
|
|
|
:title="isWindow ? 'E' : 'E'"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-caizhi"
|
|
|
|
|
|
@click="setOperation('texture')"
|
|
|
|
|
|
:class="{ active: operation == 'texture' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
|
|
|
|
|
|
<label
|
|
|
|
|
|
class="uploadImage"
|
|
|
|
|
|
:title="isWindow ? 'Ctrl+O' : 'Command+O'"
|
|
|
|
|
|
>
|
|
|
|
|
|
<i class="fi fi-br-upload"></i>
|
|
|
|
|
|
<input type="file" @change="uploadImage" accept="image/*" />
|
|
|
|
|
|
</label>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont"
|
|
|
|
|
|
@click="setOperation('text')"
|
|
|
|
|
|
:class="{ active: operation == 'text' }"
|
|
|
|
|
|
>T</i
|
|
|
|
|
|
>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-IC-yehua"
|
|
|
|
|
|
@click="setLiquefaction()"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<!-- <i class="fi fi-rr-zoom-in" @click="setOperation('zoomIn')" :class="{active:operation == 'zoomIn'}"></i>
|
2024-10-11 23:26:10 +08:00
|
|
|
|
<i class="fi fi-rr-zoom-out" @click="setOperation('zoomOut')" :class="{active:operation == 'zoomOut'}"></i> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-xiala"
|
|
|
|
|
|
:class="closeNav.tool ? 'icon-rotate-tool' : ''"
|
|
|
|
|
|
@click.stop="setCloseNav('tool')"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_left_tool exportCanvasBox_left_item"
|
|
|
|
|
|
:class="{ closeNav: closeNav.tool }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="exportCanvasBox_left_tool_item exportCanvasBox_left_tool_item_more"
|
|
|
|
|
|
>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-xian"
|
|
|
|
|
|
@click="setOperation('fold')"
|
|
|
|
|
|
:class="{ active: operation == 'fold' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-checkbox-full"
|
|
|
|
|
|
@click="setOperation('rect')"
|
|
|
|
|
|
:class="{ active: operation == 'rect' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<!-- <i class="icon iconfont icon-zhixian" @click="setOperation('line')" :class="{active:operation == 'line'}"></i> -->
|
|
|
|
|
|
<!-- <i class="icon iconfont icon-circle" @click="setOperation('circle')" :class="{active:operation == 'circle'}"></i> -->
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-sanjiaoxing"
|
|
|
|
|
|
@click="setOperation('triangle')"
|
|
|
|
|
|
:class="{ active: operation == 'triangle' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<i
|
|
|
|
|
|
class="icon iconfont icon-tx-fill-tuoyuanxing"
|
|
|
|
|
|
@click="setOperation('ellipse')"
|
|
|
|
|
|
:class="{ active: operation == 'ellipse' }"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="exportCanvasBox_center">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="editFrontBack_pencilbtn"
|
|
|
|
|
|
v-show="!isShowMark"
|
|
|
|
|
|
:style="pencilbtnStyle"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
<!-- <div>
|
2024-10-10 17:01:15 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div></div>
|
|
|
|
|
|
<span>16:9</span>
|
|
|
|
|
|
</div>
|
2024-10-11 23:26:10 +08:00
|
|
|
|
</div> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="exportCanvasBox_scroll">
|
|
|
|
|
|
<div></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="exportCanvasBox_bottom">
|
|
|
|
|
|
<div class="exportCanvasBox_left_btn Guide_1_38">
|
|
|
|
|
|
<div class="exportCanvasBox_left_credits" v-show="credits < 1">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span class="icon iconfont icon-zhuyi"></span
|
|
|
|
|
|
>{{ $t("exportModel.insufficient") }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div class="subitOkPreviewBtn" :class="{active:allBoardData.printboardFiles.length<=0}" :title="allBoardData.printboardFiles.length<=0?$t('exportModel.jsContent2'):''" @click="setHDExport">{{ $t('exportModel.HDExport') }}</div> -->
|
|
|
|
|
|
<div class="subitOkPreviewBtn" @click="setSubmit">
|
|
|
|
|
|
{{ $t("exportModel.Save") }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="subitOkPreviewBtn" @click="setShare">
|
|
|
|
|
|
{{ $t("exportModel.Share") }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="subitOkPreviewBtn" @click="setExport">
|
|
|
|
|
|
{{ $t("exportModel.Export") }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div class="exportCanvasBox_right">
|
2024-03-04 09:57:46 +08:00
|
|
|
|
<div class="exportCanvasBox_title">
|
|
|
|
|
|
High-definition Download
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="exportCanvasBox_right_definition">
|
|
|
|
|
|
<label>
|
2024-03-22 12:01:11 +08:00
|
|
|
|
<div>Scale:</div>
|
|
|
|
|
|
<input type="number" @input="setMaxInput('scale', 500)" v-model="scaleSR"/>
|
2024-03-04 09:57:46 +08:00
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
2024-03-26 15:45:32 +08:00
|
|
|
|
<div class="" @click="multiselect">all</div>
|
2024-03-08 16:51:24 +08:00
|
|
|
|
<div class="exportCanvasBox_right_credits" v-show="credits<1">
|
|
|
|
|
|
<div><span class="icon iconfont icon-zhuyi"></span>Your points balance is insufficient, if you need to use this feature, please click the top left corner to recharge</div>
|
|
|
|
|
|
</div>
|
2024-03-26 15:45:32 +08:00
|
|
|
|
</div> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<!-- <div @click="toSvg()">2312312312</div> -->
|
2024-04-25 12:58:10 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div class="mark_loading" v-show="isShowMark">
|
|
|
|
|
|
<a-spin size="large" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a-modal
|
|
|
|
|
|
v-model:visible="showSRExport"
|
|
|
|
|
|
class="modal_component SRExport generalModel"
|
|
|
|
|
|
width="48%"
|
|
|
|
|
|
:maskClosable="false"
|
|
|
|
|
|
:centered="true"
|
|
|
|
|
|
:closable="false"
|
|
|
|
|
|
:keyboard="false"
|
|
|
|
|
|
:footer="null"
|
|
|
|
|
|
:mask="false"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="generalModel_btn">
|
|
|
|
|
|
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
|
|
|
|
|
|
<i class="fi fi-rr-cross-small"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal_title_text">
|
|
|
|
|
|
<div class="modal_title_text_max">{{ $t("exportModel.SR") }}</div>
|
|
|
|
|
|
<div class="modal_title_text_intro">
|
|
|
|
|
|
{{
|
|
|
|
|
|
$t("exportModel.requiresCredits", {
|
|
|
|
|
|
data: allExportSR.filter((item) => item.checked).length * 5,
|
|
|
|
|
|
})
|
|
|
|
|
|
}}
|
|
|
|
|
|
</div>
|
2024-02-29 17:16:51 +08:00
|
|
|
|
</div>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div class="SRExport_operate">
|
|
|
|
|
|
<div class="SRExport_operate_box">
|
|
|
|
|
|
<div>{{ $t("exportModel.Scale") }}:</div>
|
|
|
|
|
|
<!-- <input type="number" @input="setMaxInput('scale', 500)" v-model="scaleSR"/> -->
|
|
|
|
|
|
<!-- <a-select ref="select" class="SRExport_operate_sclae" size="small" v-model:value="scaleSR"
|
2024-03-27 16:42:52 +08:00
|
|
|
|
style="flex: 1"
|
|
|
|
|
|
@change="setScaleSR"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-select-option class="label_select_item" v-for="item in scaleSRList" :value="item.value">
|
|
|
|
|
|
</a-select-option>
|
2024-03-27 17:49:25 +08:00
|
|
|
|
</a-select> -->
|
2025-06-18 22:57:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="SRExport_operate_item_sclae"
|
|
|
|
|
|
:class="{ active: scaleSR == 2 }"
|
|
|
|
|
|
@click="setScaleSR(2)"
|
|
|
|
|
|
>
|
|
|
|
|
|
2
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="SRExport_operate_item_sclae"
|
|
|
|
|
|
:class="{ active: scaleSR == 4 }"
|
|
|
|
|
|
@click="setScaleSR(4)"
|
|
|
|
|
|
>
|
|
|
|
|
|
4
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div class="SRExport_operate_item_sclae" :class="{active:scaleSR==8}" @click="setScaleSR(8)">8</div> -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
:class="['check_all_block', allChecked ? 'check_all' : '']"
|
|
|
|
|
|
@click="selectAllImg()"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="check_block"><div class="check_block_body"></div></div>
|
|
|
|
|
|
<div>all</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="SRExport_img">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="SRExport_img_item_box"
|
|
|
|
|
|
v-for="item in allExportSR"
|
|
|
|
|
|
@click="selectImg(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<input type="checkbox" v-model="item.checked" />
|
|
|
|
|
|
<img class="SRExport_img_item" :src="item.imgUrl" alt="" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="generalModelOperate_endBtn">
|
|
|
|
|
|
<div class="generalModelOperate_btn_cancel" @click="cancelSRExport">
|
|
|
|
|
|
{{ $t("exportModel.Cancel") }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="generalModelOperate_btn_ok"
|
|
|
|
|
|
:class="[
|
|
|
|
|
|
credits < allExportSR.filter((item) => item.checked).length * 5
|
|
|
|
|
|
? 'active'
|
|
|
|
|
|
: '',
|
|
|
|
|
|
]"
|
|
|
|
|
|
@click="setExportSR"
|
|
|
|
|
|
>
|
|
|
|
|
|
OK
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-modal>
|
|
|
|
|
|
<publish ref="publish" @clearPublish="clearPublish"></publish>
|
|
|
|
|
|
<liquefaction
|
|
|
|
|
|
ref="liquefaction"
|
|
|
|
|
|
@submitLiquefaction="submitLiquefaction"
|
|
|
|
|
|
@clearLiquefaction="clearLiquefaction"
|
|
|
|
|
|
></liquefaction>
|
2024-02-29 17:16:51 +08:00
|
|
|
|
</a-modal>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</div>
|
2024-02-23 14:32:33 +08:00
|
|
|
|
</template>
|
2024-02-27 15:15:38 +08:00
|
|
|
|
<script>
|
2025-06-18 22:57:10 +08:00
|
|
|
|
import {
|
|
|
|
|
|
defineComponent,
|
|
|
|
|
|
computed,
|
|
|
|
|
|
h,
|
|
|
|
|
|
ref,
|
|
|
|
|
|
nextTick,
|
|
|
|
|
|
inject,
|
|
|
|
|
|
reactive,
|
|
|
|
|
|
onMounted,
|
|
|
|
|
|
onBeforeUnmount,
|
2024-02-29 17:16:51 +08:00
|
|
|
|
} from "vue";
|
2024-02-23 14:32:33 +08:00
|
|
|
|
import { Https } from "@/tool/https";
|
2025-06-18 22:57:10 +08:00
|
|
|
|
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
|
2024-02-23 14:32:33 +08:00
|
|
|
|
import scaleImage from "@/component/HomePage/scaleImage.vue";
|
|
|
|
|
|
import ExportNewCoolection from "@/component/HomePage/ExportNewCoolection.vue";
|
2024-02-27 15:15:38 +08:00
|
|
|
|
import { useStore } from "vuex";
|
2024-02-29 17:16:51 +08:00
|
|
|
|
import JSZip, { forEach } from "jszip";
|
2024-03-21 10:49:21 +08:00
|
|
|
|
// import fabric from 'fabric';
|
2024-02-29 17:16:51 +08:00
|
|
|
|
import { message, Modal } from "ant-design-vue";
|
2025-06-18 22:57:10 +08:00
|
|
|
|
import domTurnImg from "@/tool/domTurnImg";
|
|
|
|
|
|
import { openGuide, driverObj__ } from "@/tool/guide";
|
|
|
|
|
|
import FileSaver from "file-saver";
|
|
|
|
|
|
import {
|
|
|
|
|
|
exportSele,
|
|
|
|
|
|
JSRectUpdata,
|
|
|
|
|
|
JSchangeType,
|
|
|
|
|
|
JScanvasMouseDown,
|
|
|
|
|
|
JScanvasMouseMove,
|
|
|
|
|
|
JScreateCheck,
|
|
|
|
|
|
JSSetTexture,
|
|
|
|
|
|
JSSetRemoveImage,
|
|
|
|
|
|
} from "@/tool/canvasDrawing";
|
2024-03-26 15:45:32 +08:00
|
|
|
|
import { useI18n } from "vue-i18n";
|
2025-06-18 22:57:10 +08:00
|
|
|
|
import {
|
|
|
|
|
|
isMoible,
|
|
|
|
|
|
calculateGradientCoordinate,
|
|
|
|
|
|
base64ToFile,
|
|
|
|
|
|
} from "@/tool/util";
|
2024-06-17 09:39:01 +08:00
|
|
|
|
import publish from "@/component/WorksPage/publish.vue";
|
2024-09-25 11:07:49 +08:00
|
|
|
|
import liquefaction from "@/component/modules/liquefaction.vue";
|
2024-10-08 17:03:22 +08:00
|
|
|
|
import { getMousePosition } from "@/tool/mdEvent";
|
2024-04-25 17:16:34 +08:00
|
|
|
|
|
2024-02-23 14:32:33 +08:00
|
|
|
|
export default defineComponent({
|
2025-06-18 22:57:10 +08:00
|
|
|
|
components: {
|
|
|
|
|
|
scaleImage,
|
|
|
|
|
|
ExportNewCoolection,
|
|
|
|
|
|
publish,
|
|
|
|
|
|
liquefaction,
|
|
|
|
|
|
},
|
|
|
|
|
|
props: ["msg", "sketchCatecoryList", "setTask"],
|
|
|
|
|
|
setup(props, { emit }) {
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
const store = useStore();
|
|
|
|
|
|
let driver__ = computed(() => {
|
|
|
|
|
|
return store.state.Guide.guide;
|
|
|
|
|
|
});
|
|
|
|
|
|
let isWindow = true;
|
|
|
|
|
|
let showUpgradePlan = ref(false);
|
|
|
|
|
|
let canvas = ref({});
|
|
|
|
|
|
// let canvasDom = ref()
|
|
|
|
|
|
let canvasWH = ref({
|
|
|
|
|
|
width: 400,
|
|
|
|
|
|
height: 0,
|
|
|
|
|
|
});
|
|
|
|
|
|
let pencilbtnStyle = ref({
|
|
|
|
|
|
background: "",
|
|
|
|
|
|
width: 0 + "px",
|
|
|
|
|
|
height: 0 + "px",
|
|
|
|
|
|
display: "none",
|
|
|
|
|
|
left: 0 + "px",
|
|
|
|
|
|
top: 0 + "px",
|
|
|
|
|
|
});
|
|
|
|
|
|
let publish = ref();
|
|
|
|
|
|
// canvasWH.value.width = [window.innerWidth/2.4]
|
|
|
|
|
|
// canvasWH.value.width = canvasWH.value.width.map(num => Math.round(num / 100) * 100)[0];
|
|
|
|
|
|
let credits = computed(() => {
|
|
|
|
|
|
return store.state.UserHabit.credits.value;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let allBoardData = computed(() => {
|
|
|
|
|
|
return store.state.UploadFilesModule.allBoardData;
|
|
|
|
|
|
});
|
|
|
|
|
|
let likeDesignCollectionList = computed(() => {
|
|
|
|
|
|
return store.state.HomeStoreModule.likeDesignCollectionList;
|
|
|
|
|
|
});
|
|
|
|
|
|
let isShowMark = ref(false);
|
|
|
|
|
|
// let allImage = Object.assign(allBoardData.value,{likeDesignCollectionList:likeDesignCollectionList.value})
|
|
|
|
|
|
let position = {
|
|
|
|
|
|
//设置每个图形位置的初始值
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
height: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
let canvasScale = 1; //canvas放大缩小倍率
|
|
|
|
|
|
let sketchGrouping = 6; //sketch分组
|
|
|
|
|
|
let likeDesign = 4; //整体图分组
|
|
|
|
|
|
let disposeMoodboardShow = true;
|
|
|
|
|
|
let canvasState = ref(); //存放canvas操作
|
|
|
|
|
|
let reverseCanvasState = ref([]); //存放canvas操作
|
|
|
|
|
|
let normalCanvasState = ref([]); //存放canvas操作
|
|
|
|
|
|
let isLoadCanvas = false; //撤回或者反撤回false为撤回
|
|
|
|
|
|
let userlikeGroupId = 0;
|
|
|
|
|
|
let imgWidth = {}; //这是设置画布等宽
|
|
|
|
|
|
let submitCanvasContent = null;
|
|
|
|
|
|
let contentKeyList = [];
|
|
|
|
|
|
let init = (productData) => {
|
|
|
|
|
|
userlikeGroupId = productData.userlikeGroupId;
|
|
|
|
|
|
allBoardData.value[productData.key] = productData.imgList;
|
|
|
|
|
|
contentKeyList = [
|
|
|
|
|
|
"disposeMoodboard",
|
|
|
|
|
|
"moodboardFiles",
|
|
|
|
|
|
"printboardFiles",
|
|
|
|
|
|
"colorBoards",
|
|
|
|
|
|
"sketchboardFiles",
|
|
|
|
|
|
"likeDesignCollectionList",
|
|
|
|
|
|
productData.key,
|
|
|
|
|
|
];
|
|
|
|
|
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
|
|
|
|
if (userAgent.indexOf("windows") !== -1) {
|
|
|
|
|
|
isWindow = true;
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
userAgent.indexOf("macintosh") !== -1 ||
|
|
|
|
|
|
userAgent.indexOf("mac os") !== -1
|
|
|
|
|
|
) {
|
|
|
|
|
|
isWindow = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
createCanvas();
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasData = async (oldExportCanvas) => {
|
|
|
|
|
|
let oldKey = "";
|
|
|
|
|
|
let margin = 20; //每个图形边距
|
|
|
|
|
|
let maxHeight = 0;
|
|
|
|
|
|
let sketchXy = { x: 0, y: 0 };
|
|
|
|
|
|
|
|
|
|
|
|
contentKeyList.forEach((item) => {
|
|
|
|
|
|
if (item !== "likeDesignCollectionList")
|
|
|
|
|
|
imgWidth[item] = setImageWidth(item);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// arr.forEach((item,index)=>{
|
|
|
|
|
|
if (oldExportCanvas) {
|
|
|
|
|
|
canvasWH.value.height = oldExportCanvas.canvasHeight;
|
|
|
|
|
|
canvas.setHeight(canvasWH.value.height);
|
|
|
|
|
|
canvas.loadFromJSON(oldExportCanvas, () => {});
|
|
|
|
|
|
isShowMark.value = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
canvasWH.value.height = 500;
|
|
|
|
|
|
canvas.setHeight(canvasWH.value.height);
|
|
|
|
|
|
isShowMark.value = false;
|
|
|
|
|
|
await nextTick(async () => {
|
|
|
|
|
|
for (const item of contentKeyList) {
|
|
|
|
|
|
for (const key in allBoardData.value) {
|
|
|
|
|
|
if (item == key) {
|
|
|
|
|
|
//循环渲染顺序
|
|
|
|
|
|
let sketchGroupingItem = [];
|
|
|
|
|
|
if (item == "moodboardFiles" && !disposeMoodboardShow) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (const [allItemIndex, allItem] of allBoardData.value[
|
|
|
|
|
|
key
|
|
|
|
|
|
].entries()) {
|
|
|
|
|
|
await new Promise(async (resolve, reject) => {
|
|
|
|
|
|
if (!allItem) {
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
maxHeight =
|
|
|
|
|
|
position.y + position.height > maxHeight
|
|
|
|
|
|
? position.y + position.height
|
|
|
|
|
|
: maxHeight;
|
|
|
|
|
|
if (key == "colorBoards") {
|
|
|
|
|
|
let rect = setGroup(allItem);
|
|
|
|
|
|
if (
|
|
|
|
|
|
position.x + rect.width > canvasWH.value.width ||
|
|
|
|
|
|
oldKey != key
|
|
|
|
|
|
) {
|
|
|
|
|
|
position.x = 0;
|
|
|
|
|
|
position.y = maxHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
let group = setCanvasColor(position.y, position.x, rect);
|
|
|
|
|
|
oldKey = key;
|
|
|
|
|
|
position.x += rect.width + margin;
|
|
|
|
|
|
position.height = group.height + margin;
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let itemCanvasImg = allItem.imgUrl;
|
|
|
|
|
|
if (key == "likeDesignCollectionList") {
|
|
|
|
|
|
itemCanvasImg = allItem.designOutfitUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
fabric.Image.fromURL(
|
|
|
|
|
|
itemCanvasImg,
|
|
|
|
|
|
(img) => {
|
|
|
|
|
|
if (item == "likeDesignCollectionList")
|
|
|
|
|
|
imgWidth[item] = setImageWidth(key, img);
|
|
|
|
|
|
let scaleWH = imgWidth[item] / img.width; //计算放到画布上缩小倍率
|
|
|
|
|
|
if (key == "sketchboardFiles") {
|
|
|
|
|
|
if (allItemIndex == 0) {
|
|
|
|
|
|
position.x = 0;
|
|
|
|
|
|
position.y = maxHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (
|
|
|
|
|
|
position.x + img.width * scaleWH >
|
|
|
|
|
|
canvasWH.value.width ||
|
|
|
|
|
|
oldKey != key
|
|
|
|
|
|
) {
|
|
|
|
|
|
position.x = 0;
|
|
|
|
|
|
position.y = maxHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
setCanvasImage(
|
|
|
|
|
|
img,
|
|
|
|
|
|
key,
|
|
|
|
|
|
position.x,
|
|
|
|
|
|
position.y,
|
|
|
|
|
|
allItem
|
|
|
|
|
|
); //设置图片
|
|
|
|
|
|
position.height = img.height * scaleWH + margin;
|
|
|
|
|
|
if (key == "sketchboardFiles") {
|
|
|
|
|
|
if (
|
|
|
|
|
|
sketchGroupingItem.length <
|
|
|
|
|
|
sketchGrouping + 1
|
|
|
|
|
|
) {
|
|
|
|
|
|
sketchGroupingItem.push(
|
|
|
|
|
|
JSON.parse(JSON.stringify(position))
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sketchGroupingItem.length > sketchGrouping) {
|
|
|
|
|
|
let sketchXyIndex = {
|
|
|
|
|
|
maxIndex: 0,
|
|
|
|
|
|
maxNum: 0,
|
|
|
|
|
|
minNum: 999999,
|
|
|
|
|
|
minIndex: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
sketchGroupingItem.forEach(
|
|
|
|
|
|
(sketchItem, sketchIndex) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
sketchItem.y + sketchItem.height <
|
|
|
|
|
|
sketchXyIndex.minNum
|
|
|
|
|
|
) {
|
|
|
|
|
|
sketchXyIndex.minNum =
|
|
|
|
|
|
sketchItem.y + sketchItem.height;
|
|
|
|
|
|
sketchXyIndex.minIndex = sketchIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
sketchItem.y + sketchItem.height >
|
|
|
|
|
|
sketchXyIndex.maxNum
|
|
|
|
|
|
) {
|
|
|
|
|
|
sketchXyIndex.maxNum =
|
|
|
|
|
|
sketchItem.y + sketchItem.height;
|
|
|
|
|
|
sketchXyIndex.maxIndex = sketchIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
sketchGroupingItem[sketchXyIndex.minIndex].y =
|
|
|
|
|
|
sketchXyIndex.minNum;
|
|
|
|
|
|
// sketchGroupingItem[sketchXyIndex.maxIndex].y = sketchXyIndex.maxNum
|
|
|
|
|
|
if (
|
|
|
|
|
|
allBoardData.value[key].length ==
|
|
|
|
|
|
allItemIndex + 1
|
|
|
|
|
|
) {
|
|
|
|
|
|
maxHeight = sketchXyIndex.maxNum;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
position =
|
|
|
|
|
|
sketchGroupingItem[sketchXyIndex.minIndex];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
key == "sketchboardFiles" &&
|
|
|
|
|
|
sketchGroupingItem.length > sketchGrouping
|
|
|
|
|
|
) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
position.x += img.width * scaleWH + margin;
|
|
|
|
|
|
}
|
|
|
|
|
|
img.lock_rotation = true;
|
|
|
|
|
|
oldKey = key;
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
canvas.add(img);
|
|
|
|
|
|
},
|
|
|
|
|
|
{ crossOrigin: "Anonymous" }
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (position.y + position.height > canvasWH.value.height) {
|
|
|
|
|
|
canvasWH.value.height = Math.floor(position.y + position.height);
|
|
|
|
|
|
canvas.setHeight(canvasWH.value.height);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
isShowMark.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
updateCanvasState(""); //加载完成后记录一下
|
|
|
|
|
|
};
|
|
|
|
|
|
let createCanvas = (oldExportCanvas) => {
|
|
|
|
|
|
showUpgradePlan.value = true;
|
|
|
|
|
|
clearTimeout(submitCanvasContent);
|
|
|
|
|
|
setCanvasKeyDown();
|
|
|
|
|
|
// document.addEventListener("keydown", setCanvasKeyDown);
|
|
|
|
|
|
// document.addEventListener("keyup", clearCanvasKeyDown);
|
|
|
|
|
|
normalCanvasState.value = [];
|
|
|
|
|
|
reverseCanvasState.value = [];
|
|
|
|
|
|
allBoardData.value.likeDesignCollectionList = likeDesignCollectionList;
|
|
|
|
|
|
nextTick().then(async () => {
|
|
|
|
|
|
let canvasBox = document.querySelector(
|
|
|
|
|
|
".Export .exportCanvasBox_center"
|
|
|
|
|
|
);
|
|
|
|
|
|
canvasWH.value.width = canvasBox.offsetWidth - 10;
|
|
|
|
|
|
let oldCanvasDom = canvasBox.querySelector(".canvas-container");
|
|
|
|
|
|
let oldCanvasDom1 = canvasBox.querySelector("canvas");
|
|
|
|
|
|
var canvasDom = document.createElement("canvas");
|
|
|
|
|
|
if (oldCanvasDom) oldCanvasDom.remove();
|
|
|
|
|
|
if (oldCanvasDom) loadingShow.value = false;
|
|
|
|
|
|
if (oldCanvasDom1) oldCanvasDom1.remove();
|
|
|
|
|
|
|
|
|
|
|
|
canvasBox.appendChild(canvasDom);
|
|
|
|
|
|
canvas = new fabric.Canvas(canvasDom, {
|
|
|
|
|
|
backgroundColor: "rgba(255, 255, 255)",
|
|
|
|
|
|
width: canvasWH.value.width,
|
|
|
|
|
|
height: canvasWH.value.height,
|
|
|
|
|
|
isDrawingMode: false, // 开启绘图模式
|
|
|
|
|
|
selectionFullyContained: true,
|
|
|
|
|
|
selectionKey: "ctrlKey",
|
|
|
|
|
|
includeDefaultValues: false, //尚未测试 精简导出JSON
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
canvasOnDrop(); //开启鼠标到画布事件
|
|
|
|
|
|
if (!fabric.Object.prototype.controls.deleteControl) {
|
|
|
|
|
|
//设置元素删除
|
|
|
|
|
|
JSSetRemoveImage(deleteObject);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
fabric.Object.prototype.controls.deleteControl.mouseUpHandler =
|
|
|
|
|
|
deleteObject;
|
|
|
|
|
|
}
|
|
|
|
|
|
// setRemoveImage()//设置元素删除
|
|
|
|
|
|
canvas.on("object:modified", () => {
|
|
|
|
|
|
updateCanvasState();
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
canvas.preserveObjectStacking = true;
|
|
|
|
|
|
//鼠标移动
|
|
|
|
|
|
canvas.on("mouse:move", (event) => setCanvasMove(event));
|
|
|
|
|
|
canvas.on("mouse:down", (event) => setCanvasDown(event));
|
|
|
|
|
|
canvas.on("mouse:up", (event) => setCanvasUp(event));
|
|
|
|
|
|
|
|
|
|
|
|
//双击
|
|
|
|
|
|
canvas.on("mouse:dblclick", (event) => {
|
|
|
|
|
|
if (operation.value == "fold") {
|
|
|
|
|
|
foldEnd("Enter");
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// canvas.on('path:created', (event)=>{updateCanvasState()});
|
|
|
|
|
|
// canvas.on("selection:created", (event)=>{setZIndex(event)});
|
|
|
|
|
|
// canvas.on('object:removed', function() {
|
|
|
|
|
|
// });
|
|
|
|
|
|
// canvas.on("object:added", (obj)=>{
|
|
|
|
|
|
// obj.target.cornerSize = 10
|
|
|
|
|
|
// obj.target.transparentCorners = false
|
|
|
|
|
|
// });
|
|
|
|
|
|
initAligningGuidelines(canvas, true);
|
|
|
|
|
|
JSchangeType(canvas, "init");
|
|
|
|
|
|
pencilbtnStyle.value.background = "#fff";
|
|
|
|
|
|
fabric.Object.prototype.cornerSize = 10;
|
|
|
|
|
|
fabric.Object.prototype.transparentCorners = false;
|
|
|
|
|
|
// setCanvasOperation()//设置监听添加修改画布元素,用来做撤回功能
|
2024-05-21 10:55:06 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
setOperation("move");
|
|
|
|
|
|
submitCanvasContent = setInterval(() => {
|
|
|
|
|
|
let data = setCanvasContent(true);
|
|
|
|
|
|
if (data.objects.length == 0) {
|
|
|
|
|
|
clearTimeout(submitCanvasContent);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
data.canvasHeight = canvasWH.value.height;
|
|
|
|
|
|
localStorage.setItem("canvasContent", JSON.stringify(data));
|
|
|
|
|
|
localStorage.setItem("userlikeGroupId", userlikeGroupId);
|
|
|
|
|
|
localStorage.setItem("currentTime", new Date().getTime());
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
if (driver__.value.driver) {
|
|
|
|
|
|
driverObj__.moveNext();
|
|
|
|
|
|
}
|
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
|
let oldExportCanvas;
|
|
|
|
|
|
let localCanvas = localStorage.getItem("canvasContent");
|
|
|
|
|
|
let localUserlikeGroupId = localStorage.getItem("userlikeGroupId");
|
|
|
|
|
|
let currentTime = localStorage.getItem("currentTime");
|
|
|
|
|
|
oldExportCanvas = await new Promise((resolve, reject) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
localUserlikeGroupId == userlikeGroupId &&
|
|
|
|
|
|
new Date().getTime() - currentTime < 21600000
|
|
|
|
|
|
) {
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: useI18.t("exportModel.jsContent8"),
|
|
|
|
|
|
okText: "Yes",
|
|
|
|
|
|
cancelText: "No",
|
|
|
|
|
|
mask: false,
|
|
|
|
|
|
centered: true,
|
|
|
|
|
|
onOk() {
|
|
|
|
|
|
localCanvas = localCanvas ? JSON.parse(localCanvas) : null;
|
|
|
|
|
|
resolve(localCanvas);
|
|
|
|
|
|
},
|
|
|
|
|
|
onCancel() {
|
|
|
|
|
|
resolve(null);
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
resolve(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!oldExportCanvas) {
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
userLikeGroupId: userlikeGroupId,
|
|
|
|
|
|
};
|
|
|
|
|
|
oldExportCanvas = await new Promise((resolve, reject) => {
|
|
|
|
|
|
Https.axiosPost(Https.httpUrls.exportSearch, data)
|
|
|
|
|
|
.then((rv) => {
|
|
|
|
|
|
resolve(rv);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((rv) => {
|
|
|
|
|
|
resolve(null);
|
|
|
|
|
|
});
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
setCanvasData(oldExportCanvas);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let deleteObject = () => {
|
|
|
|
|
|
// var target = [transform.target];
|
|
|
|
|
|
if (!canvas.getActiveObjects()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let target = canvas.getActiveObjects();
|
2024-03-22 12:01:11 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
target.forEach((item) => {
|
|
|
|
|
|
// var canvas = item.canvas;
|
|
|
|
|
|
// canvas.remove(item);
|
|
|
|
|
|
canvas.fxRemove(item, {
|
|
|
|
|
|
onComplete() {
|
|
|
|
|
|
canvas.discardActiveObject(); // 丢弃当前选中的对象
|
|
|
|
|
|
canvas.renderAll(); // 重新渲染 Canvas
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.FX_DURATION = 300;
|
|
|
|
|
|
});
|
|
|
|
|
|
// canvas.requestRenderAll();
|
|
|
|
|
|
// canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数,则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
|
|
|
|
|
|
// canvas.discardActiveObject(); // 丢弃当前选中的对象
|
|
|
|
|
|
// canvas.renderAll(); // 重新渲染 Canvas
|
|
|
|
|
|
updateCanvasState("remove");
|
|
|
|
|
|
};
|
2024-10-11 23:26:10 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let setImageWidth = (key, img) => {
|
|
|
|
|
|
let imgWidth = canvasWH.value.width; //这是设置画布等宽
|
|
|
|
|
|
if (
|
|
|
|
|
|
disposeMoodboardShow &&
|
|
|
|
|
|
key == "disposeMoodboard" &&
|
|
|
|
|
|
allBoardData.value[key].length != 0 &&
|
|
|
|
|
|
allBoardData.value[key][0] != null
|
|
|
|
|
|
) {
|
|
|
|
|
|
//如果是mood 需要判断用户是否点击layout
|
|
|
|
|
|
disposeMoodboardShow = false;
|
2024-09-03 16:39:06 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
imgWidth = canvasWH.value.width / 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key == "upImgFiles") {
|
|
|
|
|
|
imgWidth = canvasWH.value.width / 8;
|
|
|
|
|
|
// imgWidth = canvasWH.value.width / 4;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key == "printboardFiles") {
|
|
|
|
|
|
imgWidth = canvasWH.value.width / 14;
|
|
|
|
|
|
// imgWidth = canvasWH.value.width / 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
key == "sketchboardFiles" ||
|
|
|
|
|
|
key == "moodboardFiles" ||
|
|
|
|
|
|
key == "FinalizeImage"
|
|
|
|
|
|
) {
|
|
|
|
|
|
imgWidth =
|
|
|
|
|
|
(canvasWH.value.width - (sketchGrouping - 1) * 20) / sketchGrouping;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key == "likeDesignCollectionList") {
|
|
|
|
|
|
if (img) {
|
|
|
|
|
|
let imgObj = JSON.parse(JSON.stringify(img));
|
|
|
|
|
|
let height = imgObj.height;
|
|
|
|
|
|
imgObj.height = (canvasWH.value.width / 8) * 1.8;
|
|
|
|
|
|
let heightScale = imgObj.height / height;
|
|
|
|
|
|
imgWidth = imgObj.width * heightScale;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return imgWidth;
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasImage = (img, key, left, top, data) => {
|
|
|
|
|
|
// data
|
|
|
|
|
|
let imgId = 0;
|
|
|
|
|
|
let minioUrl = ""; //表示收藏或者generate
|
|
|
|
|
|
let imgUrl = data.imgUrl;
|
|
|
|
|
|
if (key == "likeDesignCollectionList") {
|
|
|
|
|
|
imgUrl = data.designOutfitUrl;
|
|
|
|
|
|
imgWidth[key] = setImageWidth(key, img);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key == "upImgFiles") imgWidth[key] = setImageWidth(key, img);
|
|
|
|
|
|
|
|
|
|
|
|
// let url = imgUrl.split('?')[0]
|
|
|
|
|
|
// var match = url.match(/^(?:https?:\/\/[^\/]+)\/(.*)/);
|
|
|
|
|
|
const { pathname } = new URL(imgUrl);
|
|
|
|
|
|
const result = pathname.slice(1);
|
|
|
|
|
|
minioUrl = result;
|
|
|
|
|
|
// let id =
|
|
|
|
|
|
let proportion = img.height / img.width; //计算图形宽高比例
|
|
|
|
|
|
// let imgWidth = setImageWidth(key)
|
|
|
|
|
|
let scaleWH = imgWidth[key] / img.width; //计算放到画布上缩小倍率
|
|
|
|
|
|
img.set({
|
|
|
|
|
|
// width: imgWidth[key]/img.width,
|
|
|
|
|
|
// height: canvasWH.value.height/img.height,
|
|
|
|
|
|
left,
|
|
|
|
|
|
top,
|
|
|
|
|
|
imgId,
|
|
|
|
|
|
minioUrl,
|
|
|
|
|
|
scaleX: imgWidth[key] / img.width,
|
|
|
|
|
|
scaleY: (img.width * proportion * scaleWH) / img.height,
|
|
|
|
|
|
// cornerSize: 10, // 选中时,角的大小为20
|
|
|
|
|
|
// transparentCorners: false, // 选中时,角是被填充了。true 空心;false 实心
|
|
|
|
|
|
lockRotation: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let setExportCanvas = async () => {
|
|
|
|
|
|
await calculateHeight();
|
|
|
|
|
|
canvas.setDimensions({ height: canvasWH.value.height });
|
|
|
|
|
|
canvas.renderAll();
|
|
|
|
|
|
return canvas.toDataURL({
|
|
|
|
|
|
format: "png", // 导出格式为 PNG
|
|
|
|
|
|
quality: 1, // 图片质量为 1(最高质量)
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let calculateHeight = () => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
var objects = canvas.getObjects();
|
|
|
|
|
|
var maxHeight = 0;
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: useI18.t("exportModel.jsContent9"),
|
|
|
|
|
|
okText: "Yes",
|
|
|
|
|
|
cancelText: "No",
|
|
|
|
|
|
mask: false,
|
|
|
|
|
|
centered: true,
|
|
|
|
|
|
onOk() {
|
|
|
|
|
|
objects.forEach(function (obj) {
|
|
|
|
|
|
var objBottom = obj.top + obj.height * obj.scaleY;
|
|
|
|
|
|
if (objBottom > maxHeight) {
|
|
|
|
|
|
maxHeight = objBottom;
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
});
|
2025-06-18 22:57:10 +08:00
|
|
|
|
canvasWH.value.height = Math.round(maxHeight) + 30;
|
2024-02-27 15:15:38 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
resolve(canvasWH.value.height);
|
|
|
|
|
|
},
|
|
|
|
|
|
onCancel() {
|
|
|
|
|
|
resolve(canvasWH.value.height);
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置导出
|
|
|
|
|
|
let setExport = async () => {
|
|
|
|
|
|
initAligningGuidelines(canvas, false);
|
|
|
|
|
|
var imageDataURL = await setExportCanvas();
|
|
|
|
|
|
let a = document.createElement("a");
|
|
|
|
|
|
let img = [];
|
|
|
|
|
|
let index = 0;
|
|
|
|
|
|
img.push({
|
|
|
|
|
|
imgUrl: imageDataURL,
|
|
|
|
|
|
name: "collection.png",
|
|
|
|
|
|
});
|
|
|
|
|
|
let num = 0;
|
|
|
|
|
|
for (let key in allBoardData.value) {
|
|
|
|
|
|
if (key !== "colorBoards" && key !== "moodTemplateId") {
|
|
|
|
|
|
if (!(allBoardData.value[key] instanceof Array)) continue;
|
|
|
|
|
|
for (let item of allBoardData.value[key]) {
|
|
|
|
|
|
if (
|
|
|
|
|
|
key == "disposeMoodboard" &&
|
|
|
|
|
|
allBoardData.value[key][0] == undefined
|
|
|
|
|
|
) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let nameTail = item?.imgUrl?.split(".").pop().split("?").shift();
|
|
|
|
|
|
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
imgUrl: item.imgUrl,
|
|
|
|
|
|
name: item?.resData?.name + index + "." + nameTail,
|
|
|
|
|
|
};
|
|
|
|
|
|
if (key == "likeDesignCollectionList") {
|
|
|
|
|
|
data.imgUrl = item.designOutfitUrl;
|
|
|
|
|
|
data.name =
|
|
|
|
|
|
"result" +
|
|
|
|
|
|
index +
|
|
|
|
|
|
"." +
|
|
|
|
|
|
data.imgUrl.split(".").pop().split("?").shift();
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
if (key == "FinalizeImage") {
|
|
|
|
|
|
data.imgUrl = item.url;
|
|
|
|
|
|
data.name =
|
|
|
|
|
|
"Finalize" +
|
|
|
|
|
|
index +
|
|
|
|
|
|
"." +
|
|
|
|
|
|
data.imgUrl.split(".").pop().split("?").shift();
|
|
|
|
|
|
}
|
|
|
|
|
|
img.push(data);
|
|
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
num++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
let dataList = [];
|
|
|
|
|
|
likeDesignCollectionList.value.forEach((item) => {
|
|
|
|
|
|
dataList.push(item.designItemId);
|
|
|
|
|
|
index++;
|
|
|
|
|
|
});
|
|
|
|
|
|
let mannequinList = [];
|
|
|
|
|
|
await Https.axiosPost(Https.httpUrls.designGetModel, dataList)
|
|
|
|
|
|
.then((rv) => {
|
|
|
|
|
|
mannequinList = rv;
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((rv) => {});
|
|
|
|
|
|
mannequinList.forEach((item) => {
|
|
|
|
|
|
let nameTail = item?.split(".").pop().split("?").shift();
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
imgUrl: item,
|
|
|
|
|
|
name: "mannequin" + index + "." + nameTail,
|
2024-02-29 17:16:51 +08:00
|
|
|
|
};
|
2025-06-18 22:57:10 +08:00
|
|
|
|
img.push(data);
|
|
|
|
|
|
index++;
|
|
|
|
|
|
});
|
|
|
|
|
|
downImg(img);
|
|
|
|
|
|
};
|
|
|
|
|
|
let getImgArrayBuffer = (url) => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
//通过请求获取文件blob格式
|
|
|
|
|
|
let xmlhttp = new XMLHttpRequest();
|
|
|
|
|
|
xmlhttp.open("GET", url, true);
|
|
|
|
|
|
xmlhttp.responseType = "blob";
|
|
|
|
|
|
xmlhttp.withCredentials = false;
|
|
|
|
|
|
xmlhttp.onload = function () {
|
|
|
|
|
|
if (this.status == 200) {
|
|
|
|
|
|
resolve(this.response);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(this.status);
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
};
|
2025-06-18 22:57:10 +08:00
|
|
|
|
xmlhttp.send();
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let downImg = (imagesParams) => {
|
|
|
|
|
|
let zip = new JSZip();
|
|
|
|
|
|
let cache = {};
|
|
|
|
|
|
let promises = [];
|
|
|
|
|
|
for (let item of imagesParams) {
|
|
|
|
|
|
const promise = getImgArrayBuffer(item.imgUrl).then((data) => {
|
|
|
|
|
|
// 下载文件, 并存成ArrayBuffer对象(blob)
|
|
|
|
|
|
zip.file(item.name, data, { binary: true }); // 逐个添加文件
|
|
|
|
|
|
cache[item.title] = data;
|
|
|
|
|
|
});
|
|
|
|
|
|
promises.push(promise);
|
|
|
|
|
|
}
|
|
|
|
|
|
Promise.all(promises)
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
function downloadBlob(blob, filename) {
|
|
|
|
|
|
const link = document.createElement("a");
|
|
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
|
link.href = url;
|
|
|
|
|
|
link.download = filename;
|
|
|
|
|
|
document.body.appendChild(link);
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
|
document.body.removeChild(link);
|
|
|
|
|
|
}
|
|
|
|
|
|
zip.generateAsync({ type: "blob" }).then((content) => {
|
|
|
|
|
|
// 生成二进制流
|
|
|
|
|
|
downloadBlob(content, "DesignFiles");
|
|
|
|
|
|
// FileSaver.saveAs(content, "DesignFiles"); // 利用file-saver保存文件 自定义文件名
|
|
|
|
|
|
isShowMark.value = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
setSubmit(); //导出的时候保存
|
|
|
|
|
|
initAligningGuidelines(canvas, true);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((res) => {
|
|
|
|
|
|
// message.warning(t('HomeView.jsContent3'));
|
|
|
|
|
|
isShowMark.value = false;
|
|
|
|
|
|
initAligningGuidelines(canvas, true);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
//关闭画布
|
|
|
|
|
|
let useI18 = useI18n();
|
|
|
|
|
|
let cancelDsign = () => {
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: useI18.t("exportModel.jsContent1"),
|
|
|
|
|
|
okText: "Yes",
|
|
|
|
|
|
cancelText: "No",
|
|
|
|
|
|
mask: false,
|
|
|
|
|
|
centered: true,
|
|
|
|
|
|
onOk() {
|
|
|
|
|
|
showUpgradePlan.value = false;
|
|
|
|
|
|
canvas.dispose();
|
|
|
|
|
|
position = {
|
|
|
|
|
|
//设置每个图形位置的初始值
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
height: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
canvasWH.value.height = 0;
|
|
|
|
|
|
operation.value = "move";
|
|
|
|
|
|
operation.value = "fill";
|
|
|
|
|
|
},
|
|
|
|
|
|
// onCancel(){
|
|
|
|
|
|
// _this.isShowMark.value = false
|
|
|
|
|
|
// resolve(false)
|
|
|
|
|
|
// }
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置画布宽高
|
|
|
|
|
|
let setMaxInput = (str, maxNum) => {
|
|
|
|
|
|
if (str == "width") {
|
|
|
|
|
|
// maxNum = window.innerWidth < 1100 ? 400 : maxNum;
|
|
|
|
|
|
maxNum = [window.innerWidth / 2.4];
|
|
|
|
|
|
maxNum = maxNum.map((num) => Math.round(num / 10) * 10)[0];
|
|
|
|
|
|
} else if (str == "height") {
|
|
|
|
|
|
if (position.y + position.height > maxNum) {
|
|
|
|
|
|
maxNum = Math.floor(position.y + position.height);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (str == "width" && canvasWH.value.width >= maxNum) {
|
|
|
|
|
|
canvasWH.value.width = maxNum;
|
|
|
|
|
|
} else if (str == "height" && canvasWH.value.height >= maxNum) {
|
|
|
|
|
|
canvasWH.value.height = maxNum;
|
|
|
|
|
|
} else if (str == "scale") {
|
|
|
|
|
|
scaleSR.value =
|
|
|
|
|
|
scaleSR.value < 1 ? 1 : scaleSR.value > 4 ? 4 : scaleSR.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
canvas.setHeight(canvasWH.value.height);
|
|
|
|
|
|
canvas.setWidth(canvasWH.value.width);
|
|
|
|
|
|
};
|
2024-05-20 14:45:43 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let closeNav = ref({
|
|
|
|
|
|
nav: false,
|
|
|
|
|
|
tool: false,
|
|
|
|
|
|
shortcut: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
let setCloseNav = (key) => {
|
|
|
|
|
|
closeNav.value[key] = !closeNav.value[key];
|
|
|
|
|
|
// for (const iterator in closeNav.value) {
|
|
|
|
|
|
// if(key != iterator){
|
|
|
|
|
|
// closeNav.value[iterator] = false
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
function multiselect() {
|
|
|
|
|
|
//获取整体宽高
|
|
|
|
|
|
canvas.discardActiveObject(); // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数,则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
|
|
|
|
|
|
const sel = new fabric.ActiveSelection(canvas.getObjects(), {
|
|
|
|
|
|
canvas,
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.setActiveObject(sel);
|
|
|
|
|
|
canvas.requestRenderAll();
|
|
|
|
|
|
const activeObject = canvas.getActiveObject(); // 获取当前选中的整体对象
|
|
|
|
|
|
if (activeObject && activeObject.type === "activeSelection") {
|
|
|
|
|
|
const totalWidth = activeObject.width * activeObject.scaleX;
|
|
|
|
|
|
const totalHeight = activeObject.height * activeObject.scaleY;
|
|
|
|
|
|
console.log("Total Width:", totalWidth);
|
|
|
|
|
|
console.log("Total Height:", totalHeight);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
let currentType = ref({
|
|
|
|
|
|
type: "",
|
|
|
|
|
|
data: "",
|
|
|
|
|
|
});
|
|
|
|
|
|
let onDragstart = (type, imgItem) => {
|
|
|
|
|
|
currentType.value.type = type;
|
|
|
|
|
|
currentType.value.data = imgItem;
|
|
|
|
|
|
};
|
|
|
|
|
|
let present = {};
|
|
|
|
|
|
let setDragstart = (type, imgItem) => {
|
|
|
|
|
|
currentType.value.type = type;
|
|
|
|
|
|
present.upScaleChecked = false;
|
|
|
|
|
|
present = {};
|
|
|
|
|
|
if (imgItem.upScaleChecked) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
imgItem.upScaleChecked = true;
|
|
|
|
|
|
present = imgItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
currentType.value.data = imgItem;
|
|
|
|
|
|
};
|
|
|
|
|
|
let canvasOnDrop = () => {
|
|
|
|
|
|
canvas.on("drop", (opt) => {
|
|
|
|
|
|
let offset = {
|
|
|
|
|
|
left: canvas.getSelectionElement().getBoundingClientRect().left,
|
|
|
|
|
|
top: canvas.getSelectionElement().getBoundingClientRect().top,
|
2024-02-29 17:16:51 +08:00
|
|
|
|
};
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let point = {
|
|
|
|
|
|
x: opt.e.x - offset.left,
|
|
|
|
|
|
y: opt.e.y - offset.top,
|
2024-02-29 17:16:51 +08:00
|
|
|
|
};
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let pointerVpt = canvas.restorePointerVpt(point);
|
|
|
|
|
|
switch (currentType.value.type) {
|
|
|
|
|
|
case "colorBoards":
|
|
|
|
|
|
let rect = setGroup(currentType.value.data);
|
|
|
|
|
|
setCanvasColor(pointerVpt.y, pointerVpt.x, rect);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "moodboardFiles":
|
|
|
|
|
|
createImage(pointerVpt.y, pointerVpt.x, currentType.value.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
createImage(pointerVpt.y, pointerVpt.x, currentType.value.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 创建完元素,把当前操作的元素类型设置回 null
|
|
|
|
|
|
currentType.value.type = null;
|
|
|
|
|
|
currentType.value.data = null;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let setGroup = (data) => {
|
|
|
|
|
|
let rect;
|
|
|
|
|
|
if (data.gradient) {
|
|
|
|
|
|
let colorStops = [];
|
|
|
|
|
|
data.gradient.gradientList.forEach((item) => {
|
|
|
|
|
|
let obj = {
|
|
|
|
|
|
offset: item.left.split("%")[0] / 100,
|
|
|
|
|
|
color: `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a})`,
|
|
|
|
|
|
};
|
|
|
|
|
|
colorStops.push(obj);
|
|
|
|
|
|
});
|
|
|
|
|
|
let { x0, y0, x1, y1 } = calculateGradientCoordinate(
|
|
|
|
|
|
100,
|
|
|
|
|
|
120,
|
|
|
|
|
|
data.gradient.angle
|
|
|
|
|
|
);
|
|
|
|
|
|
let linear = new fabric.Gradient({
|
|
|
|
|
|
type: "linear", // 线性渐变
|
|
|
|
|
|
// coords: { x1: 0, y1: 0, x2: 200, y2: 0 }, // 渐变方向
|
|
|
|
|
|
coords: { x1: x0, y1: y0, x2: x1, y2: y1 }, // 渐变方向
|
|
|
|
|
|
colorStops: colorStops,
|
|
|
|
|
|
});
|
|
|
|
|
|
var color = new fabric.Rect({
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
width: 110,
|
|
|
|
|
|
height: 130,
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
fill: linear, // 设置渐变填充
|
|
|
|
|
|
// fill: `rgb(${data.rgbValue.r},${data.rgbValue.g},${data.rgbValue.b})`,
|
|
|
|
|
|
});
|
|
|
|
|
|
var text = new fabric.Text("", {
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
fontSize: 0,
|
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
fill: "black",
|
|
|
|
|
|
});
|
|
|
|
|
|
let text1 = new fabric.Text("", {
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
width: 20,
|
|
|
|
|
|
fontSize: 0,
|
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
});
|
|
|
|
|
|
rect = { text, text1, color, width: 110 };
|
|
|
|
|
|
} else {
|
|
|
|
|
|
var text = new fabric.Text(data.tcx, {
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
top: 60,
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
fill: "black",
|
|
|
|
|
|
});
|
|
|
|
|
|
let text1 = new fabric.Text(data.name, {
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
top: 80,
|
|
|
|
|
|
width: 20,
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
});
|
|
|
|
|
|
let width = 110 > text1.width ? 110 : text1.width;
|
|
|
|
|
|
var color = new fabric.Rect({
|
|
|
|
|
|
width: width,
|
|
|
|
|
|
height: 60,
|
|
|
|
|
|
textAlign: "left",
|
|
|
|
|
|
fill: `rgb(${data.rgbValue.r},${data.rgbValue.g},${data.rgbValue.b})`,
|
|
|
|
|
|
});
|
|
|
|
|
|
rect = { text, text1, color, width };
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
return rect;
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasColor = (top, left, rect) => {
|
|
|
|
|
|
let group;
|
|
|
|
|
|
group = new fabric.Group([rect.color, rect.text, rect.text1], {
|
|
|
|
|
|
left,
|
|
|
|
|
|
top,
|
|
|
|
|
|
width: rect.width,
|
|
|
|
|
|
fill: "rgb(255,255,255)",
|
|
|
|
|
|
stroke: "#212121",
|
|
|
|
|
|
strokeWidth: 1,
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.add(group);
|
|
|
|
|
|
return group;
|
|
|
|
|
|
};
|
|
|
|
|
|
// 创建矩形
|
|
|
|
|
|
let createImage = async (top, left, key) => {
|
|
|
|
|
|
let itemCanvasImg = currentType.value.data.imgUrl;
|
|
|
|
|
|
let data = JSON.parse(JSON.stringify(currentType.value.data));
|
|
|
|
|
|
if (key == "likeDesignCollectionList") {
|
|
|
|
|
|
itemCanvasImg = currentType.value.data.designOutfitUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
|
|
fabric.Image.fromURL(
|
|
|
|
|
|
itemCanvasImg,
|
|
|
|
|
|
(img) => {
|
|
|
|
|
|
setCanvasImage(img, key, left, top, data); //设置图片
|
|
|
|
|
|
canvas.add(img);
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
{ crossOrigin: "Anonymous" }
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
updateCanvasState();
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置画布监听修改添加事件,用来做撤回功能
|
|
|
|
|
|
let updateCanvasState = (str) => {
|
|
|
|
|
|
const canvasAsJson = JSON.stringify(canvas.toJSON());
|
|
|
|
|
|
if (str == "loadingCompleted") {
|
|
|
|
|
|
// reverseCanvasState.value.push(canvasAsJson);
|
|
|
|
|
|
}
|
|
|
|
|
|
normalCanvasState.value.push(canvasAsJson);
|
|
|
|
|
|
if (isLoadCanvas) {
|
|
|
|
|
|
reverseCanvasState.value = [];
|
|
|
|
|
|
isLoadCanvas = false;
|
|
|
|
|
|
canvasState.value = canvasAsJson;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
//撤回
|
|
|
|
|
|
let historyState = (str) => {
|
|
|
|
|
|
if (str == "reverse" && reverseCanvasState.value.length > 0) {
|
|
|
|
|
|
//反撤回
|
|
|
|
|
|
let obj = reverseCanvasState.value.pop();
|
|
|
|
|
|
// canvasState.value = reverseCanvasState.value[reverseCanvasState.value.length-1]
|
|
|
|
|
|
canvasState.value = obj;
|
|
|
|
|
|
normalCanvasState.value.push(obj);
|
|
|
|
|
|
} else if (str == "" && normalCanvasState.value.length > 1) {
|
|
|
|
|
|
let obj = normalCanvasState.value.pop();
|
|
|
|
|
|
canvasState.value =
|
|
|
|
|
|
normalCanvasState.value[normalCanvasState.value.length - 1];
|
|
|
|
|
|
reverseCanvasState.value.push(obj);
|
|
|
|
|
|
isLoadCanvas = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
canvas.loadFromJSON(canvasState.value, () => {});
|
|
|
|
|
|
};
|
2024-03-08 11:19:33 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
//在画布进行画画
|
|
|
|
|
|
let operation = ref("move");
|
|
|
|
|
|
let operationMode = ref("fill");
|
|
|
|
|
|
let textureValue = ref(0); //材质信息
|
2024-06-17 09:39:01 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let textureValueChange = (value) => {
|
|
|
|
|
|
textureValue.value = value;
|
|
|
|
|
|
setTexture();
|
|
|
|
|
|
};
|
|
|
|
|
|
//铅笔颜色 大小
|
|
|
|
|
|
let brushworkValue = ref("PencilBrush");
|
|
|
|
|
|
let brushworkChange = (value) => {
|
|
|
|
|
|
brushworkValue.value = value;
|
|
|
|
|
|
setPencil();
|
|
|
|
|
|
};
|
2024-03-20 13:34:07 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// let brushwork = ref('')
|
|
|
|
|
|
// 监听键盘的 keydown 和 keyup 事件
|
|
|
|
|
|
let keyDown = [];
|
|
|
|
|
|
const keysList = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Painting"),
|
|
|
|
|
|
winDowKey: "B",
|
|
|
|
|
|
macKey: "B",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Eraser"),
|
|
|
|
|
|
winDowKey: "E",
|
|
|
|
|
|
macKey: "E",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Uncheck"),
|
|
|
|
|
|
winDowKey: "Ctrl + D",
|
|
|
|
|
|
macKey: "Command + D",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Revoke"),
|
|
|
|
|
|
winDowKey: "Ctrl + Z",
|
|
|
|
|
|
macKey: "Command + Z",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Retreat"),
|
|
|
|
|
|
winDowKey: "Ctrl + Shift + Z",
|
|
|
|
|
|
macKey: "Command + Ctrl + Z",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.ReduceBrushSize"),
|
|
|
|
|
|
winDowKey: "[",
|
|
|
|
|
|
macKey: "[",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.IncreaseBrushSize"),
|
|
|
|
|
|
winDowKey: "]",
|
|
|
|
|
|
macKey: "]",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.DrinkingStraw"),
|
|
|
|
|
|
winDowKey: "I",
|
|
|
|
|
|
macKey: "I",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Copy"),
|
|
|
|
|
|
winDowKey: "Ctrl + C",
|
|
|
|
|
|
macKey: "Command + C",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.Paste"),
|
|
|
|
|
|
winDowKey: "Ctrl + V",
|
|
|
|
|
|
macKey: "Command + V",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: useI18.t("exportModel.UploadOpenimage"),
|
|
|
|
|
|
winDowKey: "Ctrl + O",
|
|
|
|
|
|
macKey: "Command + O",
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
let canvasKeyDown = (event) => {
|
|
|
|
|
|
let keys = [
|
|
|
|
|
|
"Enter",
|
|
|
|
|
|
"Delete",
|
|
|
|
|
|
"ControlLeft",
|
|
|
|
|
|
"ShiftLeft",
|
|
|
|
|
|
"BracketLeft",
|
|
|
|
|
|
"BracketRight",
|
|
|
|
|
|
"MetaLeft",
|
|
|
|
|
|
];
|
|
|
|
|
|
var activeObject = canvas.getActiveObject();
|
|
|
|
|
|
let state =
|
|
|
|
|
|
activeObject &&
|
|
|
|
|
|
activeObject.type == "textbox" &&
|
|
|
|
|
|
activeObject.isEditing;
|
|
|
|
|
|
if (keys.indexOf(event.code) > -1) {
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (keyDown.indexOf(event.code) > -1 || state) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
keyDown.push(event.code);
|
|
|
|
|
|
// console.log(keyDown.indexOf('ControlLeft') > -1 , keyDown.indexOf('MetaLeft') > -1, event.code == 'KeyC')
|
|
|
|
|
|
if (event.code === "Enter" && operation.value == "fold") {
|
|
|
|
|
|
foldEnd("Enter");
|
|
|
|
|
|
} else if (event.key === "Delete") {
|
|
|
|
|
|
deleteObject();
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyZ" &&
|
|
|
|
|
|
keyDown.indexOf("ShiftLeft") > -1
|
|
|
|
|
|
) {
|
|
|
|
|
|
historyState("reverse");
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyZ"
|
|
|
|
|
|
) {
|
|
|
|
|
|
historyState("");
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyC"
|
|
|
|
|
|
) {
|
|
|
|
|
|
copy();
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyV"
|
|
|
|
|
|
) {
|
|
|
|
|
|
paste();
|
|
|
|
|
|
} else if (keyDown.indexOf("BracketLeft") > -1) {
|
|
|
|
|
|
let width = canvasPencilWidth.value[operation.value];
|
|
|
|
|
|
canvasPencilWidth.value[operation.value] =
|
|
|
|
|
|
width - 5 < 3 ? 3 : width - 5;
|
|
|
|
|
|
setPencilWidth();
|
|
|
|
|
|
} else if (keyDown.indexOf("BracketRight") > -1) {
|
|
|
|
|
|
let width = canvasPencilWidth.value[operation.value];
|
|
|
|
|
|
canvasPencilWidth.value[operation.value] =
|
|
|
|
|
|
width + 5 > 50 ? 50 : width + 5;
|
|
|
|
|
|
setPencilWidth();
|
|
|
|
|
|
} else if (keyDown.indexOf("KeyI") > -1) {
|
|
|
|
|
|
getColor(); //吸色
|
|
|
|
|
|
} else if (keyDown.indexOf("KeyM") > -1) {
|
|
|
|
|
|
setOperation("move");
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyD"
|
|
|
|
|
|
) {
|
|
|
|
|
|
canvas.discardActiveObject().renderAll();
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
(keyDown.indexOf("ControlLeft") > -1 ||
|
|
|
|
|
|
keyDown.indexOf("MetaLeft") > -1) &&
|
|
|
|
|
|
event.code == "KeyO"
|
|
|
|
|
|
) {
|
|
|
|
|
|
let input = document.querySelector(".uploadImage input");
|
|
|
|
|
|
input.click();
|
|
|
|
|
|
} else if (keyDown.indexOf("KeyB") > -1) {
|
|
|
|
|
|
// if(operation.value == 'pencil' || operation.value == 'texture'){
|
|
|
|
|
|
setOperation("pencil");
|
|
|
|
|
|
// }
|
|
|
|
|
|
} else if (keyDown.indexOf("KeyE") > -1) {
|
|
|
|
|
|
// if(operation.value == 'pencil' || operation.value == 'texture'){
|
|
|
|
|
|
setOperation("eraser");
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let getColor = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const dropper = new EyeDropper();
|
|
|
|
|
|
const result = await dropper.open();
|
|
|
|
|
|
let hex = result.sRGBHex.replace("#", "");
|
|
|
|
|
|
// 将十六进制颜色码拆分成红、绿、蓝三个部分
|
|
|
|
|
|
// const r = parseInt(hex.substring(0, 2), 16);
|
|
|
|
|
|
// const g = parseInt(hex.substring(2, 4), 16);
|
|
|
|
|
|
// const b = parseInt(hex.substring(4, 6), 16);
|
|
|
|
|
|
canvasPencilColor.value = result.sRGBHex;
|
|
|
|
|
|
setPencilColor();
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
message.info(this.t("ColorboardUpload.jsContent1"));
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let canvasKeyUp = (event) => {
|
|
|
|
|
|
let keys = [
|
|
|
|
|
|
"Enter",
|
|
|
|
|
|
"Delete",
|
|
|
|
|
|
"ControlLeft",
|
|
|
|
|
|
"ShiftLeft",
|
|
|
|
|
|
"BracketLeft",
|
|
|
|
|
|
"BracketRight",
|
|
|
|
|
|
"MetaLeft",
|
|
|
|
|
|
];
|
|
|
|
|
|
if (keys.indexOf(event.code) > -1) {
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
keyDown = keyDown.filter(function (item) {
|
|
|
|
|
|
return event.code !== item;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasKeyDown = (event) => {
|
|
|
|
|
|
// let e = event || window.event
|
|
|
|
|
|
// e.stopPropagation();
|
|
|
|
|
|
document.addEventListener("keydown", canvasKeyDown);
|
|
|
|
|
|
document.addEventListener("keyup", canvasKeyUp);
|
|
|
|
|
|
};
|
|
|
|
|
|
let clearCanvasKeyDown = (pointer) => {
|
|
|
|
|
|
// var pointer = canvas.getPointer(pointer);
|
|
|
|
|
|
if (!pointer?.target) {
|
|
|
|
|
|
document.removeEventListener("keydown", canvasKeyDown);
|
|
|
|
|
|
document.removeEventListener("keyup", canvasKeyUp);
|
|
|
|
|
|
}
|
|
|
|
|
|
// var x = pointer.x;
|
|
|
|
|
|
// var y = pointer.y;
|
2024-03-15 09:21:17 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// 检查是否鼠标离开了画布
|
|
|
|
|
|
// if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
|
|
|
|
|
|
// // 执行你的操作
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if(!x || !y){
|
|
|
|
|
|
// document.removeEventListener('keydown',canvasKeyDown);
|
|
|
|
|
|
// document.removeEventListener('keyup', canvasKeyUp);
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
let canvasPencilColor = ref("#000000"); //画笔颜色
|
|
|
|
|
|
// let canvasPencilWidth = ref(20)//画笔大小
|
|
|
|
|
|
let canvasPencilWidth = ref({});
|
|
|
|
|
|
let fontFamily = ref({});
|
|
|
|
|
|
let textFontFamilyList = ref([]);
|
|
|
|
|
|
let allSelectWidth = ref(-1); //多选或单选的宽度
|
|
|
|
|
|
let allSelect = ref([]); //多选或单选的宽度
|
|
|
|
|
|
let setOperation = (str) => {
|
|
|
|
|
|
operation.value = str;
|
|
|
|
|
|
//折线图的时候切换其他形状或者笔触需要把未完成的折线图删掉
|
|
|
|
|
|
canvas.discardActiveObject(); //取消所有选中边框
|
|
|
|
|
|
if (createPatterningIs) {
|
|
|
|
|
|
canvas.remove(currentPatterning);
|
|
|
|
|
|
}
|
|
|
|
|
|
removeSetText();
|
|
|
|
|
|
initAligningGuidelines(canvas, false);
|
|
|
|
|
|
canvas.remove(polyLineBtn);
|
|
|
|
|
|
if (str == "pencil") {
|
|
|
|
|
|
setPencil();
|
|
|
|
|
|
pencilbtnStyle.value.display = `block`;
|
|
|
|
|
|
} else if (str == "move") {
|
|
|
|
|
|
JSchangeType(canvas, "init");
|
|
|
|
|
|
initAligningGuidelines(canvas, true);
|
|
|
|
|
|
setMove();
|
|
|
|
|
|
pencilbtnStyle.value.display = `none`;
|
|
|
|
|
|
} else if (str == "texture") {
|
|
|
|
|
|
setTexture();
|
|
|
|
|
|
pencilbtnStyle.value.display = `block`;
|
|
|
|
|
|
} else if (str == "eraser") {
|
|
|
|
|
|
setEraser();
|
|
|
|
|
|
pencilbtnStyle.value.display = `block`;
|
|
|
|
|
|
} else if (str == "text") {
|
|
|
|
|
|
setMove();
|
|
|
|
|
|
setText();
|
|
|
|
|
|
JSchangeType(canvas, "init");
|
|
|
|
|
|
pencilbtnStyle.value.display = `none`;
|
|
|
|
|
|
} else if (str == "zoomIn" || str == "zoomOut") {
|
|
|
|
|
|
pencilbtnStyle.value.display = `none`;
|
|
|
|
|
|
canvas.forEachObject((obj) => (obj.selectable = false));
|
|
|
|
|
|
} else if (str) {
|
|
|
|
|
|
pencilbtnStyle.value.display = `none`;
|
|
|
|
|
|
canvas.forEachObject((obj) => (obj.selectable = false));
|
|
|
|
|
|
canvas.isDrawingMode = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
setPencilWidth();
|
|
|
|
|
|
};
|
|
|
|
|
|
let _setAllSelectTime = null;
|
|
|
|
|
|
let setAllSelectWidth = () => {
|
|
|
|
|
|
clearTimeout(_setAllSelectTime);
|
|
|
|
|
|
allSelect.value.forEach((item) => {
|
|
|
|
|
|
// item.width = allSelectWidth.value
|
|
|
|
|
|
item.scaleX = allSelectWidth.value / item.width;
|
|
|
|
|
|
item.scaleY = item.scaleX;
|
|
|
|
|
|
item.setCoords();
|
|
|
|
|
|
});
|
|
|
|
|
|
_setAllSelectTime = setTimeout(() => {
|
|
|
|
|
|
updateCanvasState(""); //加载完成后记录一下
|
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
};
|
|
|
|
|
|
let _clipboard = null; // 复制到的内容
|
|
|
|
|
|
let copy = () => {
|
|
|
|
|
|
//复制
|
|
|
|
|
|
var activeObject = canvas.getActiveObject();
|
|
|
|
|
|
if (!activeObject) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
activeObject.clone(function (cloned) {
|
|
|
|
|
|
_clipboard = cloned;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let paste = () => {
|
|
|
|
|
|
//粘贴
|
|
|
|
|
|
if (!_clipboard) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
_clipboard.clone((clonedObj) => {
|
|
|
|
|
|
canvas.discardActiveObject(); // 取消选择
|
2024-03-28 17:35:25 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// 设置新内容的坐标位置
|
|
|
|
|
|
clonedObj.set({
|
|
|
|
|
|
left: clonedObj.left + 10,
|
|
|
|
|
|
top: clonedObj.top + 10,
|
|
|
|
|
|
evented: true,
|
|
|
|
|
|
});
|
2024-05-21 16:00:27 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
if (clonedObj.type === "activeSelection") {
|
|
|
|
|
|
// 活动选择需要一个对画布的引用
|
|
|
|
|
|
clonedObj.canvas = canvas;
|
|
|
|
|
|
clonedObj.forEachObject(function (obj) {
|
|
|
|
|
|
canvas.add(obj);
|
|
|
|
|
|
});
|
2024-03-20 13:34:07 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
clonedObj.setCoords();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
canvas.add(clonedObj);
|
|
|
|
|
|
}
|
|
|
|
|
|
_clipboard.top += 10;
|
|
|
|
|
|
_clipboard.left += 10;
|
|
|
|
|
|
canvas.setActiveObject(clonedObj);
|
|
|
|
|
|
canvas.requestRenderAll();
|
|
|
|
|
|
});
|
|
|
|
|
|
updateCanvasState();
|
|
|
|
|
|
};
|
|
|
|
|
|
let textureList = ref([]);
|
|
|
|
|
|
for (let index = 0; index < 20; index++) {
|
|
|
|
|
|
textureList.value.push({
|
|
|
|
|
|
value: index,
|
|
|
|
|
|
url: `/image/texture/texture${index}.webp`,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
let setTexture = async () => {
|
|
|
|
|
|
canvas.isDrawingMode = true; //开启绘画模式
|
|
|
|
|
|
let img = await JSSetTexture(textureList.value[textureValue.value].url);
|
2024-03-20 13:34:07 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let patternBrush = new fabric.PatternBrush(canvas);
|
|
|
|
|
|
patternBrush.source = img;
|
|
|
|
|
|
patternBrush.width = canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20; // 设置画笔大小
|
|
|
|
|
|
canvas.freeDrawingBrush = patternBrush;
|
|
|
|
|
|
};
|
|
|
|
|
|
let setOperationMode = (str) => {
|
|
|
|
|
|
operationMode.value = str;
|
|
|
|
|
|
};
|
|
|
|
|
|
let uploadImage = (event) => {
|
|
|
|
|
|
let input = document.querySelector(".uploadImage input");
|
|
|
|
|
|
const file = event.target.files[0];
|
|
|
|
|
|
setOperation("move");
|
|
|
|
|
|
if (file) {
|
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
reader.onload = (e) => {
|
|
|
|
|
|
let file = base64ToFile(e.target.result, "upload");
|
|
|
|
|
|
let formData = new FormData();
|
|
|
|
|
|
formData.append("file", file);
|
|
|
|
|
|
let config = {
|
|
|
|
|
|
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" },
|
|
|
|
|
|
};
|
|
|
|
|
|
Https.axiosPost(
|
|
|
|
|
|
Https.httpUrls.canvasElementUpload,
|
|
|
|
|
|
formData,
|
|
|
|
|
|
config
|
|
|
|
|
|
).then((rv) => {
|
|
|
|
|
|
rv.imgUrl = rv.minioUrl;
|
|
|
|
|
|
fabric.Image.fromURL(
|
|
|
|
|
|
rv.minioUrl,
|
|
|
|
|
|
(img) => {
|
|
|
|
|
|
console.log(canvas.wrapperEl.parentNode.scrollTop);
|
|
|
|
|
|
setCanvasImage(
|
|
|
|
|
|
img,
|
|
|
|
|
|
"upImgFiles",
|
|
|
|
|
|
0,
|
|
|
|
|
|
canvas.wrapperEl.parentNode.scrollTop,
|
|
|
|
|
|
rv
|
|
|
|
|
|
);
|
|
|
|
|
|
canvas.add(img);
|
|
|
|
|
|
},
|
|
|
|
|
|
{ crossOrigin: "Anonymous" }
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
input.value = "";
|
|
|
|
|
|
};
|
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let setLayerIndex = (str) => {
|
|
|
|
|
|
//设置优先级
|
|
|
|
|
|
var activeObject = canvas.getActiveObject();
|
|
|
|
|
|
switch (str) {
|
|
|
|
|
|
case "Front":
|
|
|
|
|
|
canvas.bringToFront(activeObject); //顶层
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "Back":
|
|
|
|
|
|
canvas.sendToBack(activeObject); //底层
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "Forward":
|
|
|
|
|
|
canvas.bringForward(activeObject);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "Backwards":
|
|
|
|
|
|
canvas.sendBackwards(activeObject);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let hexToRgba = (hex, alpha) => {
|
|
|
|
|
|
const r = parseInt(hex.slice(1, 3), 16);
|
|
|
|
|
|
const g = parseInt(hex.slice(3, 5), 16);
|
|
|
|
|
|
const b = parseInt(hex.slice(5, 7), 16);
|
|
|
|
|
|
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
|
|
|
|
};
|
|
|
|
|
|
let brushList = ref([
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "PencilBrush",
|
|
|
|
|
|
url: "/image/brush/PencilBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "Marking",
|
|
|
|
|
|
url: "/image/brush/PencilBrush-2.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "InkBrush",
|
|
|
|
|
|
url: "/image/brush/InkBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "CrayonBrush",
|
|
|
|
|
|
url: "/image/brush/CrayonBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "RibbonBrush",
|
|
|
|
|
|
url: "/image/brush/RibbonBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "MarkerBrush",
|
|
|
|
|
|
url: "/image/brush/MarkerBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "WritingBrush",
|
|
|
|
|
|
url: "/image/brush/WritingBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "LongfurBrush",
|
|
|
|
|
|
url: "/image/brush/LongfurBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: "SpraypaintBrush",
|
|
|
|
|
|
url: "/image/brush/SpraypaintBrush.jpg",
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
let setPencil = () => {
|
|
|
|
|
|
let pencil;
|
|
|
|
|
|
canvas.isDrawingMode = true; //开启绘画模式
|
|
|
|
|
|
if (brushworkValue.value == "PencilBrush") {
|
|
|
|
|
|
pencil = new fabric.PencilBrush(canvas, {}); //普通笔
|
|
|
|
|
|
} else if (brushworkValue.value == "Marking") {
|
|
|
|
|
|
pencil = new fabric.PencilBrush(canvas); //记号笔
|
|
|
|
|
|
} else if (brushworkValue.value == "InkBrush") {
|
|
|
|
|
|
pencil = new fabric.InkBrush(canvas, {}); //油画笔
|
|
|
|
|
|
} else if (brushworkValue.value == "CrayonBrush") {
|
|
|
|
|
|
pencil = new fabric.CrayonBrush(canvas, {}); //蜡笔
|
|
|
|
|
|
} else if (brushworkValue.value == "RibbonBrush") {
|
|
|
|
|
|
pencil = new fabric.RibbonBrush(canvas, { width: 1 }); //色带
|
|
|
|
|
|
} else if (brushworkValue.value == "MarkerBrush") {
|
|
|
|
|
|
pencil = new fabric.MarkerBrush(canvas, {}); //书写笔
|
|
|
|
|
|
// pencil = new fabric.PenBrush(canvas,{}); //书写笔
|
|
|
|
|
|
} else if (brushworkValue.value == "WritingBrush") {
|
|
|
|
|
|
pencil = new fabric.WritingBrush(canvas, {}); //毛笔
|
|
|
|
|
|
} else if (brushworkValue.value == "LongfurBrush") {
|
|
|
|
|
|
pencil = new fabric.LongfurBrush(canvas, { width: 1 }); //色带
|
|
|
|
|
|
} else if (brushworkValue.value == "SpraypaintBrush") {
|
|
|
|
|
|
pencil = new fabric.SpraypaintBrush(canvas, {}); //长毛刷
|
|
|
|
|
|
}
|
2024-03-20 13:34:07 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
canvas.freeDrawingBrush = pencil;
|
|
|
|
|
|
canvas.freeDrawingBrush.width = canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20;
|
2024-03-20 13:34:07 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
if (
|
|
|
|
|
|
brushworkValue.value == "RibbonBrush" ||
|
|
|
|
|
|
brushworkValue.value == "LongfurBrush"
|
|
|
|
|
|
) {
|
|
|
|
|
|
canvas.freeDrawingBrush.width = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (brushworkValue.value == "Marking") {
|
|
|
|
|
|
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value, 0.5);
|
|
|
|
|
|
// }else if(brushworkValue.value == 'InkBrush'){
|
|
|
|
|
|
// canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value,.2);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value, 1);
|
|
|
|
|
|
}
|
2024-03-15 09:21:17 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
pencilbtnStyle.value.background = canvasPencilColor.value;
|
|
|
|
|
|
canvas.freeDrawingBrush.isEraser = false;
|
|
|
|
|
|
};
|
2024-03-15 09:21:17 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let setMove = () => {
|
|
|
|
|
|
canvas.isDrawingMode = false;
|
|
|
|
|
|
canvas.forEachObject((obj) => (obj.selectable = true));
|
|
|
|
|
|
};
|
|
|
|
|
|
let setEraser = () => {
|
|
|
|
|
|
canvas.isDrawingMode = true;
|
|
|
|
|
|
let eraser = new fabric.EraserBrush(canvas);
|
|
|
|
|
|
canvas.freeDrawingBrush = eraser;
|
|
|
|
|
|
pencilbtnStyle.value.background = "#fff";
|
|
|
|
|
|
canvas.requestRenderAll();
|
|
|
|
|
|
canvas.freeDrawingBrush.isEraser = true;
|
|
|
|
|
|
canvas.freeDrawingBrush.width = canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20;
|
|
|
|
|
|
};
|
|
|
|
|
|
let createText = {};
|
|
|
|
|
|
let setTextFun = (e) => {
|
|
|
|
|
|
if (operation.value != "text") {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var clickedObject = e.target;
|
|
|
|
|
|
if (clickedObject instanceof fabric.Textbox) {
|
|
|
|
|
|
createText = clickedObject;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
var pointer = canvas.getPointer(e.pointer);
|
|
|
|
|
|
var x = pointer.x;
|
|
|
|
|
|
var y = pointer.y;
|
|
|
|
|
|
createText = new fabric.Textbox("", {
|
|
|
|
|
|
left: x,
|
|
|
|
|
|
top: y,
|
|
|
|
|
|
width: 150,
|
|
|
|
|
|
fontSize: canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20,
|
|
|
|
|
|
fontFamily: fontFamily.value,
|
|
|
|
|
|
fill: canvasPencilColor.value,
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.add(createText);
|
|
|
|
|
|
createText.enterEditing();
|
|
|
|
|
|
canvas.setActiveObject(createText).renderAll();
|
|
|
|
|
|
operation.value = "";
|
|
|
|
|
|
removeSetText();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let setText = () => {
|
|
|
|
|
|
canvas.on("mouse:down", setTextFun);
|
|
|
|
|
|
// if(isMoible()){
|
|
|
|
|
|
// canvas.on('mouse:down',setTextFun)
|
|
|
|
|
|
// }else{
|
|
|
|
|
|
// canvas.on('mouse:dblclick',setTextFun)
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
let removeSetText = () => {
|
|
|
|
|
|
canvas.off("mouse:down", setTextFun);
|
|
|
|
|
|
// if(isMoible()){
|
|
|
|
|
|
// canvas.off('mouse:down',setTextFun)
|
|
|
|
|
|
// }else{
|
|
|
|
|
|
// canvas.off('mouse:dblclick',setTextFun)
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
// let setTextStyle = (x,y)=>{
|
|
|
|
|
|
// var group = new fabric.Group([rect.color, rect.text, rect.text1],{
|
|
|
|
|
|
// left,
|
|
|
|
|
|
// top,
|
|
|
|
|
|
// width: rect.width,
|
|
|
|
|
|
// fill: "rgb(255,255,255)",
|
|
|
|
|
|
// stroke: "#212121",
|
|
|
|
|
|
// strokeWidth: 1,
|
|
|
|
|
|
// });
|
|
|
|
|
|
// canvas.add(group);
|
|
|
|
|
|
// }
|
2024-04-03 17:39:44 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let setTimeOut = {
|
|
|
|
|
|
color: null,
|
|
|
|
|
|
width: null,
|
|
|
|
|
|
colorHistory: null,
|
|
|
|
|
|
}; //给切换颜色设置防抖
|
|
|
|
|
|
let colorHistoryList = ref(["rgb(0, 0, 0)"]);
|
|
|
|
|
|
let setColorHistory = (value) => {
|
|
|
|
|
|
canvasPencilColor.value = value;
|
|
|
|
|
|
pencilColor();
|
|
|
|
|
|
};
|
|
|
|
|
|
let pencilColor = () => {
|
|
|
|
|
|
if (createText.set) {
|
|
|
|
|
|
setFontFamily();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(canvasPencilColor.value);
|
|
|
|
|
|
// brushIndicator.fill = canvasPencilColor.value;
|
|
|
|
|
|
if (canvas.freeDrawingBrush.isEraser) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
pencilbtnStyle.value.background = canvasPencilColor.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (brushworkValue.value == "Marking") {
|
|
|
|
|
|
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value, 0.5);
|
|
|
|
|
|
} else if (brushworkValue.value == "InkBrush") {
|
|
|
|
|
|
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value, 0.2);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let setPencilColor = () => {
|
|
|
|
|
|
//切换颜色给铅笔设置颜色
|
|
|
|
|
|
clearTimeout(setTimeOut.color);
|
|
|
|
|
|
clearTimeout(setTimeOut.colorHistory);
|
|
|
|
|
|
setTimeOut.color = setTimeout(() => {
|
|
|
|
|
|
pencilColor();
|
|
|
|
|
|
}, 200);
|
|
|
|
|
|
setTimeOut.colorHistory = setTimeout(() => {
|
|
|
|
|
|
colorHistoryList.value.push(canvasPencilColor.value);
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
};
|
|
|
|
|
|
let setPencilWidth = () => {
|
|
|
|
|
|
//切换颜色给铅笔设置颜色
|
|
|
|
|
|
clearTimeout(setTimeOut.width);
|
|
|
|
|
|
canvasPencilWidth.value[operation.value] = Number(
|
|
|
|
|
|
canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20
|
|
|
|
|
|
);
|
|
|
|
|
|
setTimeOut.width = setTimeout(() => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
brushworkValue.value == "LongfurBrush" ||
|
|
|
|
|
|
brushworkValue.value == "RibbonBrush"
|
|
|
|
|
|
) {
|
|
|
|
|
|
canvas.freeDrawingBrush.width = 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
canvas.freeDrawingBrush.width =
|
|
|
|
|
|
canvasPencilWidth.value[operation.value];
|
|
|
|
|
|
}
|
|
|
|
|
|
pencilbtnStyle.value.height =
|
|
|
|
|
|
canvasPencilWidth.value[operation.value] + "px";
|
|
|
|
|
|
pencilbtnStyle.value.width =
|
|
|
|
|
|
canvasPencilWidth.value[operation.value] + "px";
|
|
|
|
|
|
// setPencil()
|
|
|
|
|
|
}, 300);
|
|
|
|
|
|
};
|
|
|
|
|
|
let downPoint = null; //鼠标按下位置
|
|
|
|
|
|
let upPoint = null; //鼠标抬起位置
|
|
|
|
|
|
let currentPatterning = null; //临时图形
|
|
|
|
|
|
let polyLineBtn = null;
|
|
|
|
|
|
let createPatterningIs = false;
|
|
|
|
|
|
let clearPatterning = () => {
|
|
|
|
|
|
if (createPatterningIs) {
|
|
|
|
|
|
canvas.remove(currentPatterning);
|
|
|
|
|
|
}
|
|
|
|
|
|
currentPatterning = null;
|
|
|
|
|
|
canvas.remove(polyLineBtn);
|
|
|
|
|
|
updateCanvasState();
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置再画布上移动
|
|
|
|
|
|
let setCanvasMove = (event) => {
|
|
|
|
|
|
var pointer = canvas.getPointer(event.e);
|
|
|
|
|
|
if (canvas.isDrawingMode) {
|
|
|
|
|
|
canvas.setCursor("none");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (createPatterningIs) {
|
|
|
|
|
|
JScanvasMouseMove(
|
|
|
|
|
|
operation.value,
|
|
|
|
|
|
event,
|
|
|
|
|
|
currentPatterning,
|
|
|
|
|
|
downPoint,
|
|
|
|
|
|
keyDown
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
let canvasBox = document.querySelector(".Export .canvas-container");
|
|
|
|
|
|
const rect = canvasBox.getBoundingClientRect();
|
|
|
|
|
|
const parentRect = canvasBox.parentElement.getBoundingClientRect();
|
|
|
|
|
|
let parentX = rect.left - parentRect.left;
|
|
|
|
|
|
let parentY = rect.top - parentRect.top;
|
|
|
|
|
|
pencilbtnStyle.value.left = parentX + pointer.x + "px";
|
|
|
|
|
|
pencilbtnStyle.value.top =
|
|
|
|
|
|
parentY + canvasBox.parentElement.scrollTop + pointer.y + "px";
|
|
|
|
|
|
canvas.requestRenderAll();
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasZoom = (opt) => {
|
|
|
|
|
|
console.log(123);
|
2024-05-21 10:55:06 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let zoom = canvas.getZoom(); // 获取画布当前缩放值
|
|
|
|
|
|
let num = -100;
|
|
|
|
|
|
if (operation.value == "zoomOut") num = 100;
|
2024-10-11 23:26:10 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
zoom *= 0.999 ** num;
|
|
|
|
|
|
if (zoom > 20) zoom = 20;
|
|
|
|
|
|
if (zoom < 0.01) zoom = 0.01;
|
2024-03-26 15:45:32 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// console.log(zoom);
|
|
|
|
|
|
canvas.zoomToPoint(
|
|
|
|
|
|
{
|
|
|
|
|
|
// 关键点
|
|
|
|
|
|
x: opt.e.offsetX,
|
|
|
|
|
|
y: opt.e.offsetY,
|
|
|
|
|
|
},
|
|
|
|
|
|
zoom
|
|
|
|
|
|
);
|
|
|
|
|
|
opt.e.preventDefault();
|
|
|
|
|
|
opt.e.stopPropagation();
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置再画布上按下
|
|
|
|
|
|
let setCanvasDown = (event) => {
|
|
|
|
|
|
//设置移动端按下添加元素
|
|
|
|
|
|
if (operation.value == "zoomIn" || operation.value == "zoomOut") {
|
|
|
|
|
|
setCanvasZoom(event);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isMoible && present.upScaleChecked) {
|
|
|
|
|
|
present.upScaleChecked = false;
|
|
|
|
|
|
present = {};
|
|
|
|
|
|
let pointerVpt = canvas.restorePointerVpt(event.pointer);
|
|
|
|
|
|
switch (currentType.value.type) {
|
|
|
|
|
|
case "colorBoards":
|
|
|
|
|
|
let rect = setGroup(currentType.value.data);
|
|
|
|
|
|
setCanvasColor(pointerVpt.y, pointerVpt.x, rect);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "moodboardFiles":
|
|
|
|
|
|
createImage(pointerVpt.y, pointerVpt.x, currentType.value.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
createImage(pointerVpt.y, pointerVpt.x, currentType.value.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 创建完元素,把当前操作的元素类型设置回 null
|
|
|
|
|
|
currentType.value.type = null;
|
|
|
|
|
|
currentType.value.data = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
downPoint = event.absolutePointer;
|
|
|
|
|
|
let arr = ["rect", "line", "circle", "triangle", "ellipse", "fold"];
|
|
|
|
|
|
if (arr.indexOf(operation.value) > -1) {
|
|
|
|
|
|
JSchangeType(canvas, operation.value);
|
|
|
|
|
|
createPatterningIs = true;
|
|
|
|
|
|
if (currentPatterning && operation.value == "fold") {
|
|
|
|
|
|
canvas.skipTargetFind = false;
|
|
|
|
|
|
currentPatterning.points.push({
|
|
|
|
|
|
x: downPoint.x,
|
|
|
|
|
|
y: downPoint.y,
|
|
|
|
|
|
});
|
|
|
|
|
|
// currentPatterning = JScanvasMouseDown(operation.value,event,canvasPencilWidth.value,currentPatterning)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentPatterning = JScanvasMouseDown(
|
|
|
|
|
|
operation.value,
|
|
|
|
|
|
event,
|
|
|
|
|
|
canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20,
|
|
|
|
|
|
currentPatterning
|
|
|
|
|
|
);
|
|
|
|
|
|
canvas.add(currentPatterning);
|
|
|
|
|
|
canvas.bringToFront(currentPatterning); //设置优先级最高
|
|
|
|
|
|
if (operation.value == "fold") {
|
|
|
|
|
|
polyLineBtn = JScreateCheck(event);
|
|
|
|
|
|
polyLineBtn.on("mousedown", foldEnd);
|
|
|
|
|
|
canvas.add(polyLineBtn);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
var clickedObject = event.target;
|
|
|
|
|
|
if (
|
|
|
|
|
|
clickedObject instanceof fabric.Textbox &&
|
|
|
|
|
|
operation.value != "text"
|
|
|
|
|
|
) {
|
|
|
|
|
|
textDataShow.value = true;
|
|
|
|
|
|
createText = clickedObject;
|
|
|
|
|
|
setTextData(clickedObject);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
textDataShow.value = false;
|
|
|
|
|
|
createText = {};
|
|
|
|
|
|
}
|
|
|
|
|
|
createPatterningIs = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let foldEnd = (key) => {
|
|
|
|
|
|
canvas.skipTargetFind = true;
|
|
|
|
|
|
let points = currentPatterning.points;
|
|
|
|
|
|
if (key == "Enter") {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
points.pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
points.pop();
|
|
|
|
|
|
canvas.remove(currentPatterning);
|
|
|
|
|
|
let polyline = new fabric.Polyline(points, {
|
|
|
|
|
|
fill:
|
|
|
|
|
|
operationMode.value == "fill"
|
|
|
|
|
|
? canvasPencilColor.value
|
|
|
|
|
|
: "transparent",
|
|
|
|
|
|
stroke: canvasPencilColor.value,
|
|
|
|
|
|
strokeWidth: canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20,
|
|
|
|
|
|
selection: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.add(polyline);
|
|
|
|
|
|
// currentPatterning.set({stroke: canvasPencilColor.value})
|
|
|
|
|
|
createPatterningIs = false;
|
|
|
|
|
|
clearPatterning(); //临时图形置为空并且添加撤回对象里面
|
|
|
|
|
|
setOperation("move");
|
|
|
|
|
|
};
|
|
|
|
|
|
//设置再画布上抬起
|
|
|
|
|
|
let setCanvasUp = (event) => {
|
|
|
|
|
|
upPoint = event.absolutePointer;
|
|
|
|
|
|
if (canvas.isDrawingMode) {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
// pencilbtnStyle.value.display = `none`
|
|
|
|
|
|
updateCanvasState();
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// event.target && (event.target.bringToFront())//设置优先级
|
|
|
|
|
|
}
|
|
|
|
|
|
var selectedObjects = canvas.getActiveObjects(); //获取多选选中的内容
|
|
|
|
|
|
if (selectedObjects.length >= 1) {
|
|
|
|
|
|
allSelect.value = selectedObjects;
|
|
|
|
|
|
// allSelectWidth.value = 0
|
|
|
|
|
|
allSelectWidth.value = (
|
|
|
|
|
|
selectedObjects[0].width * selectedObjects[0].scaleX
|
|
|
|
|
|
).toFixed(0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
allSelectWidth.value = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (createPatterningIs) {
|
|
|
|
|
|
switch (operation.value) {
|
|
|
|
|
|
case "line":
|
|
|
|
|
|
currentPatterning.set({ stroke: canvasPencilColor.value });
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "fold":
|
|
|
|
|
|
// currentPatterning.set({stroke: canvasPencilColor.value})
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (operationMode.value == "fill") {
|
|
|
|
|
|
currentPatterning.set({ fill: canvasPencilColor.value });
|
|
|
|
|
|
} else if (operationMode.value == "border") {
|
|
|
|
|
|
currentPatterning.set({
|
|
|
|
|
|
fill: "transparent",
|
|
|
|
|
|
stroke: canvasPencilColor.value,
|
|
|
|
|
|
strokeWidth: canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (JSON.stringify(downPoint) == JSON.stringify(upPoint)) {
|
|
|
|
|
|
canvas.remove(currentPatterning);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (operation.value == "fold") {
|
|
|
|
|
|
canvas.forEachObject((obj) => (obj.selectable = false));
|
|
|
|
|
|
canvas.bringToFront(polyLineBtn); //设置优先级最高
|
|
|
|
|
|
} else if (operation.value) {
|
|
|
|
|
|
createPatterningIs = false;
|
|
|
|
|
|
clearPatterning(); //临时图形置为空并且添加撤回对象里面
|
|
|
|
|
|
canvas.renderAll();
|
|
|
|
|
|
setOperation("move");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let setHDExport = async () => {
|
|
|
|
|
|
//获取选中内容的位置信息
|
|
|
|
|
|
// if(allBoardData.value.printboardFiles.length <= 0){
|
|
|
|
|
|
// message.info('Your print is empty')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
if (allBoardData.value.printboardFiles.length <= 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (credits.value < 30) {
|
|
|
|
|
|
message.info(useI18.t("exportModel.jsContent3"));
|
|
|
|
|
|
// return
|
|
|
|
|
|
}
|
|
|
|
|
|
showSRExport.value = true;
|
|
|
|
|
|
let arr = [];
|
|
|
|
|
|
if (allBoardData.value.printboardFiles) {
|
|
|
|
|
|
allBoardData.value.printboardFiles.forEach((item) => {
|
|
|
|
|
|
arr.push({
|
|
|
|
|
|
imgUrl: item.imgUrl,
|
|
|
|
|
|
checked: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
allExportSR.value = arr;
|
|
|
|
|
|
allChecked.value = false;
|
2024-03-26 15:45:32 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
//多选导出转高清暂时不用
|
2024-04-03 17:39:44 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// let {url,imageType} = await exportSele(canvas,'jpeg')
|
|
|
|
|
|
// if(!imageType){
|
|
|
|
|
|
// message.info('Please select the region of SR')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
// let img = new Image
|
|
|
|
|
|
// img.src = url
|
|
|
|
|
|
// let imgStyle = {
|
|
|
|
|
|
// 'width': '80%',
|
|
|
|
|
|
// 'max-height': '30rem',
|
|
|
|
|
|
// 'object-fit': 'contain',
|
|
|
|
|
|
// 'position': 'relative',
|
|
|
|
|
|
// 'left': '50%',
|
|
|
|
|
|
// 'transform': 'translateX(-50%)',
|
|
|
|
|
|
// }
|
|
|
|
|
|
// let imgElement = createVNode('img',{src:url,style:imgStyle})
|
|
|
|
|
|
// img.onload = ()=>{
|
|
|
|
|
|
// Modal.confirm({
|
|
|
|
|
|
// title: 'SR needs 300 points, whether to continue?',
|
|
|
|
|
|
// icon: false,
|
|
|
|
|
|
// okText: 'Yes',
|
|
|
|
|
|
// cancelText: 'No',
|
|
|
|
|
|
// content: imgElement,
|
|
|
|
|
|
// mask:false,
|
|
|
|
|
|
// centered:true,
|
|
|
|
|
|
// onOk() {
|
|
|
|
|
|
// if(img.width*scaleSR.value>4069 || img.height*scaleSR.value>4069){
|
|
|
|
|
|
// message.info('Your selected area and SR magnification are more than 4096 pixels,Please re-select.')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
// let data = {
|
|
|
|
|
|
// images: url,
|
|
|
|
|
|
// scale: scaleSR.value,
|
|
|
|
|
|
// uniqueId: "",
|
|
|
|
|
|
// imageType:imageType,
|
|
|
|
|
|
// }
|
|
|
|
|
|
// Https.axiosPost(Https.httpUrls.prepareForSR, data).then((rv) => {
|
|
|
|
|
|
// console.log(rv);
|
|
|
|
|
|
// store.dispatch('getCredits')
|
|
|
|
|
|
// emit('setTask')
|
|
|
|
|
|
// });
|
|
|
|
|
|
// },
|
|
|
|
|
|
// // onCancel(){
|
|
|
|
|
|
// // _this.isShowMark.value = false
|
|
|
|
|
|
// // resolve(false)
|
|
|
|
|
|
// // }
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
let allExportSR = ref([]);
|
|
|
|
|
|
let scaleSR = ref(2);
|
2024-09-25 11:07:49 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let setScaleSR = (value) => {
|
|
|
|
|
|
scaleSR.value = value;
|
|
|
|
|
|
};
|
|
|
|
|
|
let showSRExport = ref(false);
|
|
|
|
|
|
let cancelSRExport = () => {
|
|
|
|
|
|
allExportSR.value = [];
|
|
|
|
|
|
showSRExport.value = false;
|
|
|
|
|
|
};
|
|
|
|
|
|
let allChecked = ref(false);
|
|
|
|
|
|
let selectImg = (item) => {
|
|
|
|
|
|
item.checked = !item.checked;
|
|
|
|
|
|
let arr = allExportSR.value.filter((item) => item.checked);
|
|
|
|
|
|
if (arr.length == allExportSR.value.length) {
|
|
|
|
|
|
allChecked.value = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
allChecked.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
let selectAllImg = () => {
|
|
|
|
|
|
allChecked.value = !allChecked.value;
|
|
|
|
|
|
allExportSR.value.forEach((item) => {
|
|
|
|
|
|
item.checked = allChecked.value;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let setExportSR = () => {
|
|
|
|
|
|
let arr = [];
|
|
|
|
|
|
let data = [];
|
|
|
|
|
|
// if(allExportSR.value.filter(item=> item.checked ).length <= 0){
|
|
|
|
|
|
// message.info('Your print is empty')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
if (
|
|
|
|
|
|
credits <
|
|
|
|
|
|
allExportSR.value.filter((item) => item.checked).length * 30
|
|
|
|
|
|
) {
|
|
|
|
|
|
message.info(useI18.t("exportModel.jsContent4"));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let allPromise = allExportSR.value.map(async (item, index) => {
|
|
|
|
|
|
if (item.checked) {
|
|
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
|
|
let obj = {};
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
images: item.imgUrl,
|
|
|
|
|
|
scale: scaleSR.value,
|
|
|
|
|
|
uniqueId: "",
|
|
|
|
|
|
};
|
|
|
|
|
|
data.push(obj);
|
|
|
|
|
|
let img = new Image();
|
|
|
|
|
|
img.onload = () => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
img.width * scaleSR.value > 2048 ||
|
|
|
|
|
|
img.height * scaleSR.value > 2048
|
|
|
|
|
|
) {
|
|
|
|
|
|
arr.push(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
img.remove();
|
|
|
|
|
|
resolve(img);
|
|
|
|
|
|
};
|
|
|
|
|
|
img.src = item.imgUrl;
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
Promise.all(allPromise)
|
|
|
|
|
|
.then((promiseArr) => {
|
|
|
|
|
|
if (arr.length > 0) {
|
|
|
|
|
|
arr.forEach((item, index) => (arr[index] += 1));
|
|
|
|
|
|
let str = arr.join(",");
|
|
|
|
|
|
message.info(useI18.t("exportModel.jsContent5", { str: str }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let aa = promiseArr.filter((item) => item == undefined);
|
|
|
|
|
|
if (aa.length == promiseArr.length) {
|
|
|
|
|
|
message.info(useI18.t("exportModel.jsContent6"));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Https.axiosPost(Https.httpUrls.prepareForSR, data).then((rv) => {
|
|
|
|
|
|
emit("setTask", rv);
|
|
|
|
|
|
cancelSRExport();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {});
|
|
|
|
|
|
};
|
2024-06-17 09:39:01 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
let toSvg = () => {
|
|
|
|
|
|
// console.log(canvas.toSvg());
|
|
|
|
|
|
};
|
|
|
|
|
|
let setShare = async () => {
|
|
|
|
|
|
initAligningGuidelines(canvas, false);
|
|
|
|
|
|
let publishModal = publish.value;
|
|
|
|
|
|
publishModal.publishMask = true;
|
|
|
|
|
|
var imageDataURL = await setExportCanvas();
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
imgUrl: imageDataURL,
|
|
|
|
|
|
userlikeGroupId: userlikeGroupId,
|
|
|
|
|
|
};
|
|
|
|
|
|
publishModal.init(data);
|
|
|
|
|
|
document.removeEventListener("keydown", canvasKeyDown);
|
|
|
|
|
|
document.removeEventListener("keyup", canvasKeyUp);
|
|
|
|
|
|
};
|
|
|
|
|
|
const clearPublish = () => {
|
|
|
|
|
|
document.addEventListener("keydown", canvasKeyDown);
|
|
|
|
|
|
document.addEventListener("keyup", canvasKeyUp);
|
|
|
|
|
|
};
|
|
|
|
|
|
let setSubmit = () => {
|
|
|
|
|
|
let data = setCanvasContent(false);
|
|
|
|
|
|
data.canvasHeight = canvasWH.value.height;
|
|
|
|
|
|
let blob = new Blob([JSON.stringify(data)], { type: "application/json" });
|
|
|
|
|
|
let formData = new FormData();
|
|
|
|
|
|
formData.append("file", blob, "data.json");
|
|
|
|
|
|
formData.append("userLikeGroupId", userlikeGroupId);
|
|
|
|
|
|
let config = {
|
|
|
|
|
|
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" },
|
|
|
|
|
|
};
|
|
|
|
|
|
Https.axiosPost(Https.httpUrls.exportSave, formData, config).then(
|
|
|
|
|
|
(rv) => {
|
|
|
|
|
|
message.success(t("exportModel.jsContent7"));
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
let setCanvasContent = (isSaveImg) => {
|
|
|
|
|
|
var json = canvas.toJSON(["imgId", "minioUrl"]);
|
|
|
|
|
|
// console.log(JSON.stringify(json));
|
|
|
|
|
|
if (!isSaveImg) {
|
|
|
|
|
|
json.objects.forEach((item) => {
|
|
|
|
|
|
if (item.type == "image") {
|
|
|
|
|
|
delete item.src;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return json;
|
|
|
|
|
|
};
|
|
|
|
|
|
let textDataShow = ref(false);
|
|
|
|
|
|
let setTextData = (obj) => {
|
|
|
|
|
|
fontFamily.value = obj.fontFamily;
|
|
|
|
|
|
canvasPencilWidth.value["text"] = obj.fontSize;
|
|
|
|
|
|
canvasPencilColor.value = obj.fill;
|
|
|
|
|
|
};
|
|
|
|
|
|
let setFontFamily = () => {
|
|
|
|
|
|
if (createText.set) {
|
|
|
|
|
|
createText.set({
|
|
|
|
|
|
fontFamily: fontFamily.value,
|
|
|
|
|
|
fontSize: canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
? canvasPencilWidth.value[operation.value]
|
|
|
|
|
|
: 20,
|
|
|
|
|
|
fill: canvasPencilColor.value,
|
|
|
|
|
|
});
|
|
|
|
|
|
canvas.renderAll();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-10-11 23:26:10 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
//液化
|
|
|
|
|
|
//当前选择的液化对象
|
|
|
|
|
|
let liquefactionData = ref(null);
|
|
|
|
|
|
let liquefaction = ref(null);
|
|
|
|
|
|
let submitLiquefaction = (rv) => {
|
|
|
|
|
|
const originalWidth = liquefactionData.width * liquefactionData.scaleX; // 保存原始宽度
|
|
|
|
|
|
const originalHeight = liquefactionData.height * liquefactionData.scaleY; // 保存原始高度
|
|
|
|
|
|
liquefactionData.setSrc(rv, function () {
|
|
|
|
|
|
liquefactionData.scaleToWidth(originalWidth);
|
|
|
|
|
|
liquefactionData.scaleToHeight(originalHeight);
|
|
|
|
|
|
delete liquefactionData.minioUrl;
|
|
|
|
|
|
canvas.renderAll();
|
|
|
|
|
|
updateCanvasState();
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
const clearLiquefaction = () => {
|
|
|
|
|
|
setCanvasKeyDown();
|
|
|
|
|
|
};
|
|
|
|
|
|
let setLiquefaction = () => {
|
|
|
|
|
|
const activeObjects = canvas.getActiveObjects(); // 获取选中的对象
|
|
|
|
|
|
if (activeObjects.length === 1 && activeObjects[0].type === "image") {
|
|
|
|
|
|
liquefactionData = activeObjects[0];
|
|
|
|
|
|
liquefaction.value.init(activeObjects[0]);
|
|
|
|
|
|
clearCanvasKeyDown();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
message.info(useI18.t("exportModel.jsContent6"));
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
let arr = [
|
|
|
|
|
|
{ value: "Arial", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art1", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art2", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art3", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art4", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art5", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art6", name: "select font" },
|
|
|
|
|
|
{ value: "EN_slogan_art7", name: "select font" },
|
|
|
|
|
|
{ value: "微软雅黑", name: "请选择字体" },
|
|
|
|
|
|
{ value: "CN_slogan_art1", name: "请选择字体" },
|
|
|
|
|
|
{ value: "CN_slogan_art2", name: "请选择字体" },
|
|
|
|
|
|
{ value: "CN_slogan_art3", name: "请选择字体" },
|
|
|
|
|
|
{ value: "CN_slogan_art4", name: "请选择字体" },
|
|
|
|
|
|
{ value: "华文行楷", name: "请选择字体" },
|
|
|
|
|
|
{ value: "隶书", name: "请选择字体" },
|
|
|
|
|
|
];
|
|
|
|
|
|
textFontFamilyList.value = arr;
|
|
|
|
|
|
fontFamily.value = arr[0].value;
|
|
|
|
|
|
});
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
|
clearCanvasKeyDown();
|
|
|
|
|
|
});
|
|
|
|
|
|
return {
|
|
|
|
|
|
toSvg,
|
|
|
|
|
|
t,
|
|
|
|
|
|
toSvg,
|
|
|
|
|
|
isWindow, //判断是window还是mac
|
|
|
|
|
|
showUpgradePlan, //当前弹窗是否打开
|
|
|
|
|
|
canvasWH, //画布初始宽高
|
|
|
|
|
|
pencilbtnStyle, //笔触按钮
|
|
|
|
|
|
publish, //发布作品广场
|
|
|
|
|
|
credits, //积分 用来判断HD导出积分是否够用
|
|
|
|
|
|
init, //首页点击导出后初始化
|
|
|
|
|
|
setExport, //导出所有内容
|
|
|
|
|
|
cancelDsign, //关闭画布
|
|
|
|
|
|
setMaxInput, //设置画布宽高
|
|
|
|
|
|
isShowMark, //加载遮罩
|
|
|
|
|
|
allBoardData, //选择画布所有内容
|
|
|
|
|
|
closeNav, //导航展开或者收起来状态
|
|
|
|
|
|
setCloseNav, //给图片导航或者工具收起来或者展开
|
|
|
|
|
|
multiselect, //获取整体高度
|
|
|
|
|
|
onDragstart, //拖拽函数
|
|
|
|
|
|
setDragstart, //的移动端拖拽改为按下
|
|
|
|
|
|
historyState, //执行撤回或者反撤回
|
|
|
|
|
|
operation, //设置当前鼠标状态绘画或者矩形或者移动
|
|
|
|
|
|
operationMode, //设置矩形是边框还是填充
|
|
|
|
|
|
setOperation, //设置当前鼠标状态绘画或者矩形或者移动方法
|
|
|
|
|
|
setOperationMode, //设置矩形是边框还是填充方法
|
|
|
|
|
|
uploadImage, //上传图帕
|
|
|
|
|
|
setLayerIndex, //设置选中元素的层级
|
|
|
|
|
|
brushList, //笔触列表
|
|
|
|
|
|
clearPublish,
|
|
|
|
|
|
textureList, //材质列表
|
|
|
|
|
|
canvasPencilColor, //input选择颜色
|
|
|
|
|
|
canvasPencilWidth, //input选择宽度
|
|
|
|
|
|
setAllSelectWidth, //多选设置宽度
|
|
|
|
|
|
allSelectWidth, //多选设置宽度的值
|
|
|
|
|
|
colorHistoryList, //历史颜色
|
|
|
|
|
|
setColorHistory, //设置历史颜色
|
|
|
|
|
|
setPencilColor, //切换颜色执行函数 给当前矩形或者笔触设置颜色
|
|
|
|
|
|
setPencilWidth, //切换宽度执行函数 给当前矩形或者笔触设置宽度
|
|
|
|
|
|
setHDExport, //高清导出选择的图片
|
|
|
|
|
|
brushworkChange, //切换笔触的回调
|
|
|
|
|
|
keysList,
|
|
|
|
|
|
textureValueChange, //切换材质信息
|
|
|
|
|
|
brushworkValue, //当前笔触
|
|
|
|
|
|
textureValue, //当前材质
|
|
|
|
|
|
scaleSR,
|
|
|
|
|
|
setScaleSR,
|
|
|
|
|
|
//SR页面
|
|
|
|
|
|
showSRExport,
|
|
|
|
|
|
allExportSR,
|
|
|
|
|
|
cancelSRExport, //关闭高清导出
|
|
|
|
|
|
allChecked, //全选
|
|
|
|
|
|
selectAllImg, //控制全选
|
|
|
|
|
|
selectImg, //选中单个图片
|
|
|
|
|
|
setExportSR, //设置SR导出
|
|
|
|
|
|
setShare,
|
|
|
|
|
|
setSubmit,
|
|
|
|
|
|
textFontFamilyList,
|
|
|
|
|
|
fontFamily,
|
|
|
|
|
|
textDataShow,
|
|
|
|
|
|
setFontFamily,
|
|
|
|
|
|
//液化
|
|
|
|
|
|
liquefaction,
|
|
|
|
|
|
submitLiquefaction,
|
|
|
|
|
|
clearLiquefaction,
|
|
|
|
|
|
setLiquefaction,
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
data(prop) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
isMoible: isMoible(),
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
setGradient() {
|
|
|
|
|
|
return (gradient) => {
|
|
|
|
|
|
let gradientStr = "";
|
|
|
|
|
|
gradient.gradientList.sort((a, b) => {
|
|
|
|
|
|
let aArr = a.left.split("%")[0];
|
|
|
|
|
|
let bArr = b.left.split("%")[0];
|
|
|
|
|
|
return aArr - bArr;
|
|
|
|
|
|
});
|
|
|
|
|
|
gradient.gradientList.forEach((item, index) => {
|
|
|
|
|
|
let str = ",";
|
|
|
|
|
|
if (gradient.gradientList.length == index + 1) str = "";
|
|
|
|
|
|
gradientStr += `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a}) ${item.left}${str}`;
|
|
|
|
|
|
});
|
|
|
|
|
|
return `${gradientStr}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
"canvasWH.height": {
|
|
|
|
|
|
handler(newVal, oldVal) {
|
|
|
|
|
|
let canvasBox = document.querySelector(
|
|
|
|
|
|
".exportCanvasBox .exportCanvasBox_center"
|
|
|
|
|
|
);
|
|
|
|
|
|
let scrollBox = document.querySelector(".exportCanvasBox_scroll div");
|
|
|
|
|
|
if (!canvasBox || !scrollBox) return;
|
|
|
|
|
|
canvasBox.scroll({
|
|
|
|
|
|
top: 0, // 纵向滚动距离
|
|
|
|
|
|
left: 0, // 横向滚动距离
|
|
|
|
|
|
});
|
|
|
|
|
|
scrollBox.style.marginTop = 0 + "px";
|
|
|
|
|
|
let height = canvasBox.offsetHeight / (newVal / canvasBox.offsetHeight);
|
|
|
|
|
|
scrollBox.style.height = height + "px";
|
|
|
|
|
|
if (oldVal != 0) return;
|
|
|
|
|
|
let canvasBoxDom = document.querySelector(
|
|
|
|
|
|
".exportCanvasBox .exportCanvasBox_center"
|
|
|
|
|
|
);
|
|
|
|
|
|
let scale =
|
|
|
|
|
|
(newVal - canvasBoxDom.offsetHeight) /
|
|
|
|
|
|
(canvasBoxDom.offsetHeight - height);
|
|
|
|
|
|
let mouseDownOperation = (event) => {
|
|
|
|
|
|
//按下
|
|
|
|
|
|
let position = {
|
|
|
|
|
|
y: event.screenY,
|
|
|
|
|
|
top: scrollBox.style.marginTop
|
|
|
|
|
|
? scrollBox.style.marginTop.split("px")[0] * 1
|
|
|
|
|
|
: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
// let top =
|
|
|
|
|
|
let scrollMousemove = (e) => {
|
|
|
|
|
|
let height = scrollBox.style.height.split("px")[0] * 1;
|
|
|
|
|
|
let offsetTop = position.top + e.screenY - position.y;
|
|
|
|
|
|
offsetTop = offsetTop <= 0 ? 0 : offsetTop;
|
|
|
|
|
|
offsetTop =
|
|
|
|
|
|
height + offsetTop >= canvasBoxDom.offsetHeight
|
|
|
|
|
|
? canvasBoxDom.offsetHeight - height
|
|
|
|
|
|
: offsetTop;
|
|
|
|
|
|
scrollBox.style.marginTop = offsetTop + "px";
|
|
|
|
|
|
canvasBoxDom.scroll({
|
|
|
|
|
|
top: offsetTop * scale, // 纵向滚动距离
|
|
|
|
|
|
left: 0, // 横向滚动距离
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
let mouseMove = function (event) {
|
|
|
|
|
|
let e = getMousePosition(event, false);
|
|
|
|
|
|
scrollMousemove(e);
|
|
|
|
|
|
};
|
|
|
|
|
|
let touchmove = function (event) {
|
|
|
|
|
|
let e = getMousePosition(event, true);
|
|
|
|
|
|
scrollMousemove(e);
|
|
|
|
|
|
};
|
|
|
|
|
|
let mouseup = function () {
|
|
|
|
|
|
document.removeEventListener("mousemove", mouseMove);
|
|
|
|
|
|
document.removeEventListener("touchmove", touchmove);
|
|
|
|
|
|
document.removeEventListener("mouseup", mouseup);
|
|
|
|
|
|
document.removeEventListener("touchend", mouseup);
|
|
|
|
|
|
//移动端
|
|
|
|
|
|
};
|
|
|
|
|
|
document.addEventListener("mousemove", mouseMove);
|
|
|
|
|
|
document.addEventListener("touchmove", touchmove);
|
|
|
|
|
|
document.addEventListener("mouseup", mouseup);
|
|
|
|
|
|
document.addEventListener("touchend", mouseup);
|
2024-10-11 23:26:10 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// document.addEventListener('touchmove',scrollMousemove)
|
|
|
|
|
|
// scrollBox.addEventListener('touchend',mouseup)
|
|
|
|
|
|
};
|
|
|
|
|
|
canvasBoxDom.addEventListener("scroll", () => {
|
|
|
|
|
|
let height =
|
|
|
|
|
|
canvasBox.offsetHeight /
|
|
|
|
|
|
(this.canvasWH.height / canvasBox.offsetHeight);
|
|
|
|
|
|
let scale =
|
|
|
|
|
|
(this.canvasWH.height - canvasBoxDom.offsetHeight) /
|
|
|
|
|
|
(canvasBoxDom.offsetHeight - height);
|
|
|
|
|
|
const scrollTop = canvasBoxDom.scrollTop;
|
|
|
|
|
|
scrollBox.style.marginTop = scrollTop / scale + "px";
|
|
|
|
|
|
});
|
|
|
|
|
|
let mousedown = function (event) {
|
|
|
|
|
|
let e = getMousePosition(event, false);
|
|
|
|
|
|
mouseDownOperation(e);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let touchstart = function (event) {
|
|
|
|
|
|
let e = getMousePosition(event, true);
|
|
|
|
|
|
mouseDownOperation(e);
|
|
|
|
|
|
};
|
|
|
|
|
|
scrollBox.addEventListener("mousedown", mousedown);
|
|
|
|
|
|
scrollBox.addEventListener("touchstart", touchstart);
|
|
|
|
|
|
},
|
2024-02-23 14:32:33 +08:00
|
|
|
|
},
|
2025-06-18 22:57:10 +08:00
|
|
|
|
},
|
|
|
|
|
|
mounted() {},
|
2024-05-18 15:39:32 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
methods: {},
|
2024-02-23 14:32:33 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
2024-12-11 16:26:36 +08:00
|
|
|
|
:deep(.Export) {
|
2025-06-18 22:57:10 +08:00
|
|
|
|
flex: 1;
|
|
|
|
|
|
// height: 30rem;
|
|
|
|
|
|
// overflow-x: hidden;
|
|
|
|
|
|
> .ant-modal-content {
|
|
|
|
|
|
.ant-modal-body {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
background: #f9fafb;
|
|
|
|
|
|
border-radius: 3rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.icon {
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.icon-rotate {
|
|
|
|
|
|
transform: rotate(-180deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.exportCanvasBox {
|
2024-02-29 17:16:51 +08:00
|
|
|
|
flex: 1;
|
2025-06-18 22:57:10 +08:00
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
margin-top: 2rem;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
.exportCanvasBox_title {
|
|
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
|
// font-weight: 600;
|
|
|
|
|
|
// margin-top: 2rem;
|
|
|
|
|
|
padding-top: 2rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
top: -1rem;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
margin: 0 2rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_intro {
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
font-size: 1.6rem;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_right,
|
|
|
|
|
|
.exportCanvasBox_left {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: auto;
|
|
|
|
|
|
.exportCanvasBox_left_tool {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.shortcutKeys_box {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
.shortcutKeys_list {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
width: 30rem;
|
|
|
|
|
|
max-height: 45rem;
|
|
|
|
|
|
background: #f7f8fa;
|
|
|
|
|
|
border-radius: 2rem;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
|
.shortcutKeys_list_item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
|
> .key {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.shortcutKeys_list_item:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
.shortcutKeys_list {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.label_item,
|
|
|
|
|
|
label {
|
2024-02-29 17:16:51 +08:00
|
|
|
|
display: flex;
|
2025-06-18 22:57:10 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
width: 23%;
|
|
|
|
|
|
div {
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
margin-right: 2rem;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
input,
|
|
|
|
|
|
select {
|
|
|
|
|
|
// width: 10em;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow: hidden !important;
|
|
|
|
|
|
height: 4.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.label_select {
|
|
|
|
|
|
img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-height: 100%;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.texture {
|
|
|
|
|
|
.label_select {
|
|
|
|
|
|
img {
|
|
|
|
|
|
max-height: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_item {
|
|
|
|
|
|
width: 20rem;
|
2024-02-29 17:16:51 +08:00
|
|
|
|
.exportCanvasBox_title {
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.exportCanvasBox_left_tool_item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_item.closeNav {
|
|
|
|
|
|
// max-height: 1000rem;
|
|
|
|
|
|
// height: auto;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left::-webkit-scrollbar,
|
|
|
|
|
|
.exportCanvasBox_right::-webkit-scrollbar {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left {
|
|
|
|
|
|
padding-right: 1rem;
|
|
|
|
|
|
margin-right: 2rem;
|
|
|
|
|
|
// height: 7rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
> label {
|
|
|
|
|
|
width: 20%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_title {
|
|
|
|
|
|
// margin: 0 4rem;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
.exportCanvasBox_left_tool_item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
2024-03-04 09:57:46 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.exportCanvasBox_left_tool_item_more {
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_item {
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
// max-height: 0;
|
|
|
|
|
|
transform: translate3d(0, 0, 0);
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_item,
|
|
|
|
|
|
.exportCanvasBox_imgbor,
|
|
|
|
|
|
.exportCanvasBox_operation_bor {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
height: auto;
|
|
|
|
|
|
max-height: 30rem;
|
|
|
|
|
|
border: 1px solid;
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
top: 7rem;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_item.exportCanvasBox_left_tool {
|
|
|
|
|
|
top: 100%;
|
|
|
|
|
|
transform: translateY(-110%);
|
|
|
|
|
|
left: 100%;
|
|
|
|
|
|
}
|
2024-09-03 16:39:06 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.exportCanvasBox_imgbor {
|
|
|
|
|
|
// height: auto;
|
|
|
|
|
|
width: 20rem;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
&.exportCanvasBox_imgbor::-webkit-scrollbar {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.exportCanvasBox_allItem {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
// justify-content: space-between;
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
.exportCanvasBox_item {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-right: 1rem;
|
|
|
|
|
|
.exportCanvasBox_img {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
|
img {
|
|
|
|
|
|
max-width: 7rem;
|
|
|
|
|
|
max-height: 14rem;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_img_SR {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
height: 2rem;
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_item_colorBor {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_item_color {
|
|
|
|
|
|
width: 8rem;
|
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
|
.exportCanvasBox_item_BGcolor {
|
|
|
|
|
|
height: 5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
div {
|
|
|
|
|
|
// -webkit-user-select:none; /* Safari */
|
|
|
|
|
|
// -moz-user-select:none; /* Firefox */
|
|
|
|
|
|
// -ms-user-select:none; /* IE10+/Edge */
|
|
|
|
|
|
// user-select:none; /* Standard syntax */
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_item_dispose {
|
|
|
|
|
|
img {
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
max-height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.active {
|
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
|
transform: scale(0.9);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_operation_bor_item {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
margin-left: 8rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
.label_item {
|
|
|
|
|
|
margin-right: 2rem;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
.labelHover_show {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 10rem;
|
|
|
|
|
|
top: 100%;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
div {
|
|
|
|
|
|
width: 3rem;
|
|
|
|
|
|
height: 3rem;
|
|
|
|
|
|
margin-right: 1rem;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.label_item:hover {
|
|
|
|
|
|
.labelHover_show {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_tool_item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
2024-09-11 16:36:08 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
flex-wrap: nowrap;
|
|
|
|
|
|
&.leftAlign {
|
|
|
|
|
|
justify-content: flex-start;
|
2024-03-26 15:45:32 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
&.leftAlign {
|
|
|
|
|
|
justify-content: flex-start;
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
|
font-size: 2.5rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
width: 4rem;
|
|
|
|
|
|
height: 4rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
border: 1px solid;
|
|
|
|
|
|
border-radius: 0.4rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.icon-xiala {
|
|
|
|
|
|
transform: rotate(-90deg);
|
|
|
|
|
|
&.icon-rotate-tool {
|
|
|
|
|
|
transform: rotate(90deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.uploadImage {
|
|
|
|
|
|
width: 4rem;
|
|
|
|
|
|
height: 4rem;
|
|
|
|
|
|
input {
|
|
|
|
|
|
height: 0;
|
|
|
|
|
|
width: 0;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_bottom {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
background: #f9fafb;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
padding-top: 2rem;
|
|
|
|
|
|
.exportCanvasBox_left_credits {
|
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_left_btn {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
.subitOkPreviewBtn {
|
|
|
|
|
|
position: initial;
|
|
|
|
|
|
transform: none;
|
|
|
|
|
|
margin-bottom: 0rem;
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.subitOkPreviewBtn:nth-child(2n) {
|
|
|
|
|
|
margin: 0 1rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_center_box {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_center {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
// overflow: hidden;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
.editFrontBack_pencilbtn {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
border: 1px solid #000;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
|
}
|
|
|
|
|
|
&.exportCanvasBox_center::-webkit-scrollbar {
|
|
|
|
|
|
/* 竖轴的宽度 */
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.exportCanvasBox_scroll {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
width: 2rem;
|
|
|
|
|
|
background: #d6cfe3;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
border-radius: 1rem;
|
|
|
|
|
|
div {
|
|
|
|
|
|
background: #543087;
|
|
|
|
|
|
border-radius: 1rem;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 30rem;
|
|
|
|
|
|
}
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.export_new_collection_review {
|
|
|
|
|
|
position: initial;
|
|
|
|
|
|
margin: 10rem auto;
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-23 14:32:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
<style lang="less">
|
2024-02-29 17:16:51 +08:00
|
|
|
|
.Export {
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.ant-modal-content {
|
|
|
|
|
|
.ant-modal-body {
|
|
|
|
|
|
height: calc(65rem * 1.2);
|
2024-02-29 17:16:51 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
}
|
2024-03-15 09:21:17 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.label_select_item {
|
|
|
|
|
|
img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-height: 100%;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
}
|
2024-02-23 14:32:33 +08:00
|
|
|
|
}
|
2024-03-26 15:45:32 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
<style lang="less">
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.SRExport {
|
|
|
|
|
|
.ant-modal-body {
|
|
|
|
|
|
height: calc(35rem * 1.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.SRExport_img {
|
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
min-height: 12rem;
|
|
|
|
|
|
.SRExport_img_item_box {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
margin-right: 2rem;
|
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
|
input {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0.5rem;
|
|
|
|
|
|
right: 0.5rem;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
height: 2rem;
|
|
|
|
|
|
width: 2rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
img {
|
|
|
|
|
|
width: 10rem;
|
|
|
|
|
|
max-height: 10rem;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
transform: scale(0.8);
|
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.check_all_block {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
font-size: 1.6rem;
|
|
|
|
|
|
color: #64686d;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
&.check_all {
|
|
|
|
|
|
color: #1a1a1a;
|
|
|
|
|
|
.check_block {
|
|
|
|
|
|
.check_block_body {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-26 15:45:32 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
.check_block {
|
|
|
|
|
|
width: 2.4rem;
|
|
|
|
|
|
height: 2.4rem;
|
|
|
|
|
|
background: #ebecf4;
|
|
|
|
|
|
border: 0.1rem solid #64686d;
|
|
|
|
|
|
padding: 0.3rem;
|
|
|
|
|
|
margin-right: 0.7rem;
|
|
|
|
|
|
.check_block_body {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: #000;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.SRExport_operate {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
.SRExport_operate_box {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
> div {
|
|
|
|
|
|
width: 5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.SRExport_operate_item_sclae {
|
|
|
|
|
|
width: 4rem;
|
|
|
|
|
|
height: 3rem;
|
|
|
|
|
|
border: 0.2rem solid rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
margin-right: 1rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
border-radius: 0.4rem;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
border-color: rgba(152, 139, 247);
|
|
|
|
|
|
color: rgba(152, 139, 247);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.SRExport_operate_sclae {
|
|
|
|
|
|
max-width: 15rem;
|
|
|
|
|
|
}
|
2024-03-26 15:45:32 +08:00
|
|
|
|
|
2025-06-18 22:57:10 +08:00
|
|
|
|
// input {
|
|
|
|
|
|
// // width: 10em;
|
|
|
|
|
|
// overflow: hidden;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// label{
|
|
|
|
|
|
// display: flex;
|
|
|
|
|
|
// align-items: center;
|
|
|
|
|
|
// margin-right: 2rem;
|
|
|
|
|
|
// span{
|
|
|
|
|
|
// margin-right: 1rem;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.generalModelOperate_endBtn {
|
|
|
|
|
|
.generalModelOperate_btn_ok {
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
|
cursor: no-drop;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-26 15:45:32 +08:00
|
|
|
|
}
|
2025-06-18 22:57:10 +08:00
|
|
|
|
</style>
|