UNPKG

@benson.liao/react-design-editor

Version:

Design Editor Tools with React.js + ant.design + fabric.js

262 lines (261 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fabric_1 = require("fabric"); class CropHandler { constructor(handler) { /** * Validate crop type * * @returns */ this.validType = () => { const activeObject = this.handler.canvas.getActiveObject(); if (!activeObject) { return false; } if (activeObject.type === 'image') { return true; } return false; }; /** * Start crop image * */ this.start = () => { if (this.validType()) { this.handler.interactionMode = 'crop'; this.cropObject = this.handler.canvas.getActiveObject(); const { left, top } = this.cropObject; this.cropRect = new fabric_1.fabric.Rect({ width: this.cropObject.width, height: this.cropObject.height, scaleX: this.cropObject.scaleX, scaleY: this.cropObject.scaleY, originX: 'left', originY: 'top', left, top, hasRotatingPoint: false, fill: 'rgba(0, 0, 0, 0.2)', }); this.handler.canvas.add(this.cropRect); this.handler.canvas.setActiveObject(this.cropRect); this.cropObject.selectable = false; this.cropObject.evented = false; this.handler.canvas.renderAll(); } }; /** * Finish crop image * */ this.finish = () => { const { left, top, width, height, scaleX, scaleY } = this.cropRect; const croppedImg = this.cropObject.toDataURL({ left: left - this.cropObject.left, top: top - this.cropObject.top, width: width * scaleX, height: height * scaleY, }); this.handler.setImage(this.cropObject, croppedImg); this.cancel(); }; /** * Cancel crop * */ this.cancel = () => { this.handler.interactionMode = 'selection'; this.cropObject.selectable = true; this.cropObject.evented = true; this.handler.canvas.setActiveObject(this.cropObject); this.handler.canvas.remove(this.cropRect); this.cropRect = null; this.cropObject = null; this.handler.canvas.renderAll(); }; /** * Resize crop * * @param {FabricEvent} opt */ this.resize = (opt) => { const { target, transform: { original, corner }, } = opt; const { left, top, width, height, scaleX, scaleY } = target; const { left: cropLeft, top: cropTop, width: cropWidth, height: cropHeight, scaleX: cropScaleX, scaleY: cropScaleY, } = this.cropObject; if (corner === 'tl') { if (Math.round(cropLeft) > Math.round(left)) { // left const originRight = Math.round(cropLeft + cropWidth); const targetRight = Math.round(target.getBoundingRect().left + target.getBoundingRect().width); const diffRightRatio = 1 - (originRight - targetRight) / cropWidth; target.set({ left: cropLeft, scaleX: diffRightRatio > 1 ? 1 : diffRightRatio, }); } if (Math.round(cropTop) > Math.round(top)) { // top const originBottom = Math.round(cropTop + cropHeight); const targetBottom = Math.round(target.getBoundingRect().top + target.getBoundingRect().height); const diffBottomRatio = 1 - (originBottom - targetBottom) / cropHeight; target.set({ top: cropTop, scaleY: diffBottomRatio > 1 ? 1 : diffBottomRatio, }); } } else if (corner === 'bl') { if (Math.round(cropLeft) > Math.round(left)) { // left const originRight = Math.round(cropLeft + cropWidth); const targetRight = Math.round(target.getBoundingRect().left + target.getBoundingRect().width); const diffRightRatio = 1 - (originRight - targetRight) / cropWidth; target.set({ left: cropLeft, scaleX: diffRightRatio > 1 ? 1 : diffRightRatio, }); } if (Math.round(cropTop + cropHeight * cropScaleY) < Math.round(top + height * scaleY)) { // bottom const diffTopRatio = 1 - (original.top - cropTop) / cropHeight; target.set({ top: original.top, scaleY: diffTopRatio > 1 ? 1 : diffTopRatio, }); } } else if (corner === 'tr') { if (Math.round(cropLeft + cropWidth * cropScaleX) < Math.round(left + width * scaleX)) { // right const diffLeftRatio = 1 - (original.left - cropLeft) / cropWidth; target.set({ left: original.left, scaleX: diffLeftRatio > 1 ? 1 : diffLeftRatio, }); } if (Math.round(cropTop) > Math.round(top)) { // top const originBottom = Math.round(cropTop + cropHeight); const targetBottom = Math.round(target.getBoundingRect().top + target.getBoundingRect().height); const diffBottomRatio = 1 - (originBottom - targetBottom) / cropHeight; target.set({ top: cropTop, scaleY: diffBottomRatio > 1 ? 1 : diffBottomRatio, }); } } else if (corner === 'br') { if (Math.round(cropLeft + cropWidth * cropScaleX) < Math.round(left + width * scaleX)) { // right const diffLeftRatio = 1 - (original.left - cropLeft) / cropWidth; target.set({ left: original.left, scaleX: diffLeftRatio > 1 ? 1 : diffLeftRatio, }); } if (Math.round(cropTop + cropHeight * cropScaleY) < Math.round(top + height * scaleY)) { // bottom const diffTopRatio = 1 - (original.top - cropTop) / cropHeight; target.set({ top: original.top, scaleY: diffTopRatio > 1 ? 1 : diffTopRatio, }); } } else if (corner === 'ml') { if (Math.round(cropLeft) > Math.round(left)) { // left const originRight = Math.round(cropLeft + cropWidth); const targetRight = Math.round(target.getBoundingRect().left + target.getBoundingRect().width); const diffRightRatio = 1 - (originRight - targetRight) / cropWidth; target.set({ left: cropLeft, scaleX: diffRightRatio > 1 ? 1 : diffRightRatio, }); } } else if (corner === 'mt') { if (Math.round(cropTop) > Math.round(top)) { // top const originBottom = Math.round(cropTop + cropHeight); const targetBottom = Math.round(target.getBoundingRect().top + target.getBoundingRect().height); const diffBottomRatio = 1 - (originBottom - targetBottom) / cropHeight; target.set({ top: cropTop, scaleY: diffBottomRatio > 1 ? 1 : diffBottomRatio, }); } } else if (corner === 'mb') { if (Math.round(cropTop + cropHeight * cropScaleY) < Math.round(top + height * scaleY)) { // bottom const diffTopRatio = 1 - (original.top - cropTop) / cropHeight; target.set({ top: original.top, scaleY: diffTopRatio > 1 ? 1 : diffTopRatio, }); } } else if (corner === 'mr') { if (Math.round(cropLeft + cropWidth * cropScaleX) < Math.round(left + width * scaleX)) { // right const diffLeftRatio = 1 - (original.left - cropLeft) / cropWidth; target.set({ left: original.left, scaleX: diffLeftRatio > 1 ? 1 : diffLeftRatio, }); } } }; /** * Resize crop * * @param {FabricEvent} opt */ this.moving = (opt) => { const { target } = opt; const { left, top, width, height, scaleX, scaleY } = target; const { left: cropLeft, top: cropTop, width: cropWidth, height: cropHeight, } = this.cropObject.getBoundingRect(); const movedTop = () => { if (Math.round(cropTop) >= Math.round(top)) { target.set({ top: cropTop, }); } else if (Math.round(cropTop + cropHeight) <= Math.round(top + height * scaleY)) { target.set({ top: cropTop + cropHeight - height * scaleY, }); } }; if (Math.round(cropLeft) >= Math.round(left)) { target.set({ left: Math.max(left, cropLeft), }); movedTop(); } else if (Math.round(cropLeft + cropWidth) <= Math.round(left + width * scaleX)) { target.set({ left: cropLeft + cropWidth - width * scaleX, }); movedTop(); } else if (Math.round(cropTop) >= Math.round(top)) { target.set({ top: cropTop, }); } else if (Math.round(cropTop + cropHeight) <= Math.round(top + height * scaleY)) { target.set({ top: cropTop + cropHeight - height * scaleY, }); } }; this.handler = handler; this.cropRect = null; this.cropObject = null; } } exports.default = CropHandler;