This commit is contained in:
X1627315083
2024-03-04 09:57:46 +08:00
parent aa5f2e4208
commit 1dcafb8d5d
6 changed files with 571 additions and 494 deletions

View File

@@ -714,20 +714,23 @@ li {
.design_detail_modal_component .ant-upload-list-picture-card-container, .design_detail_modal_component .ant-upload-list-picture-card-container,
.designOpenrtion_modal .ant-upload-list-picture-card-container, .designOpenrtion_modal .ant-upload-list-picture-card-container,
.UpgradePlan_modal .ant-upload-list-picture-card-container, .UpgradePlan_modal .ant-upload-list-picture-card-container,
.refund_reason .ant-upload-list-picture-card-container { .refund_reason .ant-upload-list-picture-card-container,
.Export .ant-upload-list-picture-card-container {
display: none !important; display: none !important;
} }
.design_detail_modal_component .ant-upload-picture-card-wrapper, .design_detail_modal_component .ant-upload-picture-card-wrapper,
.designOpenrtion_modal .ant-upload-picture-card-wrapper, .designOpenrtion_modal .ant-upload-picture-card-wrapper,
.UpgradePlan_modal .ant-upload-picture-card-wrapper, .UpgradePlan_modal .ant-upload-picture-card-wrapper,
.refund_reason .ant-upload-picture-card-wrapper { .refund_reason .ant-upload-picture-card-wrapper,
.Export .ant-upload-picture-card-wrapper {
width: auto; width: auto;
vertical-align: top; vertical-align: top;
} }
.design_detail_modal_component .subitOkPreviewBtn, .design_detail_modal_component .subitOkPreviewBtn,
.designOpenrtion_modal .subitOkPreviewBtn, .designOpenrtion_modal .subitOkPreviewBtn,
.UpgradePlan_modal .subitOkPreviewBtn, .UpgradePlan_modal .subitOkPreviewBtn,
.refund_reason .subitOkPreviewBtn { .refund_reason .subitOkPreviewBtn,
.Export .subitOkPreviewBtn {
background-color: #38205b; background-color: #38205b;
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;

View File

@@ -798,7 +798,7 @@ input:focus{
} }
} }
} }
.design_detail_modal_component,.designOpenrtion_modal,.UpgradePlan_modal,.refund_reason{ .design_detail_modal_component,.designOpenrtion_modal,.UpgradePlan_modal,.refund_reason,.Export{
.ant-upload-list-picture-card-container{ .ant-upload-list-picture-card-container{
display: none !important; display: none !important;
} }

View File

@@ -20,43 +20,35 @@
</div> --> </div> -->
<div class="exportCanvasBox"> <div class="exportCanvasBox">
<div class="exportCanvasBox_left"> <div class="exportCanvasBox_left">
<div class="exportCanvasBox_title">Canvas Title</div> <div class="exportCanvasBox_title">Canvas Size</div>
<label> <label>
<div>Width:</div> <div>Width:</div>
<input <input type="number" @input="setMaxInput('width', 500)" v-model="canvasWH.width"/>
type="number"
@input="setMaxInput('width', 500)"
v-model="canvasWH.width"
/>
</label> </label>
<label> <label>
<div>Height:</div> <div>Height:</div>
<input <input type="number" @input="setMaxInput('height', 10000)" v-model="canvasWH.height"/>
type="number"
@input="setMaxInput('height', 1000)"
v-model="canvasWH.height"
/>
</label> </label>
<div class="exportCanvasBox_title" @click.stop="setCloseNav()"> <div class="exportCanvasBox_title" @click.stop="setCloseNav(0)">
Canvas Nav Canvas Nav
<div <div
:class="[ :class="[
'icon', 'icon',
'iconfont', 'iconfont',
'icon-xiala', 'icon-xiala',
closeNav?'icon-rotate':'' closeNav==0?'icon-rotate':''
]" ]"
> >
</div> </div>
</div> </div>
<div class="exportCanvasBox_img" :class="{closeNav:'closeNav'}"> <div class="exportCanvasBox_img" :class="{'closeNav' :closeNav==0}">
<div <div
class="exportCanvasBox_allItem" class="exportCanvasBox_allItem"
v-for="(item,key) in allBoardData" v-for="(item,key) in allBoardData"
> >
<div v-if="item[0]" class="exportCanvasBox_intro">{{ key }}</div> <div v-if="item[0]" class="exportCanvasBox_intro">{{ key }}</div>
<div class="exportCanvasBox_item_color" v-if="key == 'colorBoards'" v-for="colorItem in item" draggable="true" @dragstart="onDragstart(key,colorItem)">
<div class="exportCanvasBox_item_color" v-if="key == 'colorBoards'" v-for="colorItem in item"> <img src="" alt="">
<div class="exportCanvasBox_item_BGcolor" :style="{'background-color': 'rgb('+colorItem.rgbValue.r+','+colorItem.rgbValue.g+','+colorItem.rgbValue.b+')'}"></div> <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.tcx}}</div>
<div>{{colorItem.name}}</div> <div>{{colorItem.name}}</div>
@@ -67,20 +59,50 @@
:class="[key == 'disposeMoodboard'?'exportCanvasBox_item_dispose':'']" :class="[key == 'disposeMoodboard'?'exportCanvasBox_item_dispose':'']"
v-for="imgItem in item" v-for="imgItem in item"
draggable draggable
@dragstart="onDragstart(key)" @dragstart="onDragstart(key,imgItem)"
> >
<img :src="key == 'likeDesignCollectionList'?imgItem.designOutfitUrl:imgItem.imgUrl" alt="" /> <img :src="key == 'likeDesignCollectionList'?imgItem.designOutfitUrl:imgItem.imgUrl" alt="" />
</div> </div>
</div> </div>
</div> </div>
<div class="exportCanvasBox_title" @click.stop="setCloseNav(1)">
Canvas Tool
<div
:class="[
'icon',
'iconfont',
'icon-xiala',
closeNav==1?'icon-rotate':''
]"
>
</div>
</div>
</div> </div>
<div class="exportCanvasBox_center"> <div class="exportCanvasBox_center">
<!-- <canvas ref="canvasDom" id="exportCanvas"></canvas> --> <!-- <canvas ref="canvasDom" id="exportCanvas"></canvas> -->
</div> </div>
<!-- <ExportNewCoolection ref="ExportNewCoolection"></ExportNewCoolection> --> <!-- <ExportNewCoolection ref="ExportNewCoolection"></ExportNewCoolection> -->
<div class="exportCanvasBox_right"> <div class="exportCanvasBox_right">
<div class="" @click="setExport">export</div> <div class="exportCanvasBox_title">
High-definition Download
</div>
<div @click="historyState(stateIndex - 1)">123</div>
<div @click="historyState(stateIndex + 1)">321</div>
<div class="exportCanvasBox_right_definition">
<label>
<div>Width:</div>
<input type="number" @input="setMaxInput('width', 500)" v-model="canvasWH.width"/>
</label>
<label>
<div>Height:</div>
<input type="number" @input="setMaxInput('height', 10000)" v-model="canvasWH.height" />
</label>
</div>
<div class="" @click="multiselect">all</div> <div class="" @click="multiselect">all</div>
<div class="exportCanvasBox_right_btn">
<div class="subitOkPreviewBtn" @click="setExport">HD Export</div>
<div class="subitOkPreviewBtn" @click="setExport">Export</div>
</div>
</div> </div>
<div class="mark_loading" v-show="isShowMark"> <div class="mark_loading" v-show="isShowMark">
<a-spin size="large" /> <a-spin size="large" />
@@ -89,17 +111,10 @@
</a-modal> </a-modal>
</template> </template>
<script> <script>
import { import {defineComponent, computed, h, ref, nextTick, inject, reactive, onMounted,
defineComponent,
computed,
h,
ref,
nextTick,
inject,
reactive,
onMounted,
} from "vue"; } from "vue";
import { Https } from "@/tool/https"; import { Https } from "@/tool/https";
import { multiselectJS } from "@/tool/canvasDrawing";
import scaleImage from "@/component/HomePage/scaleImage.vue"; import scaleImage from "@/component/HomePage/scaleImage.vue";
import ExportNewCoolection from "@/component/HomePage/ExportNewCoolection.vue"; import ExportNewCoolection from "@/component/HomePage/ExportNewCoolection.vue";
import { useStore } from "vuex"; import { useStore } from "vuex";
@@ -124,7 +139,6 @@ export default defineComponent({
}); });
canvasWH.value.width = [window.innerWidth/2.4] canvasWH.value.width = [window.innerWidth/2.4]
canvasWH.value.width = canvasWH.value.width.map(num => Math.round(num / 100) * 100)[0]; canvasWH.value.width = canvasWH.value.width.map(num => Math.round(num / 100) * 100)[0];
console.log(canvasWH.value.width);
let sketch = computed(() => { let sketch = computed(() => {
return store.state.HomeStoreModule.showSketchList; return store.state.HomeStoreModule.showSketchList;
}); });
@@ -145,9 +159,16 @@ export default defineComponent({
y: 0, y: 0,
height: 0, height: 0,
}; };
let sketchGrouping = 3; //sketch分组
let likeDesign = 4; //整体图分组
let disposeMoodboardShow = true;
let canvasState = ref([])//存放canvas操作
let stateIndex = ref(-1)//表示撤回数量
let isLoadCanvas = false//撤回或者反撤回false为撤回
let init = () => { let init = () => {
showUpgradePlan.value = true; showUpgradePlan.value = true;
console.log(position);
nextTick().then(async () => { nextTick().then(async () => {
allBoardData.value.likeDesignCollectionList = allBoardData.value.likeDesignCollectionList =
likeDesignCollectionList; likeDesignCollectionList;
@@ -164,9 +185,18 @@ export default defineComponent({
width: canvasWH.value.width, width: canvasWH.value.width,
height: canvasWH.value.height, height: canvasWH.value.height,
isDrawingMode: false, // 开启绘图模式 isDrawingMode: false, // 开启绘图模式
// preserveObjectStacking: true,
}); });
canvasOnDrop() canvasOnDrop()//开启鼠标到画布事件
let disposeMoodboardShow = true; setRemoveImage()//设置元素删除
canvas.on("object:modified", ()=>{
updateCanvasState()
});
canvas.on('selection:created', ()=>{
updateCanvasState('created')
});
// canvas.on("object:added", updateCanvasState);
// setCanvasOperation()//设置监听添加修改画布元素,用来做撤回功能
let arr = [ let arr = [
"disposeMoodboard", "disposeMoodboard",
"moodboardFiles", "moodboardFiles",
@@ -176,8 +206,7 @@ export default defineComponent({
"likeDesignCollectionList", "likeDesignCollectionList",
]; ];
let sketchGrouping = 3; //sketch分组
let likeDesign = 4; //整体图分组
let oldKey = ""; let oldKey = "";
let margin = 20; //每个图形边距 let margin = 20; //每个图形边距
// arr.forEach((item,index)=>{ // arr.forEach((item,index)=>{
@@ -185,98 +214,25 @@ export default defineComponent({
for (const key in allBoardData.value) { for (const key in allBoardData.value) {
if (item == key) { if (item == key) {
//循环渲染顺序 //循环渲染顺序
let setImgWidth = canvasWH.value.width; //这是设置画布等宽 let imgWidth = setImageWidth(key); //这是设置画布等宽
let sketchGroupingItem = []; let sketchGroupingItem = [];
if (
disposeMoodboardShow &&
item == "disposeMoodboard" &&
allBoardData.value[key].length != 0 &&
allBoardData.value[key][0] != null
) {
//如果是mood 需要判断用户是否点击layout
disposeMoodboardShow = false;
}
if ( if (
item == "moodboardFiles" && item == "moodboardFiles" &&
!disposeMoodboardShow !disposeMoodboardShow
) { ) {
continue; continue;
} }
if (item == "printboardFiles") {
setImgWidth = canvasWH.value.width / 8;
}
if (item == "sketchboardFiles") {
setImgWidth =
(canvasWH.value.width -
(sketchGrouping - 1) * 20) /
sketchGrouping;
}
if (item == "likeDesignCollectionList") {
setImgWidth =
(canvasWH.value.width -
(likeDesign - 1) * 20) /
likeDesign;
}
for (const [allItemIndex, allItem,] of allBoardData.value[key].entries()) { for (const [allItemIndex, allItem,] of allBoardData.value[key].entries()) {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
if (key == "colorBoards") { if (key == "colorBoards") {
var text = new fabric.Text( let rect = setGroup(allItem)
allItem.tcx, if (position.x + rect.width > canvasWH.value.width || oldKey != key) {
{
left: 0,
top: 60,
fontSize: 14,
fontFamily: "Arial",
textAlign: "left",
fill: "black",
}
);
let text1 = new fabric.Text(
allItem.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(${allItem.rgbValue.r},${allItem.rgbValue.g},${allItem.rgbValue.b})`,
});
if (
position.x + width >
canvasWH.value.width ||
oldKey != key
) {
position.x = 0; position.x = 0;
position.y += position.height; position.y += position.height;
} }
var group = new fabric.Group( let group = setCanvasColor(position.y,position.x,rect)
[color, text, text1],
{
left: position.x,
top: position.y,
width: width,
fill: "rgb(255,255,255)",
cornerSize: 10, // 选中时角的大小为20
transparentCorners: false, // 选中时角是被填充了。true 空心false 实心
stroke: "#212121",
strokeWidth: 1,
}
);
// 将矩形对象添加到 canvas 中
canvas.add(group);
oldKey = key; oldKey = key;
position.x += width + margin; position.x += rect.width + margin;
position.height = group.height + margin; position.height = group.height + margin;
resolve(); resolve();
} else { } else {
@@ -285,48 +241,22 @@ export default defineComponent({
itemCanvasImg = itemCanvasImg =
allItem.designOutfitUrl; allItem.designOutfitUrl;
} }
fabric.Image.fromURL( fabric.Image.fromURL(itemCanvasImg,(img) => {
itemCanvasImg, let scaleWH = imgWidth / img.width; //计算放到画布上缩小倍率
(img) => {
let proportion = img.height / img.width; //计算图形宽高比例
let scaleWH = setImgWidth / img.width; //计算放到画布上缩小倍率
if (position.x + img.width * scaleWH > canvasWH.value.width || oldKey != key) { if (position.x + img.width * scaleWH > canvasWH.value.width || oldKey != key) {
position.x = 0; position.x = 0;
position.y += position.height; position.y += position.height;
} }
img.set({ setCanvasImage(img,key,position.x,position.y)//设置图片
// width: setImgWidth/img.width,
// height: canvasWH.value.height/img.height,
left: position.x,
top: position.y,
scaleX:
setImgWidth / img.width,
scaleY:(img.width * proportion * scaleWH) / img.height,
cornerSize: 10, // 选中时角的大小为20
// lockRotation:true,
// lockScalingX:true,
lockRotation: true,
crossOrigin: "anonymous",
transparentCorners: false, // 选中时角是被填充了。true 空心false 实心
// cornerColor: "#a1de93", // 选中时,角的颜色是 青色
});
position.height = img.height * scaleWH + margin; position.height = img.height * scaleWH + margin;
if (key == "sketchboardFiles") { if (key == "sketchboardFiles") {
position.x += position.x +=
img.width * scaleWH + img.width * scaleWH +
margin; margin;
if ( if (sketchGroupingItem.length >= 3) {
sketchGroupingItem.length >=
3
) {
} else { } else {
sketchGroupingItem.push( sketchGroupingItem.push(JSON.parse(JSON.stringify(position)));
JSON.parse(
JSON.stringify(
position
)
)
);
} }
if (sketchGroupingItem.length >=3) { if (sketchGroupingItem.length >=3) {
let sketchXyIndex = { let sketchXyIndex = {
@@ -362,99 +292,128 @@ export default defineComponent({
canvas.add(img); canvas.add(img);
oldKey = key; oldKey = key;
resolve(); resolve();
}, },{ crossOrigin: "Anonymous" });
{ crossOrigin: "Anonymous" }
);
} }
}); });
} }
} }
} }
if(position.y+position.height>canvasWH.value.height){
canvasWH.value.height = Math.floor(position.y+position.height)
canvas.setHeight(canvasWH.value.height);
}
} }
}); });
}; };
let setCanvasImage = (itemCanvasImg)=>{ let setRemoveImage = ()=>{
fabric.Image.fromURL( let deleteObject = (eventData, transform)=> {
itemCanvasImg, var target = [transform.target];
(img) => { if(transform.target._objects){
let proportion = img.height / img.width; //计算图形宽高比例 target = transform.target._objects
let scaleWH = setImgWidth / img.width; //计算放到画布上缩小倍率
if (position.x + img.width * scaleWH > canvasWH.value.width || oldKey != key) {
position.x = 0;
position.y += position.height;
} }
// canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
// const sel = new fabric.ActiveSelection(canvas.getObjects(), {
// canvas
// })
target.forEach((item)=>{
var canvas = item.canvas;
canvas.remove(item);
})
canvas.requestRenderAll();
canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
}
const deleteIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAACxAAAAsQHGLUmNAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAdBJREFUSImt1r1uU0EQBeDPFh1pgBQEEwFVAg9BROhCAh1FAg1gkMA8DA0oKOEB3IEIRQgF4SEQBIUC6ENSGgPFXaPx+udeSxxppPXOzJnZ8e7MrRmPWdzANZxPv+EbvmILL/G9hGcADayjgz8l0kUb56qSX8dhBeJcDrFSRv44ZRQdt3EPczieZB5NvB1ymta4zCP5J1yucOIFfM6CDJykob8s73GiAnkPJ7Eb/H9iJhpsZJlPQh6D7AWe9Z5iFr+CIpalhjWspnXZ/pXA01FURkv/HxpxK+g2UE+yGfZXM5+doHt4DEtB2R5dAXdD9nfG2LVxNa2XKGreiziXGefZ5rKZbCLmg/4jHIWNqSEZ1fC0IrnE0bM5qqdFGWoV92RBf/P/S3RRVqI3YaOZGd8eQpgHXMt8HgTd67qi5fZwMzOO5XuREmim9ShEji04q78tLwSDSR/aYuD599DgeVDsY3pMhqOQt4pnUXlGf7PbTQ5VcQofgv8BTudGK/rb9Z6it5RhEV+CX1cxYoeiZXDg7OC+4vpNJbmkuC3vMtsuHpVltKzo55OOzINxmeeYxhPVhn5H0ftnhhGNeu49NBSjdBkX9H+27Cvu+Sv8GEXwF9+O3b1zwZqdAAAAAElFTkSuQmCC"
// 创建删除图片元素
let deleteImg = document.createElement('img')
deleteImg.src = deleteIcon
function renderIcon(icon) {
return function (ctx, left, top, styleOverride, fabricObject) {
var size = this.cornerSize;
ctx.save();
ctx.translate(left, top);
ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
ctx.drawImage(icon, -size/3, -size/3, size/1.5, size/1.5);
ctx.restore();
}
}
// 删除按钮控件
fabric.Object.prototype.controls.deleteControl = new fabric.Control({
x: 0.5,
y: -0.5,
offsetY: -16,
offsetX: 16,
cursorStyle: 'pointer',
mouseUpHandler: deleteObject,
render: renderIcon(deleteImg),
cornerSize: 24
})
}
//设置画布监听修改添加事件,用来做撤回功能
let updateCanvasState = (str) =>{
if (!isLoadCanvas) {
const canvasAsJson = JSON.stringify(canvas.toJSON());
if(str == 'created'){
if(canvasState.value.length == 0){
canvasState.value.push(canvasAsJson);
}
}else{
canvasState.value.push(canvasAsJson);
}
stateIndex.value = canvasState.value.length - 1;
} else {
isLoadCanvas = false;
}
}
let setImageWidth = (key)=>{
let imgWidth = canvasWH.value.width; //这是设置画布等宽
if (
disposeMoodboardShow &&
key == "disposeMoodboard" &&
allBoardData.value[key].length != 0 &&
allBoardData.value[key][0] != null
) {
//如果是mood 需要判断用户是否点击layout
disposeMoodboardShow = false;
}
if (key == "printboardFiles") {
imgWidth = canvasWH.value.width / 8;
}
if (key == "sketchboardFiles"||key == 'moodboardFiles') {
imgWidth =
(canvasWH.value.width -
(sketchGrouping - 1) * 20) /
sketchGrouping;
}
if (key == "likeDesignCollectionList") {
imgWidth =
(canvasWH.value.width -
(likeDesign - 1) * 20) /
likeDesign;
}
return imgWidth
}
let setCanvasImage = (img,key,left,top)=>{
let proportion = img.height / img.width; //计算图形宽高比例
let imgWidth = setImageWidth(key)
let scaleWH = imgWidth / img.width; //计算放到画布上缩小倍率
img.set({ img.set({
// width: setImgWidth/img.width, // width: imgWidth/img.width,
// height: canvasWH.value.height/img.height, // height: canvasWH.value.height/img.height,
left: position.x, left,
top: position.y, top,
scaleX: scaleX:
setImgWidth / img.width, imgWidth / img.width,
scaleY:(img.width * proportion * scaleWH) / img.height, scaleY:(img.width * proportion * scaleWH) / img.height,
cornerSize: 10, // 选中时角的大小为20 cornerSize: 10, // 选中时角的大小为20
// lockRotation:true, // lockRotation:true,
// lockScalingX:true, // lockScalingX:true,
lockRotation: true, lockRotation: true,
crossOrigin: "anonymous",
transparentCorners: false, // 选中时角是被填充了。true 空心false 实心 transparentCorners: false, // 选中时角是被填充了。true 空心false 实心
// cornerColor: "#a1de93", // 选中时,角的颜色是 青色 // cornerColor: "#a1de93", // 选中时,角的颜色是 青色
}); });
position.height = img.height * scaleWH + margin;
if (key == "sketchboardFiles") {
position.x +=
img.width * scaleWH +
margin;
if (
sketchGroupingItem.length >=
3
) {
} else {
sketchGroupingItem.push(
JSON.parse(
JSON.stringify(
position
)
)
);
}
if (sketchGroupingItem.length >=3) {
let sketchXyIndex = {
maxIndex: 0,
maxNum: 9999999999,
minNum: 0,
minIndex: 0,
};
sketchGroupingItem.forEach(
(sketchItem,sketchIndex) => {
if (sketchItem.height <sketchXyIndex.maxNum) {
sketchXyIndex.maxNum = sketchItem.height;
sketchXyIndex.maxIndex = sketchIndex;
}
if (sketchItem.height > sketchXyIndex.minNum) {
sketchXyIndex.minNum = sketchItem.height;
sketchXyIndex.minIndex = sketchIndex;
}
}
);
if (allBoardData.value[key].length == allItemIndex + 1) {
position = sketchGroupingItem[sketchXyIndex.minIndex];
} else {
position = sketchGroupingItem[ sketchXyIndex.maxIndex];
position.y += position.height;
position.x -= img.width * scaleWH + margin;
}
}
} else {
position.x += img.width * scaleWH;
}
img.lock_rotation = true;
canvas.add(img);
oldKey = key;
resolve();
},
{ crossOrigin: "Anonymous" }
);
} }
//设置导出 //设置导出
let setExport = async () => { let setExport = async () => {
var imageDataURL = canvas.toDataURL({ var imageDataURL = canvas.toDataURL({
@@ -501,17 +460,7 @@ export default defineComponent({
} }
let dataList = []; let dataList = [];
likeDesignCollectionList.value.forEach((item) => { likeDesignCollectionList.value.forEach((item) => {
// let nameTail = item?.designOutfitUrl
// ?.split(".")
// .pop()
// .split("?")
// .shift();
// let data = {
// imgUrl: item.designOutfitUrl,
// name: "result" + index + "." + nameTail,
// };
dataList.push(item.designItemId); dataList.push(item.designItemId);
// img.push(data);
index++; index++;
}); });
let mannequinList = []; let mannequinList = [];
@@ -589,6 +538,10 @@ export default defineComponent({
// maxNum = window.innerWidth < 1100 ? 400 : maxNum; // maxNum = window.innerWidth < 1100 ? 400 : maxNum;
maxNum = [window.innerWidth/2.4] maxNum = [window.innerWidth/2.4]
maxNum = maxNum.map(num => Math.round(num / 10) * 10)[0]; 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) { if (str == "width" && canvasWH.value.width >= maxNum) {
canvasWH.value.width = maxNum; canvasWH.value.width = maxNum;
@@ -599,12 +552,19 @@ export default defineComponent({
canvas.setWidth(canvasWH.value.width); canvas.setWidth(canvasWH.value.width);
}; };
let closeNav = ref(false) let closeNav = ref(0)
let setCloseNav = ()=>{ let setCloseNav = (num)=>{
closeNav.value = !closeNav.value if(closeNav.value == num){
closeNav.value = -1
}else{
closeNav.value = num
} }
}
function multiselect() { // let multiselect = ()=>{
// console.log(canvas);
// multiselectJS(canvas)
// }
function multiselect() {//获取整体宽高
canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。 canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
const sel = new fabric.ActiveSelection(canvas.getObjects(), { const sel = new fabric.ActiveSelection(canvas.getObjects(), {
canvas canvas
@@ -621,13 +581,16 @@ export default defineComponent({
} }
} }
let currentType = ref() let currentType = ref({
let onDragstart = (type)=>{ type:'',
console.log(type); data:'',
currentType.value = type })
let onDragstart = (type,imgItem)=>{
currentType.value.type = type
currentType.value.data = imgItem
} }
let canvasOnDrop = ()=>{ let canvasOnDrop = ()=>{
canvas.on('drop', function(opt) { canvas.on('drop', (opt)=> {
// 省略部分代码...... // 省略部分代码......
let offset = { let offset = {
left: canvas.getSelectionElement().getBoundingClientRect().left, left: canvas.getSelectionElement().getBoundingClientRect().left,
@@ -638,33 +601,90 @@ export default defineComponent({
y: opt.e.y - offset.top, y: opt.e.y - offset.top,
} }
let pointerVpt = canvas.restorePointerVpt(point) let pointerVpt = canvas.restorePointerVpt(point)
switch (currentType.value) { switch (currentType.value.type) {
case 'disposeMoodboard': case 'colorBoards':
createRect(pointerVpt.y, pointerVpt.x) let rect = setGroup(currentType.value.data)
setCanvasColor(pointerVpt.y, pointerVpt.x,rect)
break break
case 'circle': case 'moodboardFiles':
createCircle(pointerVpt.y, pointerVpt.x) createRect(pointerVpt.y, pointerVpt.x,currentType.value.type)
break break
case 'img': default :
createImg(pointerVpt.y, pointerVpt.x) createRect(pointerVpt.y, pointerVpt.x,currentType.value.type)
break break
} }
// 创建完元素,把当前操作的元素类型设置回 null // 创建完元素,把当前操作的元素类型设置回 null
currentType.value = null currentType.value.type = null
currentType.value.data = null
}) })
}
// 创建矩形 let setGroup = (data)=>{
function createRect(top, left) { var text = new fabric.Text(data.tcx,{
canvas.add(new fabric.Rect({ left: 0,
top, top: 60,
left, fontSize: 14,
width: 60, 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, height: 60,
fill: 'pink' textAlign: "left",
})) fill: `rgb(${data.rgbValue.r},${data.rgbValue.g},${data.rgbValue.b})`,
} });
let rect = {text,text1,color,width}
return rect
} }
let setCanvasColor = (top,left,rect)=>{
var group = new fabric.Group([rect.color, rect.text, rect.text1],{
left,
top,
width: rect.width,
fill: "rgb(255,255,255)",
cornerSize: 10, // 选中时角的大小为20
transparentCorners: false, // 选中时角是被填充了。true 空心false 实心
stroke: "#212121",
strokeWidth: 1,
});
// 将矩形对象添加到 canvas 中
canvas.add(group);
return group
}
// 创建矩形
let createRect = (top, left,key)=> {
let itemCanvasImg = currentType.value.data.imgUrl
if(key == 'likeDesignCollectionList'){
itemCanvasImg = currentType.value.data.designOutfitUrl;
}
fabric.Image.fromURL(itemCanvasImg,(img) => {
setCanvasImage(img,key,left,top)//设置图片
canvas.add(img);
},{ crossOrigin: "Anonymous" });
}
//撤回
let historyState = (index)=> {
if(index<=0){
index = 0
}else if (index >canvasState.value.length){
index = canvasState.value.length-1
}
isLoadCanvas = true;
canvas.loadFromJSON(canvasState.value[index], () => {
canvas.renderAll();
stateIndex.value = index;
});
}
onMounted(() => {}); onMounted(() => {});
return { return {
@@ -680,6 +700,8 @@ export default defineComponent({
setCloseNav, setCloseNav,
multiselect, multiselect,
onDragstart, onDragstart,
historyState,
stateIndex,
}; };
}, },
data(prop) { data(prop) {
@@ -700,7 +722,9 @@ export default defineComponent({
// } // }
// }, // },
}, },
methods: {}, methods: {
},
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@@ -757,8 +781,8 @@ export default defineComponent({
.icon{ .icon{
transition: all .3s; transition: all .3s;
} }
&.icon-rotate{ .icon-rotate{
transform: rotate(90deg); transform: rotate(-180deg);
} }
} }
.exportCanvasBox_intro{ .exportCanvasBox_intro{
@@ -772,11 +796,11 @@ export default defineComponent({
width: 25rem; width: 25rem;
height: 100%; height: 100%;
overflow-x: hidden; overflow-x: hidden;
}
.exportCanvasBox_left {
label { label {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
align-items: center;
margin-bottom: 1rem;
div { div {
width: 5rem; width: 5rem;
} }
@@ -784,13 +808,21 @@ export default defineComponent({
width: 10em; width: 10em;
} }
} }
.exportCanvasBox_img { .exportCanvasBox_img.closeNav{
transition: .3s all; max-height: 1000rem;
overflow: hidden;
height: auto;
&.closeNav{
// height: 0;
} }
}
.exportCanvasBox_left::-webkit-scrollbar,
.exportCanvasBox_right::-webkit-scrollbar{display: none;}
.exportCanvasBox_left {
.exportCanvasBox_img {
transition: all .3s;
overflow: hidden;
// height: auto;
max-height: 0;
transform: translate3d(0, 0, 0);
.exportCanvasBox_allItem { .exportCanvasBox_allItem {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@@ -811,6 +843,12 @@ export default defineComponent({
.exportCanvasBox_item_BGcolor{ .exportCanvasBox_item_BGcolor{
height: 5rem; 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{ .exportCanvasBox_item_dispose{
img{ img{
@@ -821,6 +859,23 @@ export default defineComponent({
} }
} }
} }
.exportCanvasBox_right{
display: flex;
flex-direction: column;
position: relative;
.exportCanvasBox_right_definition{
// display: flex;
flex: 1;
}
.exportCanvasBox_right_btn{
display: flex;
justify-content: space-between;
.subitOkPreviewBtn{
position: initial;
transform: none;
}
}
}
.exportCanvasBox_center { .exportCanvasBox_center {
height: 100%; height: 100%;
overflow-x: hidden; overflow-x: hidden;

View File

@@ -36,7 +36,7 @@
<div <div
class="trialApproval button_second credits hideChecked" class="trialApproval button_second credits hideChecked"
> >
Credits : Credits:&nbsp;
<span :title="credits"> <span :title="credits">
<!-- <div>{{ String(credits.value[credits.value.legnth-1]) }}</div> --> <!-- <div>{{ String(credits.value[credits.value.legnth-1]) }}</div> -->
<div class="credits_item" v-for="item in String(credits)" :style="{'transform': 'translateY('+item*-100+'%)'}"> <div class="credits_item" v-for="item in String(credits)" :style="{'transform': 'translateY('+item*-100+'%)'}">

View File

@@ -0,0 +1,19 @@
function multiselectJS(canvas) {//获取整体宽高
canvas.discardActiveObject() // 丢弃当前活动的对象和触发事件。 如果fabric作为鼠标事件的结果调用该函数则将该事件作为参数传递给自定义事件的fire函数。 当作为一个方法使用时,参数没有任何应用。
const sel = new fabric.ActiveSelection(canvas.getObjects(), {
canvas
})
// console.log(sel)
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;
return {totalWidth,totalHeight}
console.log('Total Width:', totalWidth);
console.log('Total Height:', totalHeight);
}
}
export default {multiselectJS,}

View File

@@ -1011,103 +1011,24 @@ export default defineComponent({
exportModel.init() exportModel.init()
}, },
//导出合成图 //导出合成图
async exportCanvas() { // async exportCanvas() {
let collectionReview: any = document.querySelector( // let collectionReview: any = document.querySelector(
"#exportNewCoolection" // "#exportNewCoolection"
); // );
let rightContentImgBlock: any = document.querySelector( // let rightContentImgBlock: any = document.querySelector(
"#right_content_img_block" // "#right_content_img_block"
); // );
if(this.driver__.driver){ // if(this.driver__.driver){
nextTick().then(()=>{ // nextTick().then(()=>{
driverObj__.moveNext(); // driverObj__.moveNext();
}) // })
} // }
let a = document.createElement("a"); // let a = document.createElement("a");
// this.isShowMark = true; // // this.isShowMark = true;
let img:any = [] // let img:any = []
await html2canvas(collectionReview, { useCORS: true, scale: 3 }).then( // await html2canvas(collectionReview, { useCORS: true, scale: 3 }).then(
async (canvas) => { // async (canvas) => {
let blob: any = dataURLtoBlob(
canvas.toDataURL("image/png")
);
let allBoardData: any =
this.store.state.UploadFilesModule.allBoardData;
let index = 0;
img.push({
imgUrl: URL.createObjectURL(blob),
name: "collection.png",
})
let num = 0
for (let key in allBoardData) {
if (key !== "colorBoards" && key !== "moodTemplateId") {
if(this.exportNav[num]?.change || key == 'disposeMoodboard'){
for (let item of allBoardData[key]) {
if(key == 'disposeMoodboard' && allBoardData[key][0]==undefined){
break
}
let nameTail = item?.imgUrl?.split(".").pop().split("?").shift();
let data = {
imgUrl: item.imgUrl,
name:
item?.resData?.name +
index +
"." +
nameTail,
};
img.push(data);
index++;
}
}else{
}
num++
}
}
let dataList:any = []
this.likeDesignCollectionList.forEach((item:any)=>{
let nameTail = item?.designOutfitUrl?.split(".").pop().split("?").shift();
let data = {
imgUrl: item.designOutfitUrl,
name:
'result' +
index +
"." +
nameTail,
};
dataList.push(item.designItemId)
img.push(data);
index++;
})
let mannequinList:any = []
await Https.axiosPost(Https.httpUrls.designGetModel, dataList)
.then((rv: any) => {
mannequinList = rv
})
.catch((rv) => {
});
mannequinList.forEach((item:any) => {
let nameTail = item?.split(".").pop().split("?").shift();
let data = {
imgUrl: item,
name:
'mannequin' +
index +
"." +
nameTail,
};
img.push(data);
index++;
});
// a.setAttribute('href', URL.createObjectURL(blob));
// a.setAttribute('download', `collection.png`);
// a.click();
}
);
//单独导出模特图
// await html2canvas(rightContentImgBlock, { useCORS: true, scale: 3 }).then(
// (canvas) => {
// let blob: any = dataURLtoBlob( // let blob: any = dataURLtoBlob(
// canvas.toDataURL("image/png") // canvas.toDataURL("image/png")
// ); // );
@@ -1116,20 +1037,99 @@ export default defineComponent({
// let index = 0; // let index = 0;
// img.push({ // img.push({
// imgUrl: URL.createObjectURL(blob), // imgUrl: URL.createObjectURL(blob),
// name: "achievement.png", // name: "collection.png",
// },) // })
// this.likeDesignCollectionList.forEach((item:any) => { // let num = 0
// let data = { // for (let key in allBoardData) {
// imgUrl:item.designItemUrl, // if (key !== "colorBoards" && key !== "moodTemplateId") {
// name:item.pictureName // if(this.exportNav[num]?.change || key == 'disposeMoodboard'){
// for (let item of allBoardData[key]) {
// if(key == 'disposeMoodboard' && allBoardData[key][0]==undefined){
// break
// } // }
// img.push(data) // let nameTail = item?.imgUrl?.split(".").pop().split("?").shift();
// let data = {
// imgUrl: item.imgUrl,
// name:
// item?.resData?.name +
// index +
// "." +
// nameTail,
// };
// img.push(data);
// index++;
// }
// }else{
// }
// num++
// }
// }
// let dataList:any = []
// this.likeDesignCollectionList.forEach((item:any)=>{
// let nameTail = item?.designOutfitUrl?.split(".").pop().split("?").shift();
// let data = {
// imgUrl: item.designOutfitUrl,
// name:
// 'result' +
// index +
// "." +
// nameTail,
// };
// dataList.push(item.designItemId)
// img.push(data);
// index++;
// })
// let mannequinList:any = []
// await Https.axiosPost(Https.httpUrls.designGetModel, dataList)
// .then((rv: any) => {
// mannequinList = rv
// })
// .catch((rv) => {
// }); // });
// mannequinList.forEach((item:any) => {
// let nameTail = item?.split(".").pop().split("?").shift();
// let data = {
// imgUrl: item,
// name:
// 'mannequin' +
// index +
// "." +
// nameTail,
// };
// img.push(data);
// index++;
// });
// // a.setAttribute('href', URL.createObjectURL(blob));
// // a.setAttribute('download', `collection.png`);
// // a.click();
// } // }
// ); // );
// return // //单独导出模特图
this.downImg(img); // // await html2canvas(rightContentImgBlock, { useCORS: true, scale: 3 }).then(
}, // // (canvas) => {
// // let blob: any = dataURLtoBlob(
// // canvas.toDataURL("image/png")
// // );
// // let allBoardData: any =
// // this.store.state.UploadFilesModule.allBoardData;
// // let index = 0;
// // img.push({
// // imgUrl: URL.createObjectURL(blob),
// // name: "achievement.png",
// // },)
// // this.likeDesignCollectionList.forEach((item:any) => {
// // let data = {
// // imgUrl:item.designItemUrl,
// // name:item.pictureName
// // }
// // img.push(data)
// // });
// // }
// // );
// // return
// this.downImg(img);
// },
//打开图片详情 //打开图片详情
designDetail( designDetail(
@@ -1186,34 +1186,34 @@ export default defineComponent({
}); });
}, },
// imgDataUrl 数据的url数组 // imgDataUrl 数据的url数组
downImg(imagesParams: any) { // downImg(imagesParams: any) {
let _this: any = this; // let _this: any = this;
let zip = new JSZip(); // let zip = new JSZip();
let cache: any = {}; // let cache: any = {};
let promises = []; // let promises = [];
for (let item of imagesParams) { // for (let item of imagesParams) {
const promise = _this // const promise = _this
.getImgArrayBuffer(item.imgUrl) // .getImgArrayBuffer(item.imgUrl)
.then((data: any) => { // .then((data: any) => {
// 下载文件, 并存成ArrayBuffer对象(blob) // // 下载文件, 并存成ArrayBuffer对象(blob)
zip.file(item.name, data, { binary: true }); // 逐个添加文件 // zip.file(item.name, data, { binary: true }); // 逐个添加文件
cache[item.title] = data; // cache[item.title] = data;
}); // });
promises.push(promise); // promises.push(promise);
} // }
Promise.all(promises) // Promise.all(promises)
.then(() => { // .then(() => {
zip.generateAsync({ type: "blob" }).then((content: any) => { // zip.generateAsync({ type: "blob" }).then((content: any) => {
// 生成二进制流 // // 生成二进制流
FileSaver.saveAs(content, "DesignFiles"); // 利用file-saver保存文件 自定义文件名 // FileSaver.saveAs(content, "DesignFiles"); // 利用file-saver保存文件 自定义文件名
this.isShowMark = false; // this.isShowMark = false;
}); // });
}) // })
.catch((res) => { // .catch((res) => {
message.warning(this.t('HomeView.jsContent3')); // message.warning(this.t('HomeView.jsContent3'));
this.isShowMark = false; // this.isShowMark = false;
}); // });
}, // },
}, },
}); });
</script> </script>