深度画布缩略图
This commit is contained in:
@@ -52,7 +52,8 @@ export class CanvasManager {
|
||||
this.canvas.setWidth(this.canvasViewWidth)
|
||||
this.canvas.setHeight(this.canvasViewHeight)
|
||||
}
|
||||
initCanvas(options: CanvasInitOptions) {
|
||||
/** 初始化画布 */
|
||||
async initCanvas(options: CanvasInitOptions) {
|
||||
this.layerManager = this.stateManager.layerManager
|
||||
this.canvasWidth = options.canvasWidth || 750
|
||||
this.canvasHeight = options.canvasHeight || 600
|
||||
@@ -84,29 +85,35 @@ export class CanvasManager {
|
||||
this.setupCanvasEvents()
|
||||
this.setupBrushEvents()
|
||||
|
||||
|
||||
this.stateManager.setIsRecord(false)
|
||||
// 创建矩形
|
||||
const rect = this.layerManager.createRectLayer({
|
||||
const rect = await this.layerManager.createRectLayer({
|
||||
left: 400,
|
||||
top: 100,
|
||||
})
|
||||
//创建圆形
|
||||
const circle = this.layerManager.createCircleLayer({
|
||||
const circle = await this.layerManager.createCircleLayer({
|
||||
left: 200,
|
||||
top: 200,
|
||||
})
|
||||
// 文字
|
||||
const text = this.layerManager.createTextLayer('Hello World');
|
||||
const text = await this.layerManager.createTextLayer('Hello World');
|
||||
this.layerManager.updateLayers()
|
||||
this.layerManager.setActiveID(text.info.id)
|
||||
this.stateManager.setIsRecord(true)
|
||||
this.stateManager.recordState()
|
||||
// this.stateManager.toolManager.setTool(OperationType.RECTANGLE)
|
||||
}
|
||||
/** 画布添加对象 */
|
||||
add(obj: any, isUpdate = true) {
|
||||
async add(obj: any, isUpdate = true) {
|
||||
this.canvas.add(obj)
|
||||
const id = obj?.info?.id || ""
|
||||
if (isUpdate) {
|
||||
this.layerManager.updateLayers()
|
||||
this.renderAll()
|
||||
if (id) await this.layerManager.updateLayerThumbnailsById(id)
|
||||
this.stateManager.recordState()
|
||||
}
|
||||
}
|
||||
/** 画布移除对象 */
|
||||
@@ -134,7 +141,6 @@ export class CanvasManager {
|
||||
/** 设置激活对象 */
|
||||
setActiveObjectById(id: string) {
|
||||
const obj = this.getObjectById(id)
|
||||
console.log(obj)
|
||||
if (obj) this.canvas.setActiveObject(obj)
|
||||
this.renderAll()
|
||||
}
|
||||
@@ -164,12 +170,7 @@ export class CanvasManager {
|
||||
this.canvas.moveTo(this.getObjectById(id), newIndex)
|
||||
this.layerManager.updateLayers()
|
||||
this.renderAll()
|
||||
}
|
||||
getBitObjects() {
|
||||
return this.getObjects().map(v => {
|
||||
const object = v.toJSON("info");
|
||||
return object
|
||||
})
|
||||
this.stateManager.recordState()
|
||||
}
|
||||
|
||||
/** 画笔事件 */
|
||||
@@ -189,7 +190,7 @@ export class CanvasManager {
|
||||
if (activeLayer) {
|
||||
this.layerManager.imageMergeToLayer(activeLayer, fabricImage)
|
||||
} else {
|
||||
const emptyLayer = this.layerManager.createEmptyLayer();
|
||||
const emptyLayer = this.layerManager.createEmptyLayer(false);
|
||||
this.layerManager.setActiveID(emptyLayer.info.id, false)
|
||||
this.layerManager.imageMergeToLayer(emptyLayer, fabricImage)
|
||||
}
|
||||
|
||||
@@ -29,13 +29,21 @@ export class LayerManager {
|
||||
const layer = this.getLayerById(id)
|
||||
if (layer) {
|
||||
layer.info.name = name
|
||||
}
|
||||
const object = this.canvasManager.getObjectById(id)
|
||||
if (object) {
|
||||
object.info.name = name
|
||||
this.canvasManager.renderAll()
|
||||
}
|
||||
}
|
||||
setLayerVisibleById(id, visible: boolean) {
|
||||
const layer = this.getLayerById(id)
|
||||
if (layer) {
|
||||
layer.set({
|
||||
layer.visible = visible
|
||||
}
|
||||
const object = this.canvasManager.getObjectById(id)
|
||||
if (object) {
|
||||
object.set({
|
||||
visible: visible
|
||||
})
|
||||
this.canvasManager.renderAll()
|
||||
@@ -46,6 +54,7 @@ export class LayerManager {
|
||||
if (id === this.activeID.value && isActive) {
|
||||
this.setActiveID(this.layers.value[0]?.info?.id || "")
|
||||
}
|
||||
if (isActive) this.stateManager.recordState()
|
||||
}
|
||||
// 拖拽排序
|
||||
dragSort(id, newIndex) {
|
||||
@@ -61,24 +70,24 @@ export class LayerManager {
|
||||
}
|
||||
|
||||
/** 设置图层位置-不设置默认居中 */
|
||||
setLayerPosition(layer, options?: any) {
|
||||
setLayerPosition(object, options?: any) {
|
||||
const width = this.canvasManager.canvasWidth
|
||||
const height = this.canvasManager.canvasHeight
|
||||
|
||||
if (options && options.top !== undefined) {
|
||||
layer.set({ top: options.top })
|
||||
object.set({ top: options.top })
|
||||
} else {
|
||||
layer.set({ top: height / 2 - layer.height * layer.scaleY / 2 })
|
||||
object.set({ top: height / 2 - object.height * object.scaleY / 2 })
|
||||
}
|
||||
if (options && options.left !== undefined) {
|
||||
layer.set({ left: options.left })
|
||||
object.set({ left: options.left })
|
||||
} else {
|
||||
layer.set({ left: width / 2 - layer.width * layer.scaleX / 2 })
|
||||
object.set({ left: width / 2 - object.width * object.scaleX / 2 })
|
||||
}
|
||||
}
|
||||
/** 创建空图层 */
|
||||
createEmptyLayer() {
|
||||
const emptyLayer = new fabric.Rect({
|
||||
createEmptyLayer(isUpdate = true) {
|
||||
const emptyObject = new fabric.Rect({
|
||||
width: 0,
|
||||
height: 0,
|
||||
fill: 'transparent',
|
||||
@@ -87,13 +96,13 @@ export class LayerManager {
|
||||
name: '空图层',
|
||||
}
|
||||
})
|
||||
this.setLayerPosition(emptyLayer)
|
||||
this.canvasManager.add(emptyLayer)
|
||||
return emptyLayer
|
||||
this.setLayerPosition(emptyObject)
|
||||
this.canvasManager.add(emptyObject, isUpdate)
|
||||
return emptyObject
|
||||
}
|
||||
/** 创建文本图层 */
|
||||
createTextLayer(text: string, options?: any) {
|
||||
const textLayer = new fabric.IText(text, {
|
||||
async createTextLayer(text: string, options?: any) {
|
||||
const textObject = new fabric.IText(text, {
|
||||
fontSize: 24,
|
||||
fill: '#000',
|
||||
...(options || {}),
|
||||
@@ -103,13 +112,13 @@ export class LayerManager {
|
||||
...(options?.info || {}),
|
||||
}
|
||||
})
|
||||
this.setLayerPosition(textLayer, options)
|
||||
this.canvasManager.add(textLayer)
|
||||
return textLayer
|
||||
this.setLayerPosition(textObject, options)
|
||||
await this.canvasManager.add(textObject)
|
||||
return textObject
|
||||
}
|
||||
/** 创建矩形图层 */
|
||||
createRectLayer(options?: any, isActive = false) {
|
||||
const rectLayer = new fabric.Rect({
|
||||
async createRectLayer(options?: any, isActive = false) {
|
||||
const rectObject = new fabric.Rect({
|
||||
width: 100,
|
||||
height: 100,
|
||||
fill: '#000',
|
||||
@@ -120,14 +129,14 @@ export class LayerManager {
|
||||
...(options?.info || {}),
|
||||
}
|
||||
})
|
||||
this.setLayerPosition(rectLayer, options)
|
||||
this.canvasManager.add(rectLayer)
|
||||
if (isActive) this.setActiveID(rectLayer.info.id)
|
||||
return rectLayer
|
||||
this.setLayerPosition(rectObject, options)
|
||||
await this.canvasManager.add(rectObject)
|
||||
if (isActive) this.setActiveID(rectObject.info.id)
|
||||
return rectObject
|
||||
}
|
||||
/** 创建圆形图层 */
|
||||
createCircleLayer(options?: any, isActive = false) {
|
||||
const circleLayer = new fabric.Circle({
|
||||
async createCircleLayer(options?: any, isActive = false) {
|
||||
const circleObject = new fabric.Circle({
|
||||
radius: 50,
|
||||
fill: '#000',
|
||||
...(options || {}),
|
||||
@@ -137,17 +146,17 @@ export class LayerManager {
|
||||
...(options?.info || {}),
|
||||
}
|
||||
})
|
||||
this.setLayerPosition(circleLayer, options)
|
||||
this.canvasManager.add(circleLayer)
|
||||
if (isActive) this.setActiveID(circleLayer.info.id)
|
||||
return circleLayer
|
||||
this.setLayerPosition(circleObject, options)
|
||||
await this.canvasManager.add(circleObject)
|
||||
if (isActive) this.setActiveID(circleObject.info.id)
|
||||
return circleObject
|
||||
}
|
||||
/** 创建图片图层 */
|
||||
async createImageLayer(imgOrUrl: string | HTMLImageElement, options?: any) {
|
||||
const canvasWidth = this.canvasManager.canvasWidth
|
||||
const canvasHeight = this.canvasManager.canvasHeight
|
||||
|
||||
const imageLayer = await new Promise((resolve) => {
|
||||
const imageObject = await new Promise((resolve) => {
|
||||
const url = typeof imgOrUrl === 'string' ? imgOrUrl : imgOrUrl.src
|
||||
fabric.Image.fromURL(url, (img) => {
|
||||
const width = img.width
|
||||
@@ -168,10 +177,10 @@ export class LayerManager {
|
||||
resolve(img)
|
||||
})
|
||||
}) as fabric.Object
|
||||
this.setLayerPosition(imageLayer, options)
|
||||
this.canvasManager.add(imageLayer)
|
||||
this.setActiveID(imageLayer.info.id)
|
||||
return imageLayer
|
||||
this.setLayerPosition(imageObject, options)
|
||||
await this.canvasManager.add(imageObject)
|
||||
this.setActiveID(imageObject.info.id)
|
||||
return imageObject
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +205,7 @@ export class LayerManager {
|
||||
const index = this.canvasManager.getObjects().indexOf(targetLayer);
|
||||
this.deleteLayerById(targetLayer.info.id, false)
|
||||
this.setActiveID(mergedImage.info.id, false)
|
||||
this.canvasManager.add(mergedImage, false);
|
||||
await this.canvasManager.add(mergedImage);
|
||||
this.canvasManager.canvas.moveTo(mergedImage, index);
|
||||
this.canvasManager.renderAll()
|
||||
this.updateLayers()
|
||||
@@ -216,13 +225,8 @@ export class LayerManager {
|
||||
const object = this.canvasManager.getObjectById(id);
|
||||
if (!object) return;
|
||||
const url = await exportObjectToThumbnail(object);
|
||||
object.set({
|
||||
thumbnail: url
|
||||
})
|
||||
// object.thumbnail = url
|
||||
object.thumbnail = url
|
||||
this.updateLayers()
|
||||
// this.canvasManager.renderAll()
|
||||
|
||||
}
|
||||
|
||||
dispose() { }
|
||||
|
||||
@@ -37,7 +37,10 @@ export class StateManager {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 设置是否开始记录状态 */
|
||||
setIsRecord(isRecord: boolean) {
|
||||
this.running.value = !isRecord
|
||||
}
|
||||
/** 清空状态 */
|
||||
clearState(isRecordCurrentState?: boolean) {
|
||||
this.historyList.value = []
|
||||
|
||||
@@ -40,7 +40,8 @@ export class BrushManager {
|
||||
this.brushStore = new BrushState();
|
||||
this.layerManager = options.layerManager; // 添加图层管理器引用
|
||||
this.brushIndicator = options.brushIndicator; // 添加笔刷指示器引用
|
||||
this.t = options.t
|
||||
// this.t = options.t
|
||||
this.t = (v) => v
|
||||
|
||||
// 当前活动笔刷
|
||||
this.activeBrush = null;
|
||||
|
||||
@@ -728,14 +728,14 @@ export class CanvasEventManager {
|
||||
// console.log("object:skewing", e);
|
||||
updateLayers(e);
|
||||
});
|
||||
this.canvas.on("object:modified", (e) => {
|
||||
this.canvas.on("object:modified", async (e) => {
|
||||
updateLayers(e);
|
||||
const id = e.target?.info?.id;
|
||||
if (id) await this.layerManager.updateLayerThumbnailsById(id)
|
||||
this.stateManager.recordState();
|
||||
this.layerManager.updateLayerThumbnailsById(e.target.info.id);
|
||||
});
|
||||
this.canvas.on("object:removed", (e) => {
|
||||
updateLayers(e);
|
||||
this.stateManager.recordState();
|
||||
});
|
||||
}
|
||||
setupDoubleClickEvents() {
|
||||
|
||||
@@ -11,6 +11,7 @@ export async function cloneObjects(objects = []) {
|
||||
height: obj.height,
|
||||
scaleX: obj.scaleX,
|
||||
scaleY: obj.scaleY,
|
||||
angle: obj.angle,
|
||||
})
|
||||
resolve(v)
|
||||
})
|
||||
@@ -26,10 +27,11 @@ export async function getObjectsBoundingBox(objects = []) {
|
||||
const box1 = { x: Infinity, y: Infinity }
|
||||
const box2 = { x: -Infinity, y: -Infinity }
|
||||
objects.forEach(obj => {
|
||||
box1.x = Math.min(box1.x, obj.left)
|
||||
box1.y = Math.min(box1.y, obj.top)
|
||||
box2.x = Math.max(box2.x, obj.left + obj.width * obj.scaleX)
|
||||
box2.y = Math.max(box2.y, obj.top + obj.height * obj.scaleY)
|
||||
const rect = obj.getBoundingRect()
|
||||
box1.x = Math.min(box1.x, rect.left)
|
||||
box1.y = Math.min(box1.y, rect.top)
|
||||
box2.x = Math.max(box2.x, rect.left + rect.width)
|
||||
box2.y = Math.max(box2.y, rect.top + rect.height)
|
||||
})
|
||||
return {
|
||||
left: box1.x,
|
||||
|
||||
Reference in New Issue
Block a user