Files
aida_front/src/component/HomePage/ExportModel.vue
2025-01-27 16:22:34 +08:00

2925 lines
93 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div ref="ExportModal">
<a-modal
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"
>
<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>
</div>
</div>
<div class="UpgradePlan_content">
<div>{{ $t('exportModel.EditExport') }}</div>
</div>
<!-- <div>
<canvas ref="exportCanvas"></canvas>
</div> -->
<div class="exportCanvasBox">
<div class="exportCanvasBox_left">
<!-- <div class="exportCanvasBox_title">{{ $t('exportModel.CanvasSize') }}</div> -->
<!-- <label style="width: 10%">
<div>Width:</div>
<input type="number" @input="setMaxInput('width', 1000)" v-model="canvasWH.width"/>
</label> -->
<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="isMoible?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'">
<div >{{ $t('exportModel.Width') }}</div>
<input type="number" @input="setAllSelectWidth" v-model="allSelectWidth">
</div> -->
<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'">
<div >{{ $t('exportModel.Height') }}</div>
<input type="number" @input="setPencilColor" v-model="canvasPencilColor">
</div> -->
</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')">
{{ $t('exportModel.More') }}
</div>
-->
</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-bianji" @click="setOperation('pencil')" :class="{active:operation == 'pencil'}" :title="isWindow?'~':'~'"></i>
<i class="icon iconfont icon-caizhi" @click="setOperation('texture')" :class="{active:operation == 'texture'}"></i>
<i class="icon iconfont icon-move" @click="setOperation('move')" :class="{active:operation == 'move'}" :title="isWindow?'M':'M'"></i>
<i class="icon iconfont icon-xiangpi_huaban1" @click="setOperation('eraser')" :class="{active:operation == 'eraser'}" :title="isWindow?'~':'~'"></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>
<i class="fi fi-rr-zoom-out" @click="setOperation('zoomOut')" :class="{active:operation == 'zoomOut'}"></i> -->
<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>
<div>
<div></div>
<span>16:9</span>
</div>
</div> -->
</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">
<div class="exportCanvasBox_title">
High-definition Download
</div>
<div class="exportCanvasBox_right_definition">
<label>
<div>Scale:</div>
<input type="number" @input="setMaxInput('scale', 500)" v-model="scaleSR"/>
</label>
</div>
<div class="" @click="multiselect">all</div>
<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>
</div> -->
<!-- <div @click="toSvg()">2312312312</div> -->
<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>
</div>
<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"
style="flex: 1"
@change="setScaleSR"
>
<a-select-option class="label_select_item" v-for="item in scaleSRList" :value="item.value">
</a-select-option>
</a-select> -->
<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>
</a-modal>
</div>
</template>
<script>
import {defineComponent, computed, h, ref, nextTick, inject, reactive, onMounted,onBeforeUnmount
} from "vue";
import { Https } from "@/tool/https";
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import scaleImage from "@/component/HomePage/scaleImage.vue";
import ExportNewCoolection from "@/component/HomePage/ExportNewCoolection.vue";
import { useStore } from "vuex";
import JSZip, { forEach } from "jszip";
// import fabric from 'fabric';
import { message, Modal } from "ant-design-vue";
import domTurnImg from '@/tool/domTurnImg'
import { openGuide,driverObj__ } from "@/tool/guide";
const FileSaver = require("file-saver");
import { exportSele,JSRectUpdata,JSchangeType,JScanvasMouseDown,JScanvasMouseMove,JScreateCheck,JSSetTexture,JSSetRemoveImage } from "@/tool/canvasDrawing";
import { useI18n } from "vue-i18n";
import {isMoible,calculateGradientCoordinate,base64ToFile} from '@/tool/util'
import publish from "@/component/WorksPage/publish.vue";
import liquefaction from "@/component/modules/liquefaction.vue";
import { getMousePosition } from "@/tool/mdEvent";
export default defineComponent({
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);
}
}
})
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
});
canvasOnDrop()//开启鼠标到画布事件
if(!fabric.Object.prototype.controls.deleteControl){//设置元素删除
JSSetRemoveImage(deleteObject)
}else{
fabric.Object.prototype.controls.deleteControl.mouseUpHandler = deleteObject
}
// setRemoveImage()//设置元素删除
canvas.on("object:modified", ()=>{
updateCanvasState()
});
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')
}
});
// 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()//设置监听添加修改画布元素,用来做撤回功能
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)
});
})
}
setCanvasData(oldExportCanvas)
})
});
};
let deleteObject = ()=> {
// var target = [transform.target];
if(!canvas.getActiveObjects()){
return
}
let target = canvas.getActiveObjects()
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')
}
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;
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(/:(\d+)\/(.*)/);
minioUrl = match[2]
// 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;
}
});
canvasWH.value.height = Math.round(maxHeight)+30
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;
}
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();
}
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,
};
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);
}
};
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);
};
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
}
let point = {
x: opt.e.x - offset.left,
y: opt.e.y - offset.top,
}
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}
}
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, () => {});
}
//在画布进行画画
let operation = ref('move')
let operationMode = ref('fill')
let textureValue = ref(0)//材质信息
let textureValueChange = (value)=>{
textureValue.value = value
setTexture()
}
//铅笔颜色 大小
let brushworkValue = ref('PencilBrush')
let brushworkChange = (value)=>{
brushworkValue.value = value
setPencil()
}
// let brushwork = ref('')
// 监听键盘的 keydown 和 keyup 事件
let keyDown = []
const keysList = [
{
name:useI18.t('exportModel.PaintingEraser'),
winDowKey:'~',
macKey:'~',
},{
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 oldOperation = ''
let canvasKeyDown = (event) => {
let keys = ['Enter','Delete','ControlLeft','KeyZ','ShiftLeft','KeyC','KeyV','BracketLeft','BracketRight','KeyI','KeyD','KeyO','Backquote','MetaLeft']
if(keys.indexOf(event.code) > -1){
event.preventDefault();
}
if(keyDown.indexOf(event.code)>-1){
}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('Backquote') > -1){
// if(operation.value == 'pencil' || operation.value == 'texture'){
let str = 'pencil'
if(operation.value == 'pencil')str = 'eraser'
oldOperation = operation.value
setOperation(str)
// }
}
}
}
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','KeyZ','ShiftLeft','KeyC','KeyV','BracketLeft','BracketRight','KeyI','KeyD','KeyO','Backquote','MetaLeft']
if(keys.indexOf(event.code) > -1){
event.preventDefault();
}
keyDown = keyDown.filter(function(item) {
return event.code !== item;
})
if(event.code == 'Backquote' && oldOperation){
// setOperation(oldOperation)
oldOperation = ''
}
}
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;
// 检查是否鼠标离开了画布
// 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() // 取消选择
// 设置新内容的坐标位置
clonedObj.set({
left: clonedObj.left + 10,
top: clonedObj.top + 10,
evented: true
})
if (clonedObj.type === 'activeSelection') {
// 活动选择需要一个对画布的引用
clonedObj.canvas = canvas;
clonedObj.forEachObject(function(obj) {
canvas.add(obj)
})
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)
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,{}); //长毛刷
}
canvas.freeDrawingBrush = pencil
canvas.freeDrawingBrush.width = canvasPencilWidth.value[operation.value]?canvasPencilWidth.value[operation.value]:20;
if(brushworkValue.value == 'RibbonBrush' || brushworkValue.value == 'LongfurBrush'){
canvas.freeDrawingBrush.width = 1;
}
if(brushworkValue.value == 'Marking'){
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value,.5);
// }else if(brushworkValue.value == 'InkBrush'){
// canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value,.2);
}else{
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value,1);
}
pencilbtnStyle.value.background = canvasPencilColor.value
canvas.freeDrawingBrush.isEraser = false
}
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);
// }
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,.5);
}else if(brushworkValue.value == 'InkBrush'){
canvas.freeDrawingBrush.color = hexToRgba(canvasPencilColor.value,.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);
let zoom = canvas.getZoom() // 获取画布当前缩放值
let num = -100
if(operation.value == 'zoomOut') num = 100
zoom *= 0.999 ** num
if (zoom > 20) zoom = 20
if (zoom < 0.01) zoom = 0.01
// 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
//多选导出转高清暂时不用
// 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);
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 => {
});
}
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();
}
}
//液化
//当前选择的液化对象
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);
// 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)
}
},
},
mounted() {
},
methods: {
},
});
</script>
<style lang="less" scoped>
:deep(.Export) {
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 .3s;
}
.icon-rotate{
transform: rotate(-180deg);
}
.exportCanvasBox {
flex: 1;
overflow-x: hidden;
display: flex;
margin-top: 2rem;
justify-content: space-between;
flex-direction: column;
.exportCanvasBox_title {
margin-bottom: .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 {
display: flex;
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;
.exportCanvasBox_title{
.exportCanvasBox_left_tool_item{
display: flex;
}
}
}
.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;
}
.exportCanvasBox_left_tool_item_more{
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
padding: 1rem;
}
}
.exportCanvasBox_left_item{
overflow: hidden;
transition: all .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%;
}
.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 */
}
}
.exportCanvasBox_item_dispose{
img{
max-width: 100%;
max-height: 100%;
}
}
.active{
opacity: .5;
transform: scale(.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;
flex-direction: row;
flex-wrap: nowrap;
&.leftAlign{
justify-content: flex-start;
}
&.leftAlign{
justify-content: flex-start;
}
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: .4rem;
}
}
.icon-xiala{
transform: rotate(-90deg);
&.icon-rotate-tool{
transform: rotate(90deg);
}
}
.uploadImage{
width: 4rem;
height: 4rem;
input{
height: 0;
width: 0;
border: none;
}
}
}
}
.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: .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;
}
}
.export_new_collection_review {
position: initial;
margin: 10rem auto;
margin-bottom: 0;
}
}
}
</style>
<style lang="less">
.Export {
.ant-modal-content {
.ant-modal-body {
height: calc(65rem * 1.2);
}
}
}
.label_select_item{
img{
width: 100%;
max-height: 100%;
object-fit: contain;
}
}
</style>
<style lang="less">
.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: .5rem;
right: .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(.8);
opacity: .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;
}
}
}
.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: #343579;
}
}
}
.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: .2rem solid rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
cursor: pointer;
border-radius: .4rem;
font-weight: 600;
&.active{
border-color: rgba(152, 139, 247);
color: rgba(152, 139, 247);
}
}
.SRExport_operate_sclae{
max-width: 15rem;
}
// 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: .6;
cursor: no-drop;
}
}
}
}
</style>