1998 lines
62 KiB
JavaScript
1998 lines
62 KiB
JavaScript
import {
|
||
exportSele,
|
||
JSRectUpdata,
|
||
JSchangeType,
|
||
JScanvasMouseDown,
|
||
JScanvasMouseMove,
|
||
JScreateCheck,
|
||
JSSetTexture,
|
||
JSSetRemoveImage,
|
||
} from "@/tool/canvasDrawingCopy";
|
||
import { getMousePosition } from "@/tool/mdEvent";
|
||
import { file } from "jszip";
|
||
class MyCanvas {
|
||
canvas=null
|
||
constructor() {
|
||
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.canvas;
|
||
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,//用来获取移入前是否是绘画模式
|
||
}
|
||
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){//初始化
|
||
this.canvasClear()
|
||
this.canvasWH = val
|
||
|
||
this.canvasDomParent = dom;
|
||
var canvasDom = document.createElement("canvas");
|
||
this.canvasDomParent.appendChild(canvasDom);
|
||
|
||
MyCanvas.canvas = 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,
|
||
});
|
||
// MyCanvas.canvas.freeDrawingCursor= 'none'
|
||
|
||
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.canvas.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.canvas.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.canvas.add(rect1)
|
||
// // MyCanvas.canvas.add(rect1)
|
||
// let rect = new fabric.Rect({
|
||
// left: 0,
|
||
// top: 0,
|
||
// width: MyCanvas.canvas.width,
|
||
// height: MyCanvas.canvas.height,
|
||
// inverted:true,
|
||
// fill: "red",
|
||
// });
|
||
// // let rect2 = new fabric.Rect({
|
||
// // width: MyCanvas.canvas.width,
|
||
// // height: MyCanvas.canvas.height,
|
||
// // fill:'#FFF'
|
||
// // });
|
||
// // // MyCanvas.canvas.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.canvas.width/img.width,
|
||
// Y:MyCanvas.canvas.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.canvas.add(rect)
|
||
// },{ crossOrigin: "Anonymous" })
|
||
// // // MyCanvas.canvas.add(rect1)
|
||
// // // rect1.clipPath = group
|
||
// // // MyCanvas.canvas.forEachObject((item) =>{
|
||
// // // if(item.clipPath){
|
||
// // // item.clipPath.add(rect2)
|
||
// // // // item.clipPath = group
|
||
// // // }
|
||
// // // })
|
||
// return
|
||
|
||
MyCanvas.canvas.on("mouse:move", this.setCanvasMove.bind(this));
|
||
MyCanvas.canvas.on("mouse:down",this.setCanvasDown.bind(this));
|
||
MyCanvas.canvas.on("mouse:up",this.setCanvasUp.bind(this));
|
||
MyCanvas.canvas.on("mouse:wheel",this.setCanvasWheel.bind(this));
|
||
//双击
|
||
MyCanvas.canvas.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.canvas, true);
|
||
JSchangeType(MyCanvas.canvas,'init')
|
||
// await this.createBg()
|
||
await this.createLayer({str:'init'})//创建图层并且使用
|
||
MyCanvas.canvas.on("object:added", (event)=>{
|
||
this.addLayer(event)
|
||
});
|
||
this.canvas = MyCanvas.canvas;
|
||
return MyCanvas.canvas
|
||
}
|
||
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.offsetHeight / this.canvasWH.height
|
||
let x = this.canvasWH.width / 2
|
||
let y = this.canvasWH.height / 2
|
||
if(str == 'updata'){
|
||
x = 0
|
||
y = 0
|
||
const vpt = MyCanvas.canvas.viewportTransform;
|
||
vpt[4] = 0; // 更新水平偏移
|
||
vpt[5] = 0; // 更新垂直偏移
|
||
}
|
||
MyCanvas.canvas.zoomToPoint(
|
||
{ // 关键点
|
||
x: x,
|
||
y: y
|
||
},
|
||
scale
|
||
)
|
||
MyCanvas.canvas.setBackgroundColor({
|
||
source:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC',
|
||
repeat: 'repeat',
|
||
},MyCanvas.canvas.renderAll.bind(MyCanvas.canvas),
|
||
)
|
||
}
|
||
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.canvas.discardActiveObject();//取消所有选中边框
|
||
if(this.createPatterning.state){
|
||
MyCanvas.canvas.remove(this.createPatterning.current)
|
||
}
|
||
this.removeSetText()
|
||
initAligningGuidelines(MyCanvas.canvas,false)
|
||
MyCanvas.canvas.remove(this.createPatterning.polyLineBtn)
|
||
if(str == 'pencil'){
|
||
this.setPencil()
|
||
this.pencilbtnStyle.display = `block`
|
||
this.setCursor('none');
|
||
MyCanvas.canvas.freeDrawingCursor = 'none'
|
||
}else if(str == 'move'){
|
||
JSchangeType(MyCanvas.canvas,'')
|
||
MyCanvas.canvas.isDrawingMode = false
|
||
this.pencilbtnStyle.display = `none`
|
||
this.setCursor('grab');
|
||
}else if(str == 'movePosition'){
|
||
JSchangeType(MyCanvas.canvas,'init')
|
||
initAligningGuidelines(MyCanvas.canvas,true)
|
||
this.setMove()
|
||
this.pencilbtnStyle.display = `none`
|
||
this.setCursor('all-scroll');
|
||
MyCanvas.canvas.isDrawingMode = false
|
||
}else if(str == 'texture'){
|
||
this.setTexture()
|
||
this.pencilbtnStyle.display = `block`
|
||
MyCanvas.canvas.freeDrawingCursor = 'none'
|
||
this.setCursor('none');
|
||
}else if(str == 'eraser'){
|
||
this.setEraser()
|
||
this.pencilbtnStyle.display = `block`
|
||
MyCanvas.canvas.freeDrawingCursor = 'none'
|
||
this.setCursor('none');
|
||
}else if(str == 'text'){
|
||
this.setMove()
|
||
this.setText()
|
||
JSchangeType(MyCanvas.canvas,'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.canvas.isDrawingMode = false
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(obj.type != 'group' && !obj.isType('path')){
|
||
obj.selectable = false
|
||
}
|
||
});
|
||
}else if(['dashedPencil', 'dashed'].includes(str)){
|
||
this.setGroupGrid('all')
|
||
MyCanvas.canvas.isDrawingMode = false
|
||
this.pencilbtnStyle.display = `none`
|
||
this.setCursor('crosshair')
|
||
MyCanvas.canvas.freeDrawingCursor = 'crosshair'
|
||
if(str == 'dashedPencil')this.setDashedPencil()
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(obj.type != 'group' && !obj.isType('path')){
|
||
obj.selectable = false
|
||
}
|
||
});
|
||
}else if(str){
|
||
this.pencilbtnStyle.display = `none`
|
||
this.setCursor('auto');
|
||
MyCanvas.canvas.isDrawingMode = false
|
||
MyCanvas.canvas.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.canvas.defaultCursor = str;
|
||
MyCanvas.canvas.moveCursor = str;
|
||
MyCanvas.canvas.hoverCursor = str;
|
||
MyCanvas.canvas.upperCanvasEl.style.cursor = str;
|
||
}
|
||
setCanvasMove = (event)=>{
|
||
|
||
if(this.mouse.isMovePostion && this.operation == 'move') return this.setCanvasPosition(event)
|
||
if(MyCanvas.canvas.isDrawingMode){
|
||
}else{
|
||
let getActiveObject = MyCanvas.canvas.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.canvas.requestRenderAll()
|
||
}
|
||
}
|
||
}
|
||
setCanvasPosition(event){
|
||
const e = event;
|
||
const vpt = MyCanvas.canvas.viewportTransform;
|
||
|
||
vpt[4] += e.pointer.x - this.mouse.lastPosX; // 更新水平偏移
|
||
vpt[5] += e.pointer.y - this.mouse.lastPosY; // 更新垂直偏移
|
||
|
||
MyCanvas.canvas.requestRenderAll(); // 请求重绘画布
|
||
this.mouse.lastPosX = e.pointer.x;
|
||
this.mouse.lastPosY = e.pointer.y;
|
||
}
|
||
// setRemoveDashed(){
|
||
// MyCanvas.canvas.forEachObject((obj) =>{
|
||
// if(obj.custom.dashed && obj._objects){
|
||
// let rect = obj._objects.filter(item => item.type == 'rect')[0]
|
||
// obj.remove(rect)
|
||
// MyCanvas.canvas.renderAll();
|
||
// }
|
||
// });
|
||
// }
|
||
//设置再画布上按下
|
||
setCanvasDown(event){
|
||
if(event.target && event.target.custom?.dashed && ['dashedPencil', 'dashed'].includes(this.operation)){
|
||
// if(MyCanvas.canvas.isDrawingMode){
|
||
// MyCanvas.canvas.isDrawingMode = false;
|
||
// }
|
||
this.dashed.state = true
|
||
}else if(!event.target?.custom?.dashed){
|
||
// if(['dashedPencil'].includes(this.operation)){
|
||
// MyCanvas.canvas.isDrawingMode = true;
|
||
// }
|
||
this.dashed.state = false
|
||
}
|
||
let dashedGroup = MyCanvas.canvas.getObjects().filter(obj => obj?.custom?.dashed)[0];
|
||
if(this.dashed.state && (this.operation == 'dashed' || this.operation == 'dashedPencil') && dashedGroup)return
|
||
if(!this.dashed.state && (this.operation == 'dashed' || this.operation == 'dashedPencil') && !event.target?.custom?.dashed && dashedGroup){
|
||
MyCanvas.canvas.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.canvas,this.operation)
|
||
this.createPatterning.state = true
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
obj.set('selectable', false); // 禁用选中
|
||
});
|
||
if(this.createPatterning.current && this.operation == 'fold'){
|
||
MyCanvas.canvas.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.canvas.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.canvas.add(this.createPatterning.current)
|
||
if(this.operation == 'fold'){
|
||
this.createPatterning.polyLineBtn = JScreateCheck(event)
|
||
this.createPatterning.polyLineBtn.on('mousedown',this.foldEnd.bind(this))
|
||
MyCanvas.canvas.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.canvas.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.canvas.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.canvas.forEachObject((obj) =>{
|
||
if(this.isSelectable(obj)){
|
||
obj.selectable = true
|
||
}else{
|
||
obj.selectable = false
|
||
}
|
||
});
|
||
MyCanvas.canvas.bringToFront(this.createPatterning.polyLineBtn);//设置优先级最高
|
||
}else if(this.operation){
|
||
this.createPatterning.state = false
|
||
MyCanvas.canvas.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.canvas.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.canvas.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.canvas.isDrawingMode = true
|
||
let pencil = new fabric.Test(MyCanvas.canvas,{}); //普通笔
|
||
MyCanvas.canvas.freeDrawingBrush = pencil
|
||
}
|
||
async setDashed(obj){
|
||
MyCanvas.canvas.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
|
||
}
|
||
})
|
||
console.log(223);
|
||
MyCanvas.canvas.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.canvas.getObjects().filter(obj => obj.custom.layerId == id)
|
||
let copyElements = []
|
||
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.canvas.add(item))
|
||
}
|
||
async setGroupGrid(str){//group变为图片
|
||
// MyCanvas.canvas.discardActiveObject();//取消所有选中边框
|
||
let elements = MyCanvas.canvas.getObjects().filter(obj => this.isAddToLayer(obj) && !obj.custom.dashed && obj.type);
|
||
if(str == 'all'){
|
||
elements = MyCanvas.canvas.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.canvas.width,
|
||
height:layerBg?.height?layerBg?.height:MyCanvas.canvas.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.canvas.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.canvas.width,
|
||
height: MyCanvas.canvas.height,
|
||
strokeWidth:0,
|
||
fill: new fabric.Pattern({
|
||
source: img.getElement(), // 传入图片元素
|
||
repeat: 'no-repeat' // 设置图片不重复
|
||
}),
|
||
custom:{
|
||
isSelectable:true,
|
||
},
|
||
hasBorders: true,
|
||
hasControls: true
|
||
});
|
||
this.setGroupStyle(rect)
|
||
MyCanvas.canvas.add(rect)
|
||
}
|
||
MyCanvas.canvas.renderAll() // 刷新画布,改变group的visible属性,必须通过刷新画布,才能应用新属性值
|
||
}
|
||
//液化
|
||
getLiquefactionImgObj(){
|
||
return new Promise(async (resolve, reject) => {
|
||
let img,str = null
|
||
const activeObject = this.canvas.getActiveObject(); // 获取选中的对象
|
||
let dashedGroup = MyCanvas.canvas.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 = this.canvas.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 = this.canvas.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.canvas.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.canvas.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 = temporar.toDataURL(imgData);
|
||
this.closeTemporarilyExport(temporar)
|
||
return data
|
||
}
|
||
setCanvasWheel(opt){
|
||
const delta = opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下是 100
|
||
let zoom = MyCanvas.canvas.getZoom() // 获取画布当前缩放值
|
||
zoom *= 0.999 ** delta
|
||
if (zoom > 20) zoom = 20
|
||
if (zoom < 0.01) zoom = 0.01
|
||
MyCanvas.canvas.zoomToPoint(
|
||
{ // 关键点
|
||
x: opt.e.offsetX,
|
||
y: opt.e.offsetY
|
||
},
|
||
zoom
|
||
)
|
||
opt.e.preventDefault()
|
||
opt.e.stopPropagation()
|
||
this.setPencilWidth()
|
||
}
|
||
foldEnd(key){
|
||
MyCanvas.canvas.skipTargetFind = true
|
||
let points = this.createPatterning.current.points
|
||
if(key == 'Enter'){
|
||
}else{
|
||
points.pop()
|
||
}
|
||
points.pop()
|
||
this.createPatterning.state = false
|
||
MyCanvas.canvas.remove(this.createPatterning.current)
|
||
MyCanvas.canvas.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.canvas.add(polyline)
|
||
this.clearPatterning()//临时图形置为空并且添加撤回对象里面
|
||
// this.layerAddElement(polyline)
|
||
}
|
||
clearPatterning(){
|
||
if(this.createPatterning.state){
|
||
MyCanvas.canvas.remove(this.createPatterning.current)
|
||
}
|
||
this.createPatterning.current = null
|
||
MyCanvas.canvas.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.canvas.getActiveObject();
|
||
switch (str) {
|
||
case 'Front':
|
||
MyCanvas.canvas.bringToFront(activeObject)//顶层
|
||
// this.layer.selectLayer.group.bringToFront(activeObject)
|
||
break
|
||
case 'Back':
|
||
MyCanvas.canvas.sendToBack(activeObject)//底层
|
||
// this.layer.selectLayer.group.sendToBack(activeObject)
|
||
break
|
||
case 'Forward':
|
||
MyCanvas.canvas.bringForward(activeObject)
|
||
// this.layer.selectLayer.group.bringForward(activeObject)
|
||
break
|
||
case 'Backwards':
|
||
MyCanvas.canvas.sendBackwards(activeObject)
|
||
// this.layer.selectLayer.group.sendBackwards(activeObject)
|
||
break
|
||
}
|
||
|
||
}
|
||
setPencil(){
|
||
let pencil
|
||
MyCanvas.canvas.isDrawingMode = true//开启绘画模式
|
||
if(this.brushwork.value == 'PencilBrush'){
|
||
pencil = new fabric.PencilBrush(MyCanvas.canvas,{}); //普通笔
|
||
}else if(this.brushwork.value == 'Marking'){
|
||
pencil = new fabric.PencilBrush(MyCanvas.canvas,); //记号笔
|
||
}else if(this.brushwork.value == 'InkBrush'){
|
||
pencil = new fabric.InkBrush(MyCanvas.canvas,{}); //油画笔
|
||
}else if(this.brushwork.value=='CrayonBrush'){
|
||
pencil = new fabric.CrayonBrush(MyCanvas.canvas,{}); //蜡笔
|
||
}else if(this.brushwork.value == 'RibbonBrush'){
|
||
pencil = new fabric.RibbonBrush(MyCanvas.canvas,{width: 1,}); //色带
|
||
}else if(this.brushwork.value == 'MarkerBrush'){
|
||
pencil = new fabric.MarkerBrush(MyCanvas.canvas,{}); //书写笔
|
||
// pencil = new fabric.PenBrush(MyCanvas.canvas,{}); //书写笔
|
||
}else if(this.brushwork.value == 'WritingBrush'){
|
||
pencil = new fabric.WritingBrush(MyCanvas.canvas,{}); //毛笔
|
||
}else if(this.brushwork.value == 'LongfurBrush'){
|
||
pencil = new fabric.LongfurBrush(MyCanvas.canvas,{width: 1,}); //色带
|
||
}else if(this.brushwork.value == 'SpraypaintBrush'){
|
||
pencil = new fabric.SpraypaintBrush(MyCanvas.canvas,{}); //长毛刷
|
||
}
|
||
|
||
MyCanvas.canvas.freeDrawingBrush = pencil
|
||
if(this.brushwork.value == 'RibbonBrush' || this.brushwork.value == 'LongfurBrush'){
|
||
MyCanvas.canvas.freeDrawingBrush.width = 1;
|
||
}
|
||
if(this.brushwork.value == 'Marking'){
|
||
MyCanvas.canvas.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.canvas.freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,1);
|
||
}
|
||
this.setPencilWidth()
|
||
this.pencilbtnStyle.background = this.brushwork.color
|
||
MyCanvas.canvas.freeDrawingBrush.isEraser = false
|
||
}
|
||
setCanvasZoom(opt){
|
||
let zoom = MyCanvas.canvas.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.canvas.setDimensions(MyCanvas.canvas.width *= zoom,MyCanvas.canvas.height *= zoom)
|
||
// MyCanvas.canvas.wrapperEl.style.zoom = zoom
|
||
MyCanvas.canvas.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.canvas.wrapperEl.parentNode.scrollTop,
|
||
left: MyCanvas.canvas.width/2,
|
||
top: MyCanvas.canvas.height/2,
|
||
|
||
}
|
||
img.set({
|
||
custom:{
|
||
type:'upImgFiles'
|
||
}
|
||
})
|
||
await this.createLayer({})
|
||
this.setCanvasImage(img,position,"upImgFiles",imgData)
|
||
}
|
||
createImage(imgData){
|
||
return new Promise((resolve, reject) => {
|
||
fabric.Image.fromURL(imgData.minioUrl,(img) => {
|
||
resolve(img)
|
||
},{ crossOrigin: "Anonymous" })
|
||
})
|
||
}
|
||
setImageWidth = (key,img)=>{
|
||
const CW = MyCanvas.canvas.width
|
||
const CH = MyCanvas.canvas.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.canvas.height/2) / imgObj.height
|
||
// imgWidth = imgObj.width * heightScale
|
||
// }else{
|
||
// imgWidth /= 2
|
||
// }
|
||
// }
|
||
// }
|
||
return imgWidth
|
||
}
|
||
async setCanvasImage(img,position,key,data){
|
||
let minioUrl = ''//表示收藏或者generate
|
||
let imgUrl = data.imgUrl
|
||
if (key == "likeDesignCollectionList") {
|
||
imgUrl = data.designOutfitUrl;
|
||
}
|
||
let imgWidth = await this.setImageWidth(key,img);
|
||
if(imgUrl?.split('?')){
|
||
// let url = imgUrl.split('?')[0]
|
||
// var match = url.match(/^(?:https?:\/\/[^\/]+)\/(.*)/);
|
||
// minioUrl = match[1]
|
||
const { pathname } = new URL(imgUrl);
|
||
const result = pathname.slice(1);
|
||
minioUrl = result
|
||
}
|
||
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,
|
||
minioUrl,
|
||
scaleX:scale.X,
|
||
scaleY:scale.Y,
|
||
});
|
||
MyCanvas.canvas.add(img)
|
||
this.updateCanvasState('')
|
||
}
|
||
setMove(){
|
||
MyCanvas.canvas.isDrawingMode = false
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(this.isSelectable(obj)){
|
||
obj.selectable = true
|
||
}else{
|
||
obj.selectable = false
|
||
}
|
||
});
|
||
MyCanvas.canvas.renderAll() // 刷新画布,改变group的visible属性,必须通过刷新画布,才能应用新属性值
|
||
}
|
||
async setTexture(){
|
||
MyCanvas.canvas.isDrawingMode = true//开启绘画模式
|
||
let img = await JSSetTexture(this.texture.list[this.texture.value].url)
|
||
let zoom = MyCanvas.canvas.getZoom() // 获取画布当前缩放值
|
||
let patternBrush = new fabric.PatternBrush(MyCanvas.canvas)
|
||
patternBrush.source = img
|
||
patternBrush.width = Number(this.brushwork.width[this.operation]) / zoom; // 设置画笔大小
|
||
this.setPencilWidth()
|
||
MyCanvas.canvas.freeDrawingBrush = patternBrush
|
||
}
|
||
setEraser(){
|
||
MyCanvas.canvas.isDrawingMode = true
|
||
let eraser = new fabric.EraserBrush(MyCanvas.canvas)
|
||
MyCanvas.canvas.freeDrawingBrush = eraser
|
||
this.pencilbtnStyle.background = '#fff'
|
||
MyCanvas.canvas.freeDrawingBrush.isEraser = true
|
||
this.setPencilWidth()
|
||
MyCanvas.canvas.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.canvas.freeDrawingBrush.isEraser){
|
||
}else{
|
||
this.pencilbtnStyle.background = this.brushwork.color
|
||
}
|
||
if(this.brushwork.value == 'Marking'){
|
||
MyCanvas.canvas.freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.5);
|
||
}else if(this.brushwork.value == 'InkBrush'){
|
||
MyCanvas.canvas.freeDrawingBrush.color = this.hexToRgba(this.brushwork.color,.2);
|
||
}else{
|
||
MyCanvas.canvas.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.canvas.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.canvas.setWidth(this.canvasWH.width);
|
||
MyCanvas.canvas.setHeight(this.canvasWH.height);
|
||
// MyCanvas.canvas.width = this.canvasWH.width
|
||
// MyCanvas.canvas.height = this.canvasWH.height
|
||
this.initCanvasWH('updata')
|
||
},1000)
|
||
}
|
||
setColorHistory = (value)=>{
|
||
this.brushwork.color = value
|
||
this.pencilColor()
|
||
}
|
||
setPencilWidth(){//切换颜色给铅笔设置颜色
|
||
let zoom = MyCanvas.canvas.getZoom() // 获取画布当前缩放值
|
||
clearTimeout(this.setTimeOut.width)
|
||
this.setTimeOut.width = setTimeout(()=>{
|
||
if(!this.brushwork.width[this.operation])this.brushwork.width[this.operation]=20
|
||
// MyCanvas.canvas.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.canvas.freeDrawingBrush.width = Number(this.brushwork.width[this.operation]) / zoom;
|
||
}else{
|
||
MyCanvas.canvas.freeDrawingBrush.width = Number(this.brushwork.width[this.operation]);
|
||
}
|
||
if((this.brushwork.value == 'LongfurBrush' || this.brushwork.value == 'RibbonBrush') && this.operation == 'pencil'){
|
||
MyCanvas.canvas.freeDrawingBrush.width = 1;
|
||
this.pencilbtnStyle.height = 1+'px'
|
||
this.pencilbtnStyle.width = 1+'px'
|
||
}
|
||
},100)
|
||
}
|
||
//关闭u或者创建文字
|
||
setTextFun(e){
|
||
if(this.operation != 'text'){
|
||
return
|
||
}
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(obj.type == 'textbox' && !obj.text){
|
||
MyCanvas.canvas.remove(obj);
|
||
}
|
||
});
|
||
var clickedObject = e.target;
|
||
if (clickedObject instanceof fabric.Textbox) {
|
||
this.createText = clickedObject
|
||
this.setTextData(this.createText)
|
||
}else{
|
||
|
||
var pointer = MyCanvas.canvas.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.canvas.add(this.createText)
|
||
// this.layer.selectLayer.group.add(this.createText)
|
||
this.createText.enterEditing();
|
||
MyCanvas.canvas.setActiveObject(this.createText).renderAll();
|
||
this.removeSetText()
|
||
}
|
||
}
|
||
setText(){
|
||
MyCanvas.canvas.on('mouse:down',(event)=>{
|
||
if(this.operation == 'zoomIn' || this.operation == 'zoomOut'){
|
||
}else{
|
||
this.setTextFun(event)
|
||
}
|
||
})
|
||
}
|
||
removeSetText(){
|
||
MyCanvas.canvas.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.canvas.width,
|
||
// height: MyCanvas.canvas.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.canvas.width,
|
||
// height: MyCanvas.canvas.height,
|
||
// erasable:false,
|
||
// selectable:false,
|
||
// });
|
||
// group.custom.layerId = -1
|
||
// MyCanvas.canvas.add(group)
|
||
// MyCanvas.canvas.clipPath = rect
|
||
// resolve()
|
||
// });
|
||
// })
|
||
// }
|
||
createLayer(data){
|
||
let {str,id} = data
|
||
let canvasData = MyCanvas.canvas.toJSON(['selectable','minioUrl','custom']);
|
||
return new Promise(async (resolve, reject) => {
|
||
MyCanvas.canvas.discardActiveObject();
|
||
if(!id)id = new Date().getTime()
|
||
let index = this.layer.currentIndex += 1
|
||
const rect = new fabric.Rect({
|
||
left: -MyCanvas.canvas.width / 2,
|
||
top: -MyCanvas.canvas.height / 2,
|
||
// left:0,
|
||
// top:0,
|
||
width: MyCanvas.canvas.width,
|
||
height: MyCanvas.canvas.height,
|
||
strokeWidth:0,
|
||
fill:'#FFF',
|
||
custom:{
|
||
layerId:id,
|
||
isSelectable:true,
|
||
},
|
||
// erasable:false,
|
||
selectable:false,
|
||
});
|
||
rect.clone((cloned)=>{
|
||
rect.clipPath = cloned
|
||
})
|
||
const group = new fabric.Group([], {
|
||
width: MyCanvas.canvas.width,
|
||
height: MyCanvas.canvas.height,
|
||
left:0,
|
||
top:0,
|
||
selectable:false,
|
||
erasable:false,
|
||
subTargetCheck:true,
|
||
evented:false,
|
||
// originX:'left',
|
||
// originY:'top',
|
||
custom:{
|
||
layerId:id,
|
||
type:'layer' ,
|
||
groupType:'Object',
|
||
layerIndex:index,
|
||
selectLayerIndex:(index) * 10000,
|
||
}
|
||
});
|
||
if(str == 'init'){
|
||
group.moveTo(group.custom.selectLayerIndex)
|
||
group.add(rect)
|
||
group.clone((cloned)=>{
|
||
cloned.set({left:0,top:0})
|
||
MyCanvas.canvas.clipPath = cloned
|
||
})
|
||
}
|
||
MyCanvas.canvas.add(group)
|
||
let img = group.toDataURL({
|
||
width: MyCanvas.canvas.width,
|
||
height: MyCanvas.canvas.height,
|
||
})
|
||
this.layer.list.unshift({
|
||
name:`Layer${index}`,
|
||
id,img,isShow:true,
|
||
groupType:'Object',
|
||
index,})
|
||
await this.selectLayer(id)
|
||
MyCanvas.canvas.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.canvas.remove(obj)
|
||
this.updataLayerImg(this.layer.selectLayer.id,group.toDataURL({
|
||
width: MyCanvas.canvas.width,
|
||
height: MyCanvas.canvas.height
|
||
}))
|
||
}
|
||
async addLayer(options){
|
||
console.log(options);
|
||
if(this.createPatterning.state)return
|
||
this.clipPath.clipGroup = MyCanvas.canvas.getObjects().filter(obj => obj.custom?.dashed)?.[0];
|
||
if (options.target.type === 'group' && options.target.custom?.layerId) return;
|
||
if(!options.target?.custom?.layerId){
|
||
if(options.target?.custom){
|
||
options.target.custom.layerId = this.layer.selectLayer.id
|
||
}else{
|
||
options.target.set({custom:{layerId : this.layer.selectLayer.id}})
|
||
}
|
||
}
|
||
//判断是否可以点击空白地方进行选中
|
||
if(options.target?.custom?.dashed){
|
||
options.target.set({perPixelTargetFind:false,erasable:false,hasBorders: false,hasControls: false})
|
||
// MyCanvas.canvas.setActiveObject(options.target);
|
||
MyCanvas.canvas.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.canvas.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) => {
|
||
console.log(this.clipPath.clipGroup);
|
||
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)
|
||
console.log(this.clipPath.clipGroup);
|
||
MyCanvas.canvas.remove(options.target)
|
||
resolve()
|
||
})
|
||
})
|
||
})
|
||
|
||
// this.setGroupGrid('all')
|
||
}
|
||
|
||
MyCanvas.canvas.renderAll();
|
||
|
||
this.updataLayer()
|
||
}
|
||
upLayerIndex(list){
|
||
list.forEach((item,index)=>{
|
||
let arr = MyCanvas.canvas.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.canvas.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.canvas.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.canvas.remove(this.layer.selectLayer.group)
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(obj.type != 'group' && obj.custom?.layerId == id){
|
||
MyCanvas.canvas.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.canvas.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.canvas.renderAll() // 刷新画布,改变group的visible属性,必须通过刷新画布,才能应用新属性值
|
||
this.setOperation('movePosition')
|
||
resolve('')
|
||
})
|
||
}
|
||
async mergeGroup(){
|
||
const elements = MyCanvas.canvas.getObjects().filter(obj => this.isAddToLayer(obj));
|
||
let isClipPath = MyCanvas.canvas.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.canvas.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.canvas.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?.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.canvas.add(img)
|
||
// }
|
||
}else{
|
||
MyCanvas.canvas.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.canvas.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){
|
||
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){
|
||
// console.log(id);
|
||
|
||
item.isShow = !item.isShow
|
||
MyCanvas.canvas.forEachObject((obj)=>{
|
||
if(obj.custom.layerId == id)obj.visible = item.isShow
|
||
})
|
||
MyCanvas.canvas.renderAll() // 刷新画布,改变group的visible属性,必须通过刷新画布,才能应用新属性值
|
||
|
||
}
|
||
canvasKeyDown(event){
|
||
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')
|
||
}
|
||
}
|
||
}
|
||
canvasClear(){
|
||
if(MyCanvas.canvas?.dispose)MyCanvas.canvas.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=[];//反撤回
|
||
MyCanvas.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);
|
||
|
||
}
|
||
//删除选中元素
|
||
deleteObject(){
|
||
if(!MyCanvas.canvas.getActiveObjects()){
|
||
return
|
||
}
|
||
let target = MyCanvas.canvas.getActiveObjects()
|
||
target.forEach((item)=>{
|
||
MyCanvas.canvas.fxRemove(item, {
|
||
onComplete:()=>{
|
||
MyCanvas.canvas.discardActiveObject(); // 丢弃当前选中的对象
|
||
MyCanvas.canvas.renderAll(); // 重新渲染 Canvas
|
||
}
|
||
})
|
||
MyCanvas.canvas.FX_DURATION = 200
|
||
// MyCanvas.canvas.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.canvas.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.canvas.getActiveObject()){
|
||
activeObject = MyCanvas.canvas.getActiveObject()
|
||
}else{
|
||
activeObject = MyCanvas.canvas.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.canvas.discardActiveObject() // 取消选择
|
||
clonedObj.set({
|
||
left: clonedObj.left,
|
||
top: clonedObj.top,
|
||
selectable: true
|
||
})
|
||
if (clonedObj.type === 'activeSelection') {
|
||
// 活动选择需要一个对画布的引用
|
||
clonedObj.forEachObject((obj)=>{
|
||
MyCanvas.canvas.add(obj)
|
||
})
|
||
|
||
clonedObj.setCoords()
|
||
} else {
|
||
MyCanvas.canvas.add(clonedObj)
|
||
// this.layer.selectLayer.group.add(clonedObj)
|
||
}
|
||
MyCanvas.canvas.setActiveObject(clonedObj)
|
||
MyCanvas.canvas.requestRenderAll()
|
||
})
|
||
this._clipboard = null
|
||
this.updateCanvasState()
|
||
}
|
||
isSelectable(obj){//判断元素是否允许选中
|
||
return (obj.custom?.type != 'layer' && (!obj.custom?.isSelectable || this.layer.selectLayer.group.custom.groupType == 'Grid') && !obj.isType('path'))
|
||
//isSelectable已废弃,现在isSelectable作为判断是否是背景来使用
|
||
return (obj.custom?.type != 'layer' && !obj.isType('path'))
|
||
}
|
||
isAddToLayer(obj){//判断元素是否允许添加
|
||
return(obj.custom?.type != 'layer' && obj.custom?.layerId == this.layer.selectLayer.id)
|
||
}
|
||
//撤回反撤回
|
||
//设置画布监听修改添加事件,用来做撤回功能
|
||
updateCanvasState(str){
|
||
let canvasData = MyCanvas.canvas.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.canvas.loadFromJSON(this.canvasState, () => {});
|
||
MyCanvas.canvas.setBackgroundColor({
|
||
source:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC',
|
||
repeat: 'repeat',
|
||
},MyCanvas.canvas.renderAll.bind(MyCanvas.canvas),
|
||
)
|
||
}
|
||
temporarilyExport(data){
|
||
let scaleXY = {
|
||
scaleX:data?.scaleX?data?.scaleX:1,
|
||
scaleY:data?.scaleY?data?.scaleY:1,
|
||
}
|
||
let width = data?.width || MyCanvas.canvas.width
|
||
let height = data?.height || MyCanvas.canvas.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
|
||
}
|
||
//导出
|
||
selectExport(){
|
||
let layer = this.layer.list.filter(item=>item.id == this.layer.selectLayer.id)[0]
|
||
return layer.img
|
||
}
|
||
allExport(){
|
||
let exportCanvas = this.temporarilyExport()
|
||
MyCanvas.canvas.forEachObject((obj) =>{
|
||
if(obj.custom?.layerId != -1){
|
||
obj.clone((cloned)=>{
|
||
this.setClone(obj,cloned)
|
||
exportCanvas.add(cloned)
|
||
})
|
||
|
||
}
|
||
});
|
||
let data = exportCanvas.toDataURL("image/png");
|
||
this.closeTemporarilyExport(exportCanvas)
|
||
return data
|
||
}
|
||
}
|
||
export default new MyCanvas() |