Files
aida_front/src/tool/canvasGeneralCopy.js
X1627315083 b6e5f05f06 fix
2025-04-01 15:25:15 +08:00

2272 lines
74 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
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.
import {
exportSele,
JSRectUpdata,
JSchangeType,
JScanvasMouseDown,
JScanvasMouseMove,
JScreateCheck,
JSSetTexture,
JSSetRemoveImage,
} from "@/tool/canvasDrawingCopy";
import { getMousePosition } from "@/tool/mdEvent";
import { getMinioUrl } from "@/tool/util";
import { file } from "jszip";
class MyCanvas {
constructor(id) {
this.id = id || Date.now();
this.pencilList = {
textFontFamilyList:[
{ 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: '请选择字体' },
],
brushList:[
{
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'
},
]
}
this.canvasDomParent = null;
this.canvas = MyCanvas?.[this.id];
this.addPresent = {}
this.canvasWH={
width:0,
height:0,
}
this.createPatterning = {//创建图形
state:false,
content:null,
current:null, //临时图形
polyLineBtn:null,
textDataShow:false,
}
this.mouse = {
point:null,
upPoint:null,
isMovePostion:false,
isDown:false,
lastPosX:0,
lastPosY:0,
}
this.keyboard={
down:[]
}
this.pencilbtnStyle ={//笔触图形
background:'',
width:0+'px',
height:0+'px',
display:'none',
left:0+'px',
top:0+'px',
}
this.layer = {
list:[],
selectLayer:{
group:null,
id:-1,
},
currentIndex:0,
}
this.liquefaction = {
img:null,
type:'',
dashed:null,
}
this.clipPath = {
isImg:false,
img:null,
clipGroup:null
}
this.dashed = {
state:false,//用来判断鼠标是否移入dashed 如果移入就变为可拖拽
isDrawingMode:false,//用来获取移入前是否是绘画模式
isDetail:false,//判断裁剪或者局部添加内容为true是添加内容
isDashedShow:false,//判断选区是否存在
}
this.currentOperation = true //表示是否可以使用快捷键
this.fontFamily = this.pencilList.textFontFamilyList[0].value
this.createText=null
this.pencilBtn = null;
this.pencilType = null;
this.canvasPencilColor = '#000000'
this.colorHistoryList = ['rgb(0, 0, 0)']
this.keyDown = [];//键盘按下
this.oldOperation = ''
//笔触
this.brushwork = {
value:'PencilBrush',
width:{},
color:'#000000',
texture:0,
}
this.texture={
value:0,
list:[],
}
for (let index = 0; index < 20; index++) {
this.texture.list.push({value:index,url:`/image/texture/texture${index}.webp`})
}
this._clipboard = null; //剪切板
this.isLoadCanvas = false//撤回或者反撤回false为撤回
this.reverseCanvasState=[];//撤回
this.normalCanvasState=[];//反撤回
this.canvasState = {}//当前内容
this.operation = 'movePosition'
this.operationMode = 'fill'
this.setTimeOut = {//定时器
color:null,
width:null,
colorHistory:null,
canvasWH:null,
updataLayer:null,
}//给切换颜色设置防抖
}
async canvasInit (dom, val,img,editGroupImg,data){//初始化
// let {erasable} = data
// this.canvasClear()
this.canvasWH = val
this.canvasDomParent = dom;
var canvasDom = document.createElement("canvas");
this.canvasDomParent.appendChild(canvasDom);
MyCanvas[this.id] = await new fabric.Canvas(canvasDom, {
backgroundColor: "rgba(230, 230, 230)",
width: this.canvasWH.width,
height: this.canvasWH.height,
isDrawingMode: val.isDrawingMode, // 开启绘图模式
selectionFullyContained: true,
selectionKey:'ctrlKey',
includeDefaultValues: false,//尚未测试 精简导出JSON
// freeDrawingCursor: 'none',
preserveObjectStacking:true,
hoverCursor: 'pointer',
});
// await new Promise((resolve, reject) => {
// canvas.clone(cloned=>{
// cloned.set({
// })
// this.canvas = cloned
// resolve()
// })
// })
// MyCanvas?.[this.id].freeDrawingCursor= 'none'
// let imgage = await this.createImage({minioUrl:img})
// let rect1 = new fabric.Rect({
// left: 0,
// top: 0,
// width: 500,
// height: 500,
// fill: "red",
// });
// canvas.add(rect1)
this.initCanvasWH('init')
fabric.Object.prototype.cornerSize = 10//选中后的操作按钮大小
fabric.Object.prototype.transparentCorners = false //实心
if(!fabric.Object.prototype.controls.deleteControl){//设置元素删除
JSSetRemoveImage(this.deleteObject.bind(this))
}else{
fabric.Object.prototype.controls.deleteControl.mouseUpHandler = this.deleteObject.bind(this)
}
MyCanvas?.[this.id].on("object:modified", (event)=>{
this.updateCanvasState('')
this.updataLayer()
});
this.canvasKeyDown = this.canvasKeyDown.bind(this);
this.canvasKeyUp = this.canvasKeyUp.bind(this);
// let rect1 = new fabric.Rect({
// left: 0,
// top: 0,
// width: 500,
// height: 500,
// fill: "red",
// });
// MyCanvas?.[this.id].add(rect1)
// rect1.on('mouseover', function() {
// // rect1.set({ fill: 'green' }); // 鼠标移入时改变颜色为绿色
// // canvas.renderAll(); // 重新渲染画布
// });
// // 为矩形添加 mouseleave 事件
// rect1.on('mouseout', function() {
// // rect1.set({ fill: 'blue' }); // 鼠标移出时恢复颜色为蓝色
// // canvas.renderAll(); // 重新渲染画布
// });
// return
// rect1.filters.push(new fabric.Image.filters.Grayscale())
// MyCanvas?.[this.id].add(rect1)
// // MyCanvas?.[this.id].add(rect1)
// let rect = new fabric.Rect({
// left: 0,
// top: 0,
// width: MyCanvas?.[this.id].width,
// height: MyCanvas?.[this.id].height,
// inverted:true,
// fill: "red",
// });
// // let rect2 = new fabric.Rect({
// // width: MyCanvas?.[this.id].width,
// // height: MyCanvas?.[this.id].height,
// // fill:'#FFF'
// // });
// // // MyCanvas?.[this.id].add(rect2)
// fabric.Image.fromURL('https://www.minio.aida.com.hk:12024/aida-collection-element/83/Moodboard/7a5fec0f-5a8c-4f1e-80c0-c4cda335d7c5.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20241112%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20241112T060752Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=25c5fa23dc447d1d06b4efeeec23454c797219df9c45d2cec231d0c8372754ce',(img)=>{
// let scale = {
// X:MyCanvas?.[this.id].width/img.width,
// Y:MyCanvas?.[this.id].height/img.height
// }
// rect.set({
// fill: new fabric.Pattern({
// source: img.getElement(), // 传入图片元素
// repeat: 'no-repeat' // 设置图片不重复
// }),
// clipPath : rect1
// })
// img.set({
// scaleX:scale.X,
// scaleY:scale.Y,
// left:0,
// top:0,
// })
// MyCanvas?.[this.id].add(rect)
// },{ crossOrigin: "Anonymous" })
// // // MyCanvas?.[this.id].add(rect1)
// // // rect1.clipPath = group
// // // MyCanvas?.[this.id].forEachObject((item) =>{
// // // if(item.clipPath){
// // // item.clipPath.add(rect2)
// // // // item.clipPath = group
// // // }
// // // })
// return
MyCanvas?.[this.id].on("mouse:move", this.setCanvasMove.bind(this));
MyCanvas?.[this.id].on("mouse:down",this.setCanvasDown.bind(this));
MyCanvas?.[this.id].on("mouse:up",this.setCanvasUp.bind(this));
MyCanvas?.[this.id].on("mouse:wheel",this.setCanvasWheel.bind(this));
//双击
MyCanvas?.[this.id].on("mouse:dblclick", event=>{
if(this.operation == 'fold'){
this.foldEnd('Enter')
}
});
document.addEventListener('mousemove', this.mouseMove.bind(this));
document.addEventListener('touchmove', this.touchmove.bind(this));
document.addEventListener("keydown", this.canvasKeyDown);
document.addEventListener("keyup", this.canvasKeyUp);
initAligningGuidelines(MyCanvas?.[this.id], true);
JSchangeType(MyCanvas?.[this.id],'init')
// await this.createBg()
await this.createLayer({str:'init',img:img,noErasable:data?.noErasable || false})//创建图层并且使用
if(img && editGroupImg){
this.dashed.isDetail = true
await this.createLayer({editImg:editGroupImg,noErasable:data?.noErasable || false})//创建图层并且使用
}
MyCanvas?.[this.id].on("object:added", this.addLayer.bind(this));
// MyCanvas?.[this.id].on("object:added", this.addLayer.bind(this));
this.canvas = MyCanvas?.[this.id];
return MyCanvas?.[this.id]
}
initCanvasWH(str){
let scale
if(this.canvasWH.width>this.canvasWH.height)scale = this.canvasDomParent.offsetWidth / this.canvasWH.width
if(this.canvasWH.width<this.canvasWH.height)scale = this.canvasDomParent.offsetHeight / this.canvasWH.height
if(this.canvasWH.width == this.canvasWH.height)scale = this.canvasDomParent.offsetWidth / this.canvasWH.width
let x = this.canvasWH.width / 2
let y = this.canvasWH.height / 2
if(str == 'updata'){
x = 0
y = 0
const vpt = MyCanvas?.[this.id].viewportTransform;
vpt[4] = 0; // 更新水平偏移
vpt[5] = 0; // 更新垂直偏移
}
MyCanvas?.[this.id].zoomToPoint(
{ // 关键点
x: x,
y: y
},
scale
)
MyCanvas?.[this.id].setBackgroundColor({
source:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC',
repeat: 'repeat',
},MyCanvas?.[this.id].renderAll.bind(MyCanvas?.[this.id]),
)
}
mouseMove(event){
let e = getMousePosition(event,false)
this.setDomMove(e)
}
touchmove(event){
let e = getMousePosition(event,true)
this.setDomMove(e)
}
setDomMove(event){
let canvasCenterBox = this.canvasDomParent;
if(!canvasCenterBox)return
let parentX = event.clientX - canvasCenterBox.getBoundingClientRect().left
let parentY = event.clientY - canvasCenterBox.getBoundingClientRect().top
this.pencilbtnStyle.left = parentX + "px"
this.pencilbtnStyle.top = parentY+'px'
}
//设置操作
setOperation(str){
this.operation = str
MyCanvas?.[this.id].discardActiveObject();//取消所有选中边框
if(this.createPatterning.state){
MyCanvas?.[this.id].remove(this.createPatterning.current)
}
this.removeSetText()
initAligningGuidelines(MyCanvas?.[this.id],false)
MyCanvas?.[this.id].remove(this.createPatterning.polyLineBtn)
if(str == 'pencil'){
this.setPencil()
this.pencilbtnStyle.display = `block`
this.setCursor('none');
MyCanvas[this.id].freeDrawingCursor = 'none'
}else if(str == 'move'){
JSchangeType(MyCanvas?.[this.id],'')
MyCanvas[this.id].isDrawingMode = false
this.pencilbtnStyle.display = `none`
this.setCursor('grab');
}else if(str == 'movePosition'){
JSchangeType(MyCanvas?.[this.id],'init')
initAligningGuidelines(MyCanvas?.[this.id],true)
this.setMove()
this.pencilbtnStyle.display = `none`
this.setCursor('all-scroll');
MyCanvas[this.id].isDrawingMode = false
}else if(str == 'texture'){
this.setTexture()
this.pencilbtnStyle.display = `block`
MyCanvas[this.id].freeDrawingCursor = 'none'
this.setCursor('none');
}else if(str == 'eraser'){
this.setEraser()
this.pencilbtnStyle.display = `block`
MyCanvas[this.id].freeDrawingCursor = 'none'
this.setCursor('none');
}else if(str == 'text'){
this.setMove()
this.setText()
JSchangeType(MyCanvas?.[this.id],'init')
this.setCursor('text')
this.pencilbtnStyle.display = `none`
}else if(['zoomIn', 'zoomOut'].includes(str)){
this.pencilbtnStyle.display = `none`
if(str == 'zoomIn')this.setCursor('zoom-in');
if(str == 'zoomOut')this.setCursor('zoom-out');
MyCanvas[this.id].isDrawingMode = false
MyCanvas?.[this.id].forEachObject((obj) =>{
if(obj.type != 'group' && !obj.isType('path')){
obj.selectable = false
}
});
}else if(['dashedPencil', 'dashed'].includes(str)){
this.dashed.isDashedShow = false
this.setGroupGrid('all')
MyCanvas[this.id].isDrawingMode = false
this.pencilbtnStyle.display = `none`
this.setCursor('crosshair')
MyCanvas[this.id].freeDrawingCursor = 'crosshair'
if(str == 'dashedPencil')this.setDashedPencil()
MyCanvas?.[this.id].forEachObject((obj) =>{
if(obj.type != 'group' && !obj.isType('path')){
obj.selectable = false
}
});
}else if(str){
this.pencilbtnStyle.display = `none`
this.setCursor('auto');
MyCanvas[this.id].isDrawingMode = false
MyCanvas?.[this.id].forEachObject((obj) =>{
if(obj.type != 'group' && !obj.isType('path')){
obj.selectable = false
}
});
}
if(str == 'dashed' || str == 'dashedPencil'){
// if(str == 'dashed' || str == 'dashedPencil' || str != 'movePosition'){
if(this.layer.selectLayer.group.custom.groupType == 'Grid')this.setGroupGrid('all')
this.clipPath = {
isImg:false,
clipGroup:null,
img:null,
}
}
}
setCursor(str){
MyCanvas[this.id].defaultCursor = str;
MyCanvas[this.id].moveCursor = str;
MyCanvas[this.id].hoverCursor = str;
MyCanvas[this.id].upperCanvasEl.style.cursor = str;
}
setCanvasMove = (event)=>{
if(this.mouse.isMovePostion && this.operation == 'move') return this.setCanvasPosition(event)
if(MyCanvas?.[this.id].isDrawingMode){
}else{
let getActiveObject = MyCanvas?.[this.id].getActiveObject()
if(
!this.clipPath.isImg &&
this.mouse.isDown &&
getActiveObject &&
getActiveObject.custom?.dashed &&
this.layer.selectLayer.group.custom?.groupType == 'Grid' &&
this.operation == 'movePosition'
){
this.setclipPathImg()
}
if(this.createPatterning.state){
let str = this.operation
if(this.operation == 'dashed')str = 'rect'
JScanvasMouseMove(str,event,this.createPatterning.current,this.mouse.point,this.keyboard.down)
MyCanvas?.[this.id].requestRenderAll()
}
}
}
setCanvasPosition(event){
const e = event;
const vpt = MyCanvas?.[this.id].viewportTransform;
vpt[4] += e.pointer.x - this.mouse.lastPosX; // 更新水平偏移
vpt[5] += e.pointer.y - this.mouse.lastPosY; // 更新垂直偏移
MyCanvas?.[this.id].requestRenderAll(); // 请求重绘画布
this.mouse.lastPosX = e.pointer.x;
this.mouse.lastPosY = e.pointer.y;
}
// setRemoveDashed(){
// MyCanvas?.[this.id].forEachObject((obj) =>{
// if(obj.custom.dashed && obj._objects){
// let rect = obj._objects.filter(item => item.type == 'rect')[0]
// obj.remove(rect)
// MyCanvas?.[this.id].renderAll();
// }
// });
// }
//设置再画布上按下
setCanvasDown(event){
if(event.target && event.target.custom?.dashed && ['dashedPencil', 'dashed'].includes(this.operation) && !this.dashed.isDetail){
// if(MyCanvas?.[this.id].isDrawingMode){
// MyCanvas[this.id].isDrawingMode = false;
// }
this.dashed.state = true
}else if(!event.target?.custom?.dashed){
// if(['dashedPencil'].includes(this.operation)){
// MyCanvas[this.id].isDrawingMode = true;
// }
this.dashed.state = false
}
let dashedGroup = MyCanvas?.[this.id].getObjects().filter(obj => obj?.custom?.dashed)[0];
if(this.dashed.state && (this.operation == 'dashed' || this.operation == 'dashedPencil') && dashedGroup)return
if(!this.dashed.state && (!event.target?.custom?.dashed || this.dashed.isDetail) && (this.operation == 'dashed' || this.operation == 'dashedPencil') && dashedGroup){
MyCanvas?.[this.id].remove(dashedGroup)
}
if(this.operation == 'movePosition' && !event?.target?.custom?.dashed && this.layer.selectLayer.group?.custom?.groupType == 'Grid')this.setGroupGrid('all');
//设置移动端按下添加元素
this.mouse.isDown = true
this.mouse.lastPosX = event.pointer.x;
this.mouse.lastPosY = event.pointer.y;
if(this.operation == 'move'){
this.mouse.isMovePostion = true;
this.setCursor('grabbing');
return
}
if(this.operation == 'zoomIn' || this.operation == 'zoomOut'){
this.setCanvasZoom(event)
return
}
// this.setRemoveDashed()
if(this.addPresent.upScaleChecked){//创建元素
this.present.upScaleChecked = false
this.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
default :
createImage(pointerVpt.y, pointerVpt.x,currentType.value.type)
break
}
// 创建完元素,把当前操作的元素类型设置回 null
currentType.value.type = null
currentType.value.data = null
}
this.mouse.point = event.absolutePointer
let arr = ['rect','line','circle','triangle','ellipse','fold','dashed']
if(arr.indexOf(this.operation) > -1){
JSchangeType(MyCanvas?.[this.id],this.operation)
this.createPatterning.state = true
MyCanvas?.[this.id].forEachObject((obj) =>{
obj.set('selectable', false); // 禁用选中
});
if(this.createPatterning.current && this.operation == 'fold'){
MyCanvas[this.id].skipTargetFind = false
this.createPatterning.current.points.push({
x: this.mouse.point.x,
y: this.mouse.point.y
})
}else{
let width = this.brushwork.width[this.operation]?this.brushwork.width[this.operation]:20
let data = {
str:this.operation,
width,
selectable:true,
}
if(this.operation == 'dashed'){
width = 1 / MyCanvas?.[this.id].getZoom()
data = {
fill:'transparent',
strokeDashArray: [width*3, width*3],
width,
radius:0,
str:'rect',
selectable:true,
}
}else if(this.operation == 'rect'){
data.width = 0
}
this.createPatterning.current = JScanvasMouseDown(event,data)
if(this.operation == 'dashed')this.createPatterning.current.set({custom:{dashed:true}})
MyCanvas?.[this.id].add(this.createPatterning.current)
if(this.operation == 'fold'){
this.createPatterning.polyLineBtn = JScreateCheck(event)
this.createPatterning.polyLineBtn.on('mousedown',this.foldEnd.bind(this))
MyCanvas?.[this.id].add(this.createPatterning.polyLineBtn)
}
}
}else{
// var clickedObject = event.target;
// if (clickedObject instanceof fabric.Textbox && this.operation != 'text') {
// this.createPatterning.textDataShow = true
// this.createText = clickedObject
// console.log(1);
// }else{
// console.log(2);
// this.createPatterning.textDataShow = false
// this.createText = {}
// }
// this.createPatterning.state = false
}
}
setTextData(obj){
this.fontFamily = obj.fontFamily
this.brushwork.width['text'] = obj.fontSize
this.brushwork.color = obj.fill
}
async setCanvasUp(event){
this.mouse.isDown = false
if(this.mouse.isMovePostion){
this.mouse.isMovePostion = false
this.setCursor('grab');
return
}
if(this.operation == 'eraser')return this.updataLayer()
this.mouse.upPoint = event.absolutePointer
if(MyCanvas?.[this.id].isDrawingMode){
setTimeout(() => {
// pencilbtnStyle.value.display = `none`
this.updateCanvasState()
}, 100);
}else{
// event.target && (event.target.bringToFront())//设置优先级
}
if(this.createPatterning.state){
switch (this.operation) {
case 'line':
this.createPatterning.current.set({stroke: this.brushwork.color})
break
case 'fold':
// this.createPatterning.current.set({stroke: this.brushwork.color})
break
default :
if(JSON.stringify(this.mouse.point) == JSON.stringify(this.mouse.upPoint)){
MyCanvas?.[this.id].remove(this.createPatterning.current)
return
}
if(this.operation == 'dashed'){
this.createPatterning.current.set({fill: 'transparent'})
}else if(this.operationMode == 'fill'){
this.createPatterning.current.set({fill: this.brushwork.color})
}else if (this.operationMode == 'border'){
this.createPatterning.current.set({fill: 'transparent',stroke: this.brushwork.color,strokeWidth: this.brushwork.width[this.operation]?this.brushwork.width[this.operation]:20})
}
break
}
if(this.operation == 'fold'){
MyCanvas?.[this.id].forEachObject((obj) =>{
if(this.isSelectable(obj.target)){
obj.selectable = true
}else{
obj.selectable = false
}
});
MyCanvas?.[this.id].bringToFront(this.createPatterning.polyLineBtn);//设置优先级最高
}else if(this.operation){
this.createPatterning.state = false
MyCanvas?.[this.id].renderAll();
if(this.operation == 'dashed'){
await this.setDashed(this.createPatterning.current)
}else{
this.addLayer({target:this.createPatterning?.current})
this.setOperation('movePosition')
}
this.clearPatterning()//临时图形置为空并且添加撤回对象里面
}
}
}
async setclipPathImg(){//裁剪图片
if(!this.clipPath.clipGroup)return
this.clipPath.isImg = true
let clipPathElement = this.clipPath.clipGroup._objects.filter(obj => obj.custom)[0]
let imgBG = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.isSelectable && obj.type == 'rect')[0];
let position = {
left:this.clipPath.clipGroup?.left - (imgBG.left?imgBG.left:0),
top:this.clipPath.clipGroup?.top - (imgBG.top?imgBG.top:0),
width:this.clipPath.clipGroup?.width,
height:this.clipPath.clipGroup?.height,
}
// await this.setGroupGrid()
//添加裁剪后的图片
let elements = MyCanvas?.[this.id].getObjects().filter(obj => this.isAddToLayer(obj));
let imgData = await this.groupToImg(elements,position,'clipPath')
let img = await this.createImage({minioUrl:imgData})
img.set({
scaleX:1,
scaleY:1,
left:0 - position.width/2,
top:0 - position.height/2,
})
img.clipPath = clipPathElement
this.clipPath.clipGroup.insertAt(img)
//裁剪
this.layer.selectLayer.group.custom.groupType = 'Grid'
clipPathElement.clone(cloned=>{
cloned.set({left:position.left,top:position.top,strokeWidth:0})
if(imgBG?.custom?.state != 'success')this.setClipPath(imgBG,cloned)
})
}
setDashedPencil(){
MyCanvas[this.id].isDrawingMode = true
let pencil = new fabric.Test(MyCanvas?.[this.id],{}); //普通笔
MyCanvas[this.id].freeDrawingBrush = pencil
}
async setDashed(obj){
MyCanvas?.[this.id].remove(obj)
let position = {
left:obj.left,
top:obj.top,
width:obj.width,
height:obj.height,
}
await obj.clone((cloned)=>{
let {width,height,left,top} = position
cloned.set({
custom:{
dashed:true
}
})
// cloned.set({left:cloned.strokeWidth/2,top:cloned.strokeWidth/2})
let group = new fabric.Group([cloned],{
left:left + cloned.strokeWidth/2,
top:top + cloned.strokeWidth/2,
width,height,
custom:{
dashed:true
}
})
MyCanvas?.[this.id].add(group)
})
}
async setGridOrObject(id,str){
this.layer.list.forEach((item) => {
if(item.id == id)item.groupType = str
})
await this.lookingLayer(id).then(rv=>{
rv.custom.groupType = str
})
if(str == 'Grid'){
await this.setGroupGrid()
}else{
await this.setGroupGrid('all')
}
this.setOperation('movePosition')
}
// 复制图层
async copyLayer(id){
let createId = new Date().getTime()
let elements = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.layerId == id)
for (let i = 0; i < elements.length; i++) {
await new Promise((resolve, reject) => {
let item = elements[i]
item.clone((clonedObj)=>{
this.setClone(item,clonedObj)
clonedObj.custom.layerId = createId
copyElements.push(clonedObj)
resolve('')
})
})
}
await this.createLayer({id:createId})
copyElements.forEach( item=>MyCanvas?.[this.id].add(item))
}
async setGroupGrid(str){//group变为图片
// MyCanvas?.[this.id].discardActiveObject();//取消所有选中边框
let elements = MyCanvas?.[this.id].getObjects().filter(obj => this.isAddToLayer(obj) && !obj.custom.dashed && obj.type);
if(str == 'all'){
elements = MyCanvas?.[this.id].getObjects().filter(obj => this.isAddToLayer(obj) && obj.type);
}
let layerBg = elements.filter(obj => obj.custom.isSelectable)[0]
let scaleXY = {
scaleX:layerBg?.scaleX?layerBg?.scaleX:1,
scaleY:layerBg?.scaleY?layerBg?.scaleY:1,
width:layerBg?.width?layerBg?.width:MyCanvas?.[this.id].width,
height:layerBg?.height?layerBg?.height:MyCanvas?.[this.id].height,
}
let imgData = await this.groupToImg(elements,{},'setGrid',scaleXY)
let img = await this.createImage({minioUrl:imgData})
elements.forEach((obj) =>{
if(obj.custom.isSelectable){
}else{
MyCanvas?.[this.id].remove(obj)
}
});
if(layerBg){
layerBg.custom.state = ''
delete layerBg.eraser
layerBg.set({
scaleX:1,
scaleY:1,
width: scaleXY.width * scaleXY.scaleX,
height: scaleXY.height * scaleXY.scaleY,
clipPath:null,
fill: new fabric.Pattern({
source: img.getElement(), // 传入图片元素
repeat: 'no-repeat' // 设置图片不重复
}),
hasBorders: true,
hasControls: true
})
this.setGroupStyle(layerBg)
}else{
const rect = new fabric.Rect({
// left:0,
// top:0,
width: MyCanvas?.[this.id].width,
height: MyCanvas?.[this.id].height,
strokeWidth:0,
fill: new fabric.Pattern({
source: img.getElement(), // 传入图片元素
repeat: 'no-repeat' // 设置图片不重复
}),
custom:{
isSelectable:true,
},
hasBorders: true,
hasControls: true
});
this.setGroupStyle(rect)
MyCanvas?.[this.id].add(rect)
}
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
}
//液化
getLiquefactionImgObj(){
return new Promise(async (resolve, reject) => {
let img,str = null
const activeObject = MyCanvas?.[this.id].getActiveObject(); // 获取选中的对象
let dashedGroup = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.dashed)[0];
if (activeObject && activeObject.type === 'image' &&
activeObject.custom.type == 'upImgFiles'
){
img = activeObject
this.liquefaction.type = 'upImgFiles'
}else if(dashedGroup){//判断选取是否存在
if(
dashedGroup._objects.filter(item => item.type == 'image').length == 0 &&
this.layer.selectLayer.group.custom.groupType == 'Grid'
){
await this.setclipPathImg()
}else if(dashedGroup._objects.filter(item => item.type == 'image').length == 0){
resolve()
return
}
await new Promise((resolve, reject) => {
dashedGroup.clone(async (cloned)=>{
this.setClone(dashedGroup,cloned)
this.liquefaction.dashed = dashedGroup
this.liquefaction.type = 'dashed'
cloned._objects = cloned._objects.filter(item => item.type == 'image')
img = await cloned.toDataURL()
resolve()
})
})
}else if(this.layer.selectLayer.group.custom.groupType == 'Grid'){//判断当前图层是否可以做为液化图片
let bg = MyCanvas?.[this.id].getObjects().filter(item => item.custom?.isSelectable)[0]
img = bg.fill.source.src
this.liquefaction.type = 'layer'
}
this.liquefaction.img = img
resolve(this.liquefaction)
})
}
async setLiquefactionImgObj(liquefaction,data){
if(liquefaction.type == 'upImgFiles'){
await new Promise((resolve, reject) => {
liquefaction.img.setSrc(data, (value)=>{
delete liquefaction.img.minioUrl
resolve()
})
})
}else if(liquefaction.type == 'dashed'){
if(liquefaction.dashed){
await new Promise((resolve, reject) => {
liquefaction.dashed._objects = liquefaction.dashed._objects.filter(item => item.type != 'image')
fabric.Image.fromURL(data, (value)=>{
value.set({
left:-liquefaction.dashed.width/2,
top:-liquefaction.dashed.height/2,
})
liquefaction.dashed.insertAt(value)
resolve()
})
})
// canvasObj.addDashedImg(value)
}
}else if(liquefaction.type == 'layer'){
let bg = MyCanvas?.[this.id].getObjects().filter(item => item.custom?.isSelectable)[0]
let img = await this.createImage({minioUrl:data})
bg.set({
fill: new fabric.Pattern({
source: img.getElement(), // 传入图片元素
repeat: 'no-repeat' // 设置图片不重复
}),
})
}
MyCanvas?.[this.id].renderAll();
this.updateCanvasState()
}
//end液化
setGroupStyle(obj){
obj.set({
borderColor:'#4584ff',
cornerStrokeColor :'#4584ff',
cornerStyle:'circle'
})
obj.setControlsVisibility({
mtr:false,
deleteControl:false
})
// obj.controls.deleteControl.mouseUpHandler = null
}
setClipPath(img,clipPath){
let imgScale = {
pX:(img?.scaleX?img.scaleX:1),
pY:(img?.scaleY?img.scaleY:1),
}
clipPath.set({
left: clipPath.left - img.width*imgScale.pX/2,
top: clipPath.top - img.height*imgScale.pY/2,
inverted:true,
})
img.set({clipPath:clipPath})
img.custom.state = 'success'
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
}
async groupToImg(elements,imgData,type,scaleXY){
let temporar = this.temporarilyExport(scaleXY)
let bg = elements.filter(item => item.custom?.isSelectable)[0]
let xy = {
x:bg?.left?bg?.left:0,
y:bg?.top?bg?.top:0,
}
for (let index = 0; index < elements.length; index++) {
const item = elements[index];
await new Promise((resolve, reject) => {
item.clone((cloned)=>{
this.setClone(item,cloned)
if(item.custom?.dashed && item._objects){
cloned._objects = cloned._objects.filter(item => item.type == 'image')
}
// if(type == 'setGrid'){
cloned.set({
left: cloned.left - xy.x,
top: cloned.top - xy.y,
})
// }
if(cloned.custom?.layerId != -1){
temporar.add(cloned)
}
resolve()
})
})
}
let data = await temporar.toDataURL(imgData);
this.closeTemporarilyExport(temporar)
return data
}
setCanvasWheel(opt){
const delta = opt.e.deltaY // 滚轮,向上滚一下是 -100向下滚一下是 100
let zoom = MyCanvas?.[this.id].getZoom() // 获取画布当前缩放值
zoom *= 0.999 ** delta
if (zoom > 20) zoom = 20
if (zoom < 0.01) zoom = 0.01
MyCanvas?.[this.id].zoomToPoint(
{ // 关键点
x: opt.e.offsetX,
y: opt.e.offsetY
},
zoom
)
opt.e.preventDefault()
opt.e.stopPropagation()
this.setPencilWidth()
}
foldEnd(key){
MyCanvas[this.id].skipTargetFind = true
let points = this.createPatterning.current.points
if(key == 'Enter'){
}else{
points.pop()
}
points.pop()
this.createPatterning.state = false
MyCanvas?.[this.id].remove(this.createPatterning.current)
MyCanvas?.[this.id].remove(this.createPatterning.polyLineBtn)
let polyline = new fabric.Polyline(points, {
fill: this.operationMode == 'fill'? this.brushwork.color : 'transparent',
stroke: this.brushwork.color,
strokeWidth:this.brushwork.width[this.operation]?this.brushwork.width[this.operation]:20,
// selection:false,
})
polyline.set({
left:polyline.left+polyline.strokeWidth / 2,
top:polyline.top+polyline.strokeWidth / 2,
})
MyCanvas?.[this.id].add(polyline)
this.clearPatterning()//临时图形置为空并且添加撤回对象里面
// this.layerAddElement(polyline)
}
clearPatterning(){
if(this.createPatterning.state){
MyCanvas?.[this.id].remove(this.createPatterning.current)
}
this.createPatterning.current = null
MyCanvas?.[this.id].remove(this.createPatterning.polyLineBtn)
this.updateCanvasState()
}
textureValueChange = (value)=>{
this.texture.value = value
this.setTexture()
}
setOperationMode(str){
this.operationMode = str
}
brushworkChange = (value)=>{
this.brushwork.value = value
this.setPencil()
}
setLayerIndex(str){//设置优先级
var activeObject = MyCanvas?.[this.id].getActiveObject();
switch (str) {
case 'Front':
MyCanvas?.[this.id].bringToFront(activeObject)//顶层
// this.layer.selectLayer.group.bringToFront(activeObject)
break
case 'Back':
MyCanvas?.[this.id].sendToBack(activeObject)//底层
// this.layer.selectLayer.group.sendToBack(activeObject)
break
case 'Forward':
MyCanvas?.[this.id].bringForward(activeObject)
// this.layer.selectLayer.group.bringForward(activeObject)
break
case 'Backwards':
MyCanvas?.[this.id].sendBackwards(activeObject)
// this.layer.selectLayer.group.sendBackwards(activeObject)
break
}
}
setPencil(){
let pencil
MyCanvas[this.id].isDrawingMode = true//开启绘画模式
if(this.brushwork.value == 'PencilBrush'){
pencil = new fabric.PencilBrush(MyCanvas?.[this.id],{}); //普通笔
}else if(this.brushwork.value == 'Marking'){
pencil = new fabric.PencilBrush(MyCanvas?.[this.id],); //记号笔
}else if(this.brushwork.value == 'InkBrush'){
pencil = new fabric.InkBrush(MyCanvas?.[this.id],{}); //油画笔
}else if(this.brushwork.value=='CrayonBrush'){
pencil = new fabric.CrayonBrush(MyCanvas?.[this.id],{}); //蜡笔
}else if(this.brushwork.value == 'RibbonBrush'){
pencil = new fabric.RibbonBrush(MyCanvas?.[this.id],{width: 1,}); //色带
}else if(this.brushwork.value == 'MarkerBrush'){
pencil = new fabric.MarkerBrush(MyCanvas?.[this.id],{}); //书写笔
// pencil = new fabric.PenBrush(MyCanvas?.[this.id],{}); //书写笔
}else if(this.brushwork.value == 'WritingBrush'){
pencil = new fabric.WritingBrush(MyCanvas?.[this.id],{}); //毛笔
}else if(this.brushwork.value == 'LongfurBrush'){
pencil = new fabric.LongfurBrush(MyCanvas?.[this.id],{width: 1,}); //色带
}else if(this.brushwork.value == 'SpraypaintBrush'){
pencil = new fabric.SpraypaintBrush(MyCanvas?.[this.id],{}); //长毛刷
}
MyCanvas[this.id].freeDrawingBrush = pencil
if(this.brushwork.value == 'RibbonBrush' || this.brushwork.value == 'LongfurBrush'){
MyCanvas[this.id].freeDrawingBrush.width = 1;
}
if(this.brushwork.value == 'Marking'){
MyCanvas[this.id].freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.5);
// }else if(this.brushwork.value == 'InkBrush'){
// canvas.freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.2);
}else{
MyCanvas[this.id].freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,1);
}
this.setPencilWidth()
this.pencilbtnStyle.background = this.brushwork.color
MyCanvas[this.id].freeDrawingBrush.isEraser = false
}
setCanvasZoom(opt){
let zoom = MyCanvas?.[this.id].getZoom() // 获取画布当前缩放值
let num = -100
if(this.operation == 'zoomOut') num = 100
zoom *= 0.999 ** num
if (zoom > 20) zoom = 20
if (zoom < 0.01) zoom = 0.01
// MyCanvas?.[this.id].setDimensions(MyCanvas?.[this.id].width *= zoom,MyCanvas?.[this.id].height *= zoom)
// MyCanvas?.[this.id].wrapperEl.style.zoom = zoom
MyCanvas?.[this.id].zoomToPoint(
{ // 关键点
x: opt.pointer.x,
y: opt.pointer.y
},
zoom
)
opt.e.preventDefault()
opt.e.stopPropagation()
this.setPencilWidth()
}
async addImage (imgData){
let img = await this.createImage(imgData)
let position = {
// left: 0,
// top:MyCanvas?.[this.id].wrapperEl.parentNode.scrollTop,
left: MyCanvas?.[this.id].width/2,
top: MyCanvas?.[this.id].height/2,
}
img.set({
custom:{
type:'upImgFiles',
// minioUrl:getMinioUrl(imgData.url)
},
})
if(this.dashed.isDetail)await this.createLayer({})
this.setCanvasImage(img,position,"upImgFiles",imgData)
}
createImage(imgData){
return new Promise((resolve, reject) => {
console.log(imgData)
fabric.Image.fromURL(imgData.minioUrl,(img) => {
img.set({
hasControls: true,
})
img.minioUrl=getMinioUrl(imgData.minioUrl || imgData.imgUrl)
resolve(img)
},{ crossOrigin: "Anonymous" })
})
}
setImageWidth = (key,img)=>{
const CW = MyCanvas?.[this.id].width
const CH = MyCanvas?.[this.id].height
let WH = CW>CH?'H':'W'
let imgWidth; //这是设置画布等宽
if(WH == 'W'){
imgWidth = CW / 2;
}else{
let heightScale = (CH/2) / img.height
imgWidth = img.width * heightScale
}
// let sketchGrouping = 6
// if(key == 'upImgFiles'){
// imgWidth = imgWidth / 8;
// }else if (key == "printboardFiles") {
// imgWidth = imgWidth / 14;
// }else if (key == "sketchboardFiles"||key == 'moodboardFiles'||key == 'FinalizeImage') {
// imgWidth =
// (imgWidth -
// (sketchGrouping - 1) * 20) /
// sketchGrouping;
// }else if (key == "likeDesignCollectionList") {
// if(img){
// let imgObj = JSON.parse(JSON.stringify(img))
// let height = imgObj.height
// imgObj.height = imgWidth / 8 * 1.8
// let heightScale = imgObj.height / height
// imgWidth = imgObj.width * heightScale
// }
// }else {
// if(img){
// let imgObj = JSON.parse(JSON.stringify(img))
// if(imgObj.height > imgObj.width){
// let heightScale = (MyCanvas?.[this.id].height/2) / imgObj.height
// imgWidth = imgObj.width * heightScale
// }else{
// imgWidth /= 2
// }
// }
// }
return imgWidth
}
async setCanvasImage(img,position,key,data){
let imgUrl = data.imgUrl
if (key == "likeDesignCollectionList") {
imgUrl = data.designOutfitUrl;
}
console.log(img.width , img.height,img);
let imgWidth = await this.setImageWidth(key,img);
let proportion = img.height / img.width; //计算图形宽高比例
let scaleWH = imgWidth / img.width; //计算放到画布上缩小倍率
let scale = {
X: imgWidth / img.width,
Y: (img.width * proportion * scaleWH) / img.height,
}
img.set({
left:position.left - img.width*scale.X/2,
top:position.top - img.height*scale.Y / 2,
scaleX:scale.X,
scaleY:scale.Y,
});
MyCanvas?.[this.id].add(img)
this.updateCanvasState('')
}
setMove(){
MyCanvas[this.id].isDrawingMode = false
MyCanvas?.[this.id].forEachObject((obj) =>{
if(this.isSelectable(obj)){
obj.selectable = true
}else{
obj.selectable = false
}
});
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
}
async setTexture(){
MyCanvas[this.id].isDrawingMode = true//开启绘画模式
let img = await JSSetTexture(this.texture.list[this.texture.value].url)
let zoom = MyCanvas?.[this.id].getZoom() // 获取画布当前缩放值
let patternBrush = new fabric.PatternBrush(MyCanvas?.[this.id])
patternBrush.source = img
patternBrush.width = Number(this.brushwork.width[this.operation]) / zoom; // 设置画笔大小
this.setPencilWidth()
MyCanvas[this.id].freeDrawingBrush = patternBrush
}
setEraser(){
MyCanvas[this.id].isDrawingMode = true
let eraser = new fabric.EraserBrush(MyCanvas?.[this.id])
MyCanvas[this.id].freeDrawingBrush = eraser
this.pencilbtnStyle.background = '#fff'
MyCanvas[this.id].freeDrawingBrush.isEraser = true
this.setPencilWidth()
MyCanvas?.[this.id].requestRenderAll();
}
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})`;
}
pencilColor(){
if(this.createText?.set){
this.setFontFamily()
return
}
if(MyCanvas[this.id].freeDrawingBrush.isEraser){
}else{
this.pencilbtnStyle.background = this.brushwork.color
}
if(this.brushwork.value == 'Marking'){
MyCanvas[this.id].freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.5);
}else if(this.brushwork.value == 'InkBrush'){
MyCanvas[this.id].freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.2);
}else{
MyCanvas[this.id].freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,1);
}
}
setFontFamily=()=>{
if(this.createText?.set){
this.createText.set({
fontFamily:this.fontFamily,
fontSize:this.brushwork.width[this.operation]?this.brushwork.width[this.operation]:20,
fill:this.brushwork.color,
})
MyCanvas?.[this.id].renderAll();
}
}
setPencilColor(){//切换颜色给铅笔设置颜色
clearTimeout(this.setTimeOut.color)
clearTimeout(this.setTimeOut.colorHistory)
this.setTimeOut.color = setTimeout(()=>{
this.pencilColor()
},200)
this.setTimeOut.colorHistory = setTimeout(()=>{
this.colorHistoryList.push(this.brushwork.color)
},1000)
}
setCanvasWH = (str)=>{
clearTimeout(this.setTimeOut.canvasWH)
this.setTimeOut.canvasWH = setTimeout(()=>{
MyCanvas?.[this.id].setWidth(this.canvasWH.width);
MyCanvas?.[this.id].setHeight(this.canvasWH.height);
// MyCanvas?.[this.id].width = this.canvasWH.width
// MyCanvas?.[this.id].height = this.canvasWH.height
this.initCanvasWH('updata')
},1000)
}
setColorHistory = (value)=>{
this.brushwork.color = value
this.pencilColor()
}
setPencilWidth(){//切换颜色给铅笔设置颜色
let zoom = MyCanvas?.[this.id].getZoom() // 获取画布当前缩放值
clearTimeout(this.setTimeOut.width)
this.setTimeOut.width = setTimeout(()=>{
if(!this.brushwork.width[this.operation])this.brushwork.width[this.operation]=20
// MyCanvas[this.id].freeDrawingBrush.width = Number(this.brushwork.width[this.operation]);
let arr = ['PencilBrush','Marking']
this.pencilbtnStyle.height = this.brushwork.width[this.operation]+'px'
this.pencilbtnStyle.width = this.brushwork.width[this.operation]+'px'
if(arr.indexOf(this.brushwork.value) > -1){
MyCanvas[this.id].freeDrawingBrush.width = Number(this.brushwork.width[this.operation]) / zoom;
}else{
MyCanvas[this.id].freeDrawingBrush.width = Number(this.brushwork.width[this.operation]);
}
if((this.brushwork.value == 'LongfurBrush' || this.brushwork.value == 'RibbonBrush') && this.operation == 'pencil'){
MyCanvas[this.id].freeDrawingBrush.width = 1;
this.pencilbtnStyle.height = 1+'px'
this.pencilbtnStyle.width = 1+'px'
}
},100)
}
uploadImg(){
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
// 将文件输入框和图片预览元素添加到页面中
document.body.appendChild(input);
// 监听文件输入框的变化事件
input.addEventListener('change', (event)=> {
event.preventDefault()
const file = event.target.files[0]; // 获取用户选择的文件
if (file) {
const reader = new FileReader(); // 创建 FileReader 对象读取文件
reader.onload = (e)=> {
const base64Image = e.target.result;
this.addPartImg({minioUrl:base64Image},'print')
input.remove()
};
reader.readAsDataURL(file);
}
});
input.click()
}
//关闭u或者创建文字
setTextFun(e){
if(this.operation != 'text'){
return
}
MyCanvas?.[this.id].forEachObject((obj) =>{
if(obj.type == 'textbox' && !obj.text){
MyCanvas?.[this.id].remove(obj);
}
});
var clickedObject = e.target;
if (clickedObject instanceof fabric.Textbox) {
this.createText = clickedObject
this.setTextData(this.createText)
}else{
var pointer = MyCanvas?.[this.id].getPointer(e.pointer);
var x = pointer.x;
var y = pointer.y;
this.createText = new fabric.Textbox('', {
left: x,
top: y,
width: 50,
fontSize: this.brushwork.width[this.operation]?this.brushwork.width[this.operation]:20,
fontFamily:this.fontFamily,
fill:this.canvasPencilColor,
})
MyCanvas?.[this.id].add(this.createText)
// this.layer.selectLayer.group.add(this.createText)
this.createText.enterEditing();
MyCanvas?.[this.id].setActiveObject(this.createText).renderAll();
this.removeSetText()
}
}
setText(){
MyCanvas?.[this.id].on('mouse:down',(event)=>{
if(this.operation == 'zoomIn' || this.operation == 'zoomOut'){
}else{
this.setTextFun(event)
}
})
}
removeSetText(){
MyCanvas?.[this.id].off('mouse:down',this.setTextFun.bind(this))
}
// async createBg(){//
// await new Promise((resolve, reject) => {
// let url = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC'
// fabric.Image.fromURL(url, (backgroundImage)=>{
// backgroundImage.set({
// })
// const rect = new fabric.Rect({
// left: 0,
// top: 0,
// width: MyCanvas?.[this.id].width,
// height: MyCanvas?.[this.id].height,
// fill:'#FFF',
// // fill: new fabric.Pattern({
// // source: backgroundImage.getElement(), // 使用图像元素作为填充
// // repeat: 'repeat', // 设置为重复
// // patternTransform: [this.canvasWH.width/this.canvasDomParent.offsetWidth, 0, 0, this.canvasWH.width/this.canvasDomParent.offsetWidth, 0, 0]
// // }),
// });
// const group = new fabric.Group([rect], {
// width: MyCanvas?.[this.id].width,
// height: MyCanvas?.[this.id].height,
// erasable:false,
// selectable:false,
// });
// group.custom.layerId = -1
// MyCanvas?.[this.id].add(group)
// MyCanvas?.[this.id].clipPath = rect
// resolve()
// });
// })
// }
createLayer(data){
let {str,id,editImg,noErasable} = data
let image = data.img
let canvasData = MyCanvas?.[this.id].toJSON(['selectable','minioUrl','custom']);
return new Promise(async (resolve, reject) => {
MyCanvas?.[this.id].discardActiveObject();
if(!id)id = new Date().getTime()
let index = this.layer.currentIndex += 1
const rect = new fabric.Rect({
left: -MyCanvas?.[this.id].width / 2,
top: -MyCanvas?.[this.id].height / 2,
// left:0,
// top:0,
width: MyCanvas?.[this.id].width,
height: MyCanvas?.[this.id].height,
strokeWidth:0,
fill:'#FFF',
custom:{
layerId:id,
isSelectable:true,
type:str,
},
// erasable:false,
selectable:false,
});
rect.clone((cloned)=>{
rect.clipPath = cloned
})
const group = new fabric.Group([], {
width: MyCanvas?.[this.id].width,
height: MyCanvas?.[this.id].height,
left:0,
top:0,
erasable:false,
subTargetCheck:true,
evented:false,
// originX:'left',
// originY:'top',
custom:{
noErasable:noErasable,
layerId:id,
type:'layer' ,
groupType:'Object',
layerIndex:index,
selectLayerIndex:(index) * 10000,
}
});
if(str == 'init'){
group.moveTo(group.custom.selectLayerIndex)
if(image){
let img = await this.createImage({minioUrl:image})
const scaleX = group.width / img.width; // 横向比例
const scaleY = group.height / img.height; // 纵向比例
// 选择较大的比例来保持完整图片显示,避免裁剪
const scale = Math.min(scaleX, scaleY);
const patternTransform = [
scale, 0,
0, scale,
(group.width - img.width * scale) / 2,
(group.height - img.height * scale) / 2
];
rect.set({
fill: new fabric.Pattern({
source: img.getElement(), // 传入图片元素
repeat: 'no-repeat', // 设置图片不重复
patternTransform: patternTransform
// patternTransform: [group.width / img.width, 0, 0, group.height / img.height, 0, 0]
}),
})
rect.minioUrl = getMinioUrl(image)
}
group.add(rect)
group.clone((cloned)=>{
cloned.set({left:0,top:0})
// MyCanvas?.[this.id].clipPath = cloned
})
}else if(editImg){
group.moveTo(group.custom.selectLayerIndex)
let img = await this.createImage({minioUrl:editImg})
rect.set({
fill: new fabric.Pattern({
source: img.getElement(), // 传入图片元素
repeat: 'no-repeat', // 设置图片不重复
patternTransform: [group.width / img.width, 0, 0, group.height / img.height, 0, 0]
}),
})
group.add(rect)
group.clone((cloned)=>{
cloned.set({left:0,top:0})
// MyCanvas?.[this.id].clipPath = cloned
})
}
MyCanvas?.[this.id].add(group)
let img = group.toDataURL({
width: MyCanvas?.[this.id].width,
height: MyCanvas?.[this.id].height,
})
this.layer.list.unshift({
name:`Layer${index}`,
id,img,isShow:true,
groupType:'Object',
index,})
await this.selectLayer(id)
MyCanvas?.[this.id].renderAll();
this.updateCanvasState()
resolve(group)
})
}
layerAddElement(obj){
let group = this.layer.selectLayer.group
obj.left = obj.left - group.width/2
obj.top = obj.top - group.height/2
group.add(obj)
MyCanvas?.[this.id].remove(obj)
this.updataLayerImg(this.layer.selectLayer.id,group.toDataURL({
width: MyCanvas?.[this.id].width,
height: MyCanvas?.[this.id].height
}))
}
showBg(boolen){
let Bg = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.type == 'init')?.[0];
// MyCanvas?.[this.id].getObjects().forEach((item)=>{
// console.log(item)
// })
Bg.set({visible:boolen})
// if(Bg.visible){
// Bg.set({visible:false})
// }else{
// Bg.set({visible:true})
// }
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
}
async addPartImg(file,str,data){
// let {erasable} = data
let img = await this.createImage(file)
if(str){
img.set({
custom:{
type:str
}
})
}
// let dashedGroup = MyCanvas?.[this.id].getObjects().filter(obj => obj?.custom?.dashed)[0];
// dashedGroup.clone(cloned=>{
// this.setClone(img,cloned)
// img.set({
// left:0,
// top:0
// })
// })
MyCanvas?.[this.id].add(img)
img.bringToFront();
MyCanvas?.[this.id].renderAll();
}
async addLayer(options){
if(this.createPatterning.state)return
this.clipPath.clipGroup = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom?.dashed)?.[0];
if (options.target.type === 'group' && options.target.custom?.layerId) return;
if(!options.target?.custom?.layerId,this.layer.selectLayer.id){
if(options.target?.custom){
options.target.custom.layerId = this.layer.selectLayer.id
}else{
options.target.set({custom:{layerId : this.layer.selectLayer.id}})
}
}
if(this.clipPath.clipGroup && this.dashed.isDetail && !options.target?.custom?.dashed){
let clipPathElement = this.clipPath.clipGroup._objects.filter(obj => obj.custom)[0]
clipPathElement.clone(cloned=>{
cloned.set({
left:this.clipPath.clipGroup.left,
top:this.clipPath.clipGroup.top,
absolutePositioned:true,
inverted:false,
})
if(options.target.type == 'image' && options.target.custom?.type != 'pencil'){
options.target.set({
scaleX:this.clipPath.clipGroup.width / options.target.width,
scaleY:this.clipPath.clipGroup.height / options.target.height,
left:this.clipPath.clipGroup.left,
top:this.clipPath.clipGroup.top,
// width:cloned.width,
// height:options.cloned.width / target.width * options.target.height,
})
}
options.target.clipPath = cloned
})
}else if(options.target.type == 'image' && options.target.custom?.type != 'pencil' && this.dashed.isDetail ){
console.log(123321)
let scale = 1
if(options.target?.custom?.type == 'print')scale = 2
options.target.set({
scaleX:MyCanvas?.[this.id].width / scale / options.target.width,
scaleY:MyCanvas?.[this.id].height / scale / options.target.height,
left:MyCanvas?.[this.id].width / scale - (options.target.width / scale * MyCanvas?.[this.id].width / scale / options.target.width),
top:MyCanvas?.[this.id].height / scale - (options.target.height / scale * MyCanvas?.[this.id].height / scale / options.target.height),
// width:cloned.width,
// height:options.cloned.width / target.width * options.target.height,
})
}
//判断是否可以点击空白地方进行选中
if(options.target?.custom?.dashed){
this.dashed.isDashedShow = true
options.target.set({perPixelTargetFind:false,erasable:false,hasBorders: false,hasControls: false})
if(this.dashed.isDetail){//判断是裁剪还是局部添加
options.target.set({selectable:false,perPixelTargetFind:true})
}else{
// MyCanvas?.[this.id].setActiveObject(options.target);
MyCanvas[this.id].skipTargetFind = false
}
this.setOperation('movePosition')
}else if(options.target.type == 'textbox' || options.target?.custom.type == 'layer'){
options.target.set({perPixelTargetFind:false})
}else{
options.target.set({perPixelTargetFind:true})
}
//设置优先级
if(options.target?.custom?.isSelectable && (options.target?.type == 'rect')){
options.target.custom.selectLayerIndex = this.layer.selectLayer.group.custom.layerIndex * 10000
}else{
options.target.custom.selectLayerIndex = this.layer.selectLayer.group.custom.selectLayerIndex += 1
if(this.clipPath.clipGroup){
this.clipPath.clipGroup.custom.selectLayerIndex = this.layer.selectLayer.group.custom.selectLayerIndex + 1
}
}
if(options.target.isType('path'))options.target.selectable=false
let arr = MyCanvas?.[this.id].getObjects().sort((a, b) =>{
return a.custom.selectLayerIndex - b.custom.selectLayerIndex;
});
arr.forEach((item,index)=>{
item.moveTo(index)
})
if(!options?.target?.custom?.dashed && this.layer.selectLayer.group.custom.groupType == 'Grid'){
await new Promise((resolve, reject) => {
let clipPathElement = this.clipPath.clipGroup._objects.filter(obj => obj.custom?.dashed)[0]
let clipPathLect = this.clipPath.clipGroup.left
let clipPathTop = this.clipPath.clipGroup.top
clipPathElement.clone((clipPathElementCloned)=>{
clipPathElementCloned.set({
// left:this.clipPath.clipGroup.left,
// top:this.clipPath.clipGroup.top,
left:clipPathLect,
top:clipPathTop,
absolutePositioned:true,
})
let optionLect = (options.target.left - this.clipPath.clipGroup.left) - this.clipPath.clipGroup.width/2
let optionTop = (options.target.top - this.clipPath.clipGroup.top) - this.clipPath.clipGroup.height/2
options.target.clone((cloned)=>{
cloned.set({
left:optionLect,
top:optionTop,
clipPath:clipPathElementCloned,
})
this.clipPath.clipGroup.add(cloned)
MyCanvas?.[this.id].remove(options.target)
resolve()
})
})
})
// this.setGroupGrid('all')
}
MyCanvas?.[this.id].renderAll();
this.updataLayer()
}
upLayerIndex(list){
list.forEach((item,index)=>{
let arr = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.layerId == item.id)
arr.forEach((obj)=>{
if(obj.custom.type == 'layer')obj.custom.layerIndex = item.index
let selectLayerIndex = obj.custom.selectLayerIndex+''
selectLayerIndex = selectLayerIndex.replace(/^\d/, item.index);
obj.custom.selectLayerIndex = Number(selectLayerIndex)
})
// arrList.unshift(obj)
})
// this.layer.list = arrList
let arr = MyCanvas?.[this.id].getObjects().sort((a, b) =>{
return a.custom.selectLayerIndex - b.custom.selectLayerIndex;
});
arr.forEach((item,index)=>item.moveTo(index))
}
updataLayer(){
clearTimeout(this.setTimeOut.updataLayer)
this.setTimeOut.updataLayer = setTimeout(async()=>{
let elements
elements = MyCanvas?.[this.id].getObjects().filter(obj => {
return this.isAddToLayer(obj)
});
const group = new fabric.Group([], {
width: this.layer.selectLayer.group.width,
height: this.layer.selectLayer.group.height,
erasable:false,
selectable:false,
});
for (let i = 0; i < elements.length; i++) {
await new Promise((resolve, reject) => {
let item = elements[i]
item.clone((clonedObj)=>{
this.setClone(item,clonedObj)
clonedObj.left = clonedObj.left - this.layer.selectLayer.group.width/2
clonedObj.top = clonedObj.top - this.layer.selectLayer.group.height/2
if(clonedObj.custom?.dashed){
let clipPath = clonedObj._objects.filter(item => item.type != 'image')[0]
clonedObj.remove(clipPath)
}
group.add(clonedObj)
resolve('')
})
})
}
this.updataLayerImg(this.layer.selectLayer.id,group.toDataURL({
width: this.layer.selectLayer.group.width,
height: this.layer.selectLayer.group.height
})
)
},500)
}
updataLayerImg(id,img){
this.layer.list.forEach(v => {
if (v.id === id) {
v.img = img
}
})
}
async layerDelete(index,id){
if(this.layer.list.length == 1)return
for (let i = index; i < this.layer.list.length; i++) {
this.layer.list[this.layer.list.length - i-1].index--
}
this.layer.list.splice(index,1)
if(id == this.layer.selectLayer.id){
MyCanvas?.[this.id].remove(this.layer.selectLayer.group)
MyCanvas?.[this.id].forEachObject((obj) =>{
if(obj.type != 'group' && obj.custom?.layerId == id){
MyCanvas?.[this.id].remove(obj)
}
});
this.layer.selectLayer.id = -1
this.selectLayer(this.layer.list[this.layer.list.length - 1].id)
}else{
let group = await this.lookingLayer(id,'setLayerIndex')
MyCanvas?.[this.id].remove(group)
}
this.updateCanvasState()
}
async selectLayer(id){
await new Promise(async (resolve, reject) => {
if(this.layer.selectLayer.id != -1){
await this.mergeGroup()
}
let group = await this.lookingLayer(id,'setRubber')
group.custom.selectLayerIndex = group.custom.layerIndex*10000
this.layer.selectLayer.group = group
this.layer.selectLayer.id = id
await this.expandGroup()
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
this.setOperation('movePosition')
resolve('')
})
}
async mergeGroup(){
const elements = MyCanvas?.[this.id].getObjects().filter(obj => this.isAddToLayer(obj));
let isClipPath = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom?.dashed);
if(isClipPath.length>0)await this.setGroupGrid('all')
let group = await this.lookingLayer(this.layer.selectLayer.id,'setlayerIndex')
group.set({visible:true})
for (let index = 0; index < elements.length; index++) {
const item = elements[index];
await new Promise((resolve, reject) => {
item.clone((v)=>{
this.setClone(item,v)
v.left = v.left - group.width/2
v.top = v.top - group.height/2
if(v.custom?.dashed){
// MyCanvas?.[this.id].remove(item)
// let img = v._objects.filter(item => item.type == 'image')[0]
// if(img){
// img.set({
// left:v.left,
// top:v.top,
// custom:{
// layerId:v.custom.layerId
// }
// })
// group.add(img)
// }
}else{
group.add(v)
}
resolve('')
})
})
}
elements.forEach(v => MyCanvas?.[this.id].remove(v))
}
async expandGroup(){
const elements = this.layer.selectLayer.group._objects.filter(obj => this.isAddToLayer(obj));
// fabric.util.enlivenObjects(elements, (clonedObjects) => {
this.layer.selectLayer.group.set({visible:false})
for (let index = 0; index < elements.length; index++) {
const item = elements[index];
await new Promise((resolve, reject) => {
item.clone((v)=>{
this.setClone(item,v)
v.left = v.left + this.layer.selectLayer.group.width/2
v.top = v.top + this.layer.selectLayer.group.height/2
if(v.custom?.isSelectable && this.layer.selectLayer.group.custom.noErasable){
v.set({
erasable:false
})
}
if(v.custom?.dashed){
// this.layer.selectLayer.group._objects.remove(item)
// let img = v._objects.filter(item => item.type == 'image')[0]
// if(img){
// img.set({
// left:v.left,
// top:v.top,
// custom:{
// layerId:v.custom.layerId
// }
// })
// MyCanvas?.[this.id].add(img)
// }
}else{
MyCanvas?.[this.id].add(v)
}
if(index == elements.length - 1){
elements.forEach(v => this.layer.selectLayer.group.remove(v))
}
resolve()
})
})
}
}
lookingLayer(id,str){
return new Promise((resolve, reject) => {
const groups = MyCanvas?.[this.id].getObjects()
let group = null
groups.forEach(v => {
if(str && v?.custom?.type === 'layer' && (str == 'setlayerIndex' || str == 'setRubber')){
let layerIndex = v?.custom?.layerIndex * 10000
v.moveTo(layerIndex)
}
if(v?.custom?.layerId == id && !v?.custom?.noErasable){
if(str && str == 'setRubber'){
v.set({erasable:'deep'})
}
}else if(v?.custom?.type === 'layer'){
v.set({erasable:false})
}
if (v?.custom?.layerId === id && v?.custom?.type === 'layer') {
group = v
}
})
resolve(group)
})
}
canvasKeyUp(event){
this.keyDown = this.keyDown.filter((item) => {
if(item.code !== 'AltLeft'){
if(this.oldOperation)this.setOperation(this.oldOperation)
}
return event.code !== item;
})
}
async layerShowHide(id,item){
item.isShow = !item.isShow
MyCanvas?.[this.id].forEachObject((obj)=>{
if(obj.custom.layerId == id)obj.visible = item.isShow
})
MyCanvas?.[this.id].renderAll() // 刷新画布改变group的visible属性必须通过刷新画布才能应用新属性值
}
canvasKeyDown(event){
if(!this.currentOperation)return
let keys = ['Enter','Delete','ControlLeft','ShiftLeft','BracketLeft','BracketRight','MetaLeft']
var activeObject = MyCanvas?.[this.id].getActiveObject();
let state = (activeObject && activeObject.type == 'textbox'&&activeObject.isEditing)
if(keys.indexOf(event.code) > -1){
event.preventDefault();
}
if(this.keyDown.indexOf(event.code)>-1 || state){
}else{
this.keyDown.push(event.code)
// console.log(this.keyDown.indexOf('ControlLeft') > -1 , this.keyDown.indexOf('MetaLeft') > -1, event.code == 'KeyC')
if(event.code === 'Enter' && operation.value == 'fold'){
this.foldEnd('Enter')
}else if(event.key === 'Delete'){
this.deleteObject()
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyZ' && this.keyDown.indexOf('ShiftLeft') > -1){
this.historyState('reverse')
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyZ'){
this.historyState('')
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyC'){
this.copy()
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyV'){
this.paste()
}else if(this.keyDown.indexOf('BracketLeft') > -1){
let width = this.brushwork.width[this.operation]
this.brushwork.width[this.operation] = (width - 5) < 3?3:(width - 5)
this.setPencilWidth()
}else if(this.keyDown.indexOf('BracketRight') > -1){
let width = this.brushwork.width[this.operation]
this.brushwork.width[this.operation] = (width + 5) > 50?50:(width + 5)
this.setPencilWidth()
}else if(this.keyDown.indexOf('KeyI') > -1){
this.getColor()//吸色
}else if(this.keyDown.indexOf('KeyM') > -1){
setOperation('move')
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyD'){
MyCanvas?.[this.id].discardActiveObject().renderAll();
}else if((this.keyDown.indexOf('ControlLeft') > -1 || this.keyDown.indexOf('MetaLeft') > -1) && event.code == 'KeyO'){
event.preventDefault();
this.uploadImg()
}else if(this.keyDown.indexOf('KeyB') > -1){
// if(operation.value == 'pencil' || operation.value == 'texture'){
this.setOperation('pencil')
// }
}else if(this.keyDown.indexOf('KeyE') > -1){
// if(operation.value == 'pencil' || operation.value == 'texture'){
this.setOperation('eraser')
// }
}
}
// if(this.keyDown.indexOf(event.key)>-1){
// }else{
// this.keyDown.push(event.code)
// if(event.key === 'Enter' && this.operation == 'fold'){
// this.foldEnd('Enter')
// }else if(event.key === 'Delete'){
// this.deleteObject()
// }else if(this.keyDown.indexOf('ControlLeft') > -1 && this.keyDown.indexOf('KeyZ') > -1 && this.keyDown.indexOf('ShiftLeft') > -1){
// this.historyState('reverse')
// }else if(this.keyDown.indexOf('ControlLeft') > -1 && this.keyDown.indexOf('KeyZ') > -1){
// this.historyState('')
// }else if(this.keyDown.indexOf('ControlLeft') > -1 && this.keyDown.indexOf('KeyC') > -1){
// this.copy()
// }else if(this.keyDown.indexOf('ControlLeft') > -1 && this.keyDown.indexOf('KeyV') > -1){
// this.paste()
// }else if(this.keyDown.indexOf('AltLeft') > -1 && this.keyDown.length == 1 && this.operation != 'move'){
// this.oldOperation = this.operation
// this.setOperation('move')
// }
// }
}
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);
this.brushwork.color = result.sRGBHex;
// canvasPencilColor.value =
setPencilColor()
} catch (e) {
// message.info(this.t('ColorboardUpload.jsContent1'))
}
}
canvasClear(){
// if(this.canvas?.dispose)MyCanvas?.[this.id].dispose()
let oldCanvasDom = this.canvasDomParent?.querySelector('.canvas-container')
let oldCanvasDom1 = this.canvasDomParent?.querySelector('canvas')
if(oldCanvasDom)oldCanvasDom.remove()
if(oldCanvasDom1)oldCanvasDom1.remove()
this.reverseCanvasState=[];//撤回
this.normalCanvasState=[];//反撤回
this.canvas = null
this.canvas = null
this.layer = {
list:[],
selectLayer:{
group:null,
id:-1,
},
currentIndex: 0,
}
this.mouse = {
point:null,
upPoint:null,
isMovePostion:false,
lastPosX:0,
lastPosY:0,
}
this.brushwork = {
value:'PencilBrush',
width:{},
color:'#000000',
texture:0,
}
this.operation = 'movePosition'
document.removeEventListener("keydown", this.canvasKeyDown);
document.removeEventListener("keyup", this.canvasKeyUp);
document.removeEventListener('mousemove', this.mouseMove);
document.removeEventListener('touchmove', this.touchmove);
delete MyCanvas[this.id]
// MyCanvas[this.id] = null
}
//删除选中元素
deleteObject(){
if(!MyCanvas?.[this.id].getActiveObjects()){
return
}
let target = MyCanvas?.[this.id].getActiveObjects()
target.forEach((item)=>{
MyCanvas?.[this.id].fxRemove(item, {
onComplete:()=>{
MyCanvas?.[this.id].discardActiveObject(); // 丢弃当前选中的对象
MyCanvas?.[this.id].renderAll(); // 重新渲染 Canvas
}
})
MyCanvas[this.id].FX_DURATION = 200
// MyCanvas[this.id].remove(item)
})
this.updataLayer()
this.updateCanvasState('remove')
}
async getDashedImg(cloned){
let position = {
left:cloned?.left,
top:cloned?.top,
width:cloned?.width + cloned?.strokeWidth*2,
height:cloned?.height + cloned?.strokeWidth*2,
}
let elements = MyCanvas[this.id].getObjects().filter(obj => this.isAddToLayer(obj));
let imgData = await this.groupToImg(elements,position,'clipPath')//矩形裁剪图片
let img = await this.createImage({minioUrl:imgData})
// cloned._objects = cloned._objects.filter(item => item.type == 'image')
let clipPathElement = cloned._objects.filter(obj => obj.type != 'image')[0]
cloned.set({
left:0,
top:0,
visible:true
})
img.set({
left:position.left,
top:position.top,
clipPath:clipPathElement,
})
return img
}
//复制粘贴
async copy(canvas){
var activeObject=null;
if(MyCanvas?.[this.id].getActiveObject()){
activeObject = MyCanvas?.[this.id].getActiveObject()
}else{
activeObject = MyCanvas?.[this.id].getObjects().filter(obj => obj.custom.dashed)[0];
}
if(!activeObject){
return
}
let copyObj = null
await new Promise((resolve, reject) => {
activeObject.clone(async (cloned)=>{
this.setClone(activeObject,cloned)
if(cloned.custom.dashed){
copyObj = await this.getDashedImg(cloned)
}else{
copyObj = cloned
}
resolve()
})
})
this._clipboard = copyObj;
}
async paste(){//粘贴
if(!this._clipboard){
return
}
await this.createLayer({})
this._clipboard.clone(clonedObj => {
// this.setClone(this._clipboard,clonedObj)
MyCanvas?.[this.id].discardActiveObject() // 取消选择
clonedObj.set({
selectable: true
})
if (clonedObj.type === 'activeSelection') {
// 活动选择需要一个对画布的引用
clonedObj.forEachObject((obj)=>{
MyCanvas?.[this.id].add(obj)
})
clonedObj.setCoords()
} else {
MyCanvas?.[this.id].add(clonedObj)
// this.layer.selectLayer.group.add(clonedObj)
}
MyCanvas?.[this.id].setActiveObject(clonedObj)
MyCanvas?.[this.id].requestRenderAll()
})
this._clipboard = null
this.updateCanvasState()
}
isSelectable(obj){//判断元素是否允许选中
if(this.dashed.isDetail){
return (obj.custom?.type != 'layer' && (!obj.custom?.isSelectable || this.layer.selectLayer.group.custom.groupType == 'Grid') && !obj.isType('path') && !obj.custom?.dashed)
}else{
return (obj.custom?.type != 'layer' && (!obj.custom?.isSelectable || this.layer.selectLayer.group.custom.groupType == 'Grid') && !obj.isType('path') && (this.dashed.isDetail || !obj.custom?.dashed))
}
}
isAddToLayer(obj){//判断元素是否允许添加
return(obj.custom?.type != 'layer' && obj.custom?.layerId == this.layer.selectLayer.id)
}
//撤回反撤回
//设置画布监听修改添加事件,用来做撤回功能
updateCanvasState(str){
let canvasData = MyCanvas?.[this.id].toJSON(['custom','selectable','MINIOURL','perPixelTargetFind','subTargetCheck','evented']);
if(canvasData.clipPath){
canvasData.clipPath.left = 0
canvasData.clipPath.top = 0
}
let canvasAsJson = JSON.stringify(canvasData)
let layerList = JSON.stringify(this.layer.list)
let layerId = this.layer.selectLayer.id
if(str == 'loadingCompleted'){
// this.reverseCanvasState.push(canvasAsJson);
}
this.normalCanvasState.push({canvasAsJson,layerList,layerId});
if (this.isLoadCanvas) {
this.reverseCanvasState = []
this.isLoadCanvas = false;
this.canvasState = canvasAsJson
}
}
//撤回
async historyState(str){
if(str == 'reverse' && this.reverseCanvasState.length > 0){//反撤回
let obj = this.reverseCanvasState.pop()
let layerList = JSON.parse(obj.layerList)
this.layer.list = layerList
this.layer.selectLayer.id = obj.layerId
this.canvasState = obj.canvasAsJson
this.normalCanvasState.push(obj);
}else if(str == '' && this.normalCanvasState.length > 1){
let obj = this.normalCanvasState.pop()
let select = this.normalCanvasState[this.normalCanvasState.length-1]
this.canvasState = select.canvasAsJson
this.layer.list = JSON.parse(select.layerList)
this.layer.selectLayer.id = select.layerId
this.reverseCanvasState.push(obj);
this.isLoadCanvas = true;
}else{
return
}
MyCanvas?.[this.id].loadFromJSON(this.canvasState, () => {});
MyCanvas?.[this.id].setBackgroundColor({
source:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC',
repeat: 'repeat',
},MyCanvas?.[this.id].renderAll.bind(MyCanvas?.[this.id]),
)
}
setLoadFromJSON(data,fun){
MyCanvas?.[this.id].loadFromJSON(data.canvas, fun);
if(data.groupList.length == 0){
console.log(this.layer)
}else{
this.layer.list = data.groupList
this.layer.selectLayer.id = data.groupList[0].id
}
}
temporarilyExport(data){
let scaleXY = {
scaleX:data?.scaleX?data?.scaleX:1,
scaleY:data?.scaleY?data?.scaleY:1,
}
let width = data?.width || MyCanvas?.[this.id].width
let height = data?.height || MyCanvas?.[this.id].height
var canvasDom = document.createElement("canvas");
let exportCanvas = new fabric.Canvas(canvasDom, {
width:width*scaleXY.scaleX,
height:height*scaleXY.scaleY,
scaleX:scaleXY.scaleX,
scaleY:scaleXY.scaleY,
isDrawingMode: false, // 开启绘图模式
});
return exportCanvas
}
closeTemporarilyExport(temporar){
if(temporar){
temporar.wrapperEl.remove()
temporar.dispose()
}
}
setClone(obj,goal){
if(obj.custom){
goal.set({custom:JSON.parse(JSON.stringify(obj.custom))})
}
goal.perPixelTargetFind = obj.perPixelTargetFind
goal.hasBorders = obj.hasBorders
goal.hasControls = obj.hasControls
goal.selectable = obj.selectable
goal.erasable = obj.erasable
if(obj.minioUrl)goal.minioUrl = obj.minioUrl
}
//导出除了底图
async detailSubmit(){
return await new Promise(async (resolve, reject) => {
let list = MyCanvas?.[this.id].getObjects().filter(obj => this.isAddToLayer(obj) && !obj.custom.dashed && obj.type && obj.erasable);
let layerBg = list.filter(obj => obj.custom.isSelectable)[0]
let scaleXY = {
scaleX:layerBg?.scaleX?layerBg?.scaleX:1,
scaleY:layerBg?.scaleY?layerBg?.scaleY:1,
width:layerBg?.width?layerBg?.width:MyCanvas?.[this.id].width,
height:layerBg?.height?layerBg?.height:MyCanvas?.[this.id].height,
}
let imgData = await this.groupToImg(list,{},'setGrid',scaleXY)
resolve(imgData)
})
// return imgData
}
//导出
selectExport(){
let layer = this.layer.list.filter(item=>item.id == this.layer.selectLayer.id)[0]
return layer.img
}
async allExport(){
let list = MyCanvas?.[this.id].getObjects()
let layerBg = list.filter(obj => obj.custom.isSelectable)[0]
let scaleXY = {
scaleX:layerBg?.scaleX?layerBg?.scaleX:1,
scaleY:layerBg?.scaleY?layerBg?.scaleY:1,
width:layerBg?.width?layerBg?.width:MyCanvas?.[this.id].width,
height:layerBg?.height?layerBg?.height:MyCanvas?.[this.id].height,
}
let imgData = await this.groupToImg(list,{},'setGrid',scaleXY)
// let exportCanvas = this.temporarilyExport()
// let list = MyCanvas?.[this.id].getObjects()
// for (let index = 0; index < list.length; index++) {
// let item = list[index]
// new Promise((resolve, reject) => {
// item.clone((cloned)=>{
// this.setClone(item,cloned)
// exportCanvas.add(cloned)
// resolve()
// })
// })
// }
// let data = exportCanvas.toDataURL("image/png");
// this.closeTemporarilyExport(exportCanvas)
return imgData
}
}
export default MyCanvas