UNPKG

react-design-editor

Version:

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

355 lines (354 loc) 15.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fabric_1 = require("fabric"); class WorkareaHandler { constructor(handler) { /** * Set the layout on workarea * @param {WorkareaLayout} layout * @returns */ this.setLayout = (layout) => { this.handler.workarea.set('layout', layout); const { _element, isElement, workareaWidth, workareaHeight } = this.handler.workarea; const { canvas } = this.handler; let scaleX = 1; let scaleY = 1; const isFixed = layout === 'fixed'; const isResponsive = layout === 'responsive'; const isFullscreen = layout === 'fullscreen'; if (isElement) { if (isFixed) { scaleX = workareaWidth / _element.width; scaleY = workareaHeight / _element.height; } else if (isResponsive) { const scales = this.calculateScale(); scaleX = scales.scaleX; scaleY = scales.scaleY; } else { scaleX = canvas.getWidth() / _element.width; scaleY = canvas.getHeight() / _element.height; } } this.handler.getObjects().forEach(obj => { const { id, player } = obj; if (id !== 'workarea') { const objScaleX = !isFullscreen ? 1 : scaleX; const objScaleY = !isFullscreen ? 1 : scaleY; const objWidth = obj.width * objScaleX * canvas.getZoom(); const objHeight = obj.height * objScaleY * canvas.getZoom(); const el = this.handler.elementHandler.findById(obj.id); this.handler.elementHandler.setSize(el, obj); if (player) { player.setPlayerSize(objWidth, objHeight); } obj.set({ scaleX: !isFullscreen ? 1 : objScaleX, scaleY: !isFullscreen ? 1 : objScaleY, }); } }); if (isResponsive) { const center = canvas.getCenter(); if (isElement) { this.handler.workarea.set({ scaleX: 1, scaleY: 1, }); this.handler.zoomHandler.zoomToPoint(new fabric_1.fabric.Point(center.left, center.top), scaleX); } else { this.handler.workarea.set({ width: workareaWidth, height: workareaHeight, }); scaleX = canvas.getWidth() / workareaWidth; scaleY = canvas.getHeight() / workareaHeight; if (workareaHeight >= workareaWidth) { scaleX = scaleY; } else { scaleY = scaleX; } this.handler.zoomHandler.zoomToPoint(new fabric_1.fabric.Point(center.left, center.top), scaleX); } canvas.centerObject(this.handler.workarea); canvas.renderAll(); return; } if (isElement) { this.handler.workarea.set({ width: _element.width, height: _element.height, scaleX, scaleY, }); } else { const width = isFixed ? workareaWidth : this.handler.canvas.getWidth(); const height = isFixed ? workareaHeight : this.handler.canvas.getHeight(); this.handler.workarea.set({ width, height, backgroundColor: 'rgba(255, 255, 255, 1)', }); this.handler.canvas.renderAll(); if (isFixed) { canvas.centerObject(this.handler.workarea); } else { this.handler.workarea.set({ left: 0, top: 0, }); } } canvas.centerObject(this.handler.workarea); const center = canvas.getCenter(); canvas.setViewportTransform([1, 0, 0, 1, 0, 0]); this.handler.zoomHandler.zoomToPoint(new fabric_1.fabric.Point(center.left, center.top), 1); canvas.renderAll(); }; /** * Set the responsive image on Workarea * @param {string | File} [source] * @param {boolean} [loaded] * @returns */ this.setResponsiveImage = async (source, loaded) => { const imageFromUrl = async (src = '') => { return new Promise(resolve => { fabric_1.fabric.Image.fromURL(src, (img) => { const { canvas, workarea, editable } = this.handler; const { workareaWidth, workareaHeight } = workarea; const { scaleX, scaleY } = this.calculateScale(img); if (img._element) { workarea.set({ ...img, isElement: true, selectable: false, }); } else { const image = new Image(workareaWidth, workareaHeight); workarea.setElement(image); workarea.set({ isElement: false, selectable: false, width: workareaWidth, height: workareaHeight, }); } if (editable && !loaded) { canvas.getObjects().forEach(obj => { const { id, player } = obj; if (id !== 'workarea') { const objWidth = obj.width * scaleX; const objHeight = obj.height * scaleY; const el = this.handler.elementHandler.findById(id); this.handler.elementHandler.setScaleOrAngle(el, obj); this.handler.elementHandler.setSize(el, obj); if (player) { player.setPlayerSize(objWidth, objHeight); } obj.set({ scaleX: 1, scaleY: 1, }); obj.setCoords(); } }); } // 파일이 없을 경우 Canvas의 nextWidth, nextHeight 값이 변경되기 전 상태에서 zoomToFit이 동작함 // 정상 동작 resize event logic => zoomToFit // 현재 동작 zoomToFit -> resize event logic this.handler.zoomHandler.zoomToFit(); canvas.centerObject(workarea); resolve(workarea); }); }); }; const { workarea } = this.handler; if (!source) { workarea.set({ src: null, file: null, }); return imageFromUrl(source); } if (source instanceof File) { return new Promise(resolve => { const reader = new FileReader(); reader.onload = () => { workarea.set({ file: source, }); imageFromUrl(reader.result).then(resolve); }; reader.readAsDataURL(source); }); } else { workarea.set({ src: source, }); return imageFromUrl(source); } }; /** * Set the image on Workarea * @param {string | File} source * @param {boolean} [loaded=false] * @returns */ this.setImage = async (source, loaded = false) => { const { canvas, workarea, editable } = this.handler; if (workarea.layout === 'responsive') { return this.setResponsiveImage(source, loaded); } const imageFromUrl = async (src) => { return new Promise(resolve => { fabric_1.fabric.Image.fromURL(src, (img) => { let width = canvas.getWidth(); let height = canvas.getHeight(); if (workarea.layout === 'fixed') { width = workarea.width * workarea.scaleX; height = workarea.height * workarea.scaleY; } let scaleX = 1; let scaleY = 1; if (img._element) { scaleX = width / img.width; scaleY = height / img.height; img.set({ originX: 'left', originY: 'top', scaleX, scaleY, }); workarea.set({ ...img, isElement: true, selectable: false, }); } else { workarea.setElement(new Image()); workarea.set({ width, height, scaleX, scaleY, isElement: false, selectable: false, }); } canvas.centerObject(workarea); if (editable && !loaded) { const { layout } = workarea; canvas.getObjects().forEach(obj => { const { id, player } = obj; if (id !== 'workarea') { scaleX = layout === 'fullscreen' ? scaleX : obj.scaleX; scaleY = layout === 'fullscreen' ? scaleY : obj.scaleY; const el = this.handler.elementHandler.findById(id); this.handler.elementHandler.setSize(el, obj); if (player) { const objWidth = obj.width * scaleX; const objHeight = obj.height * scaleY; player.setPlayerSize(objWidth, objHeight); } obj.set({ scaleX, scaleY, }); obj.setCoords(); } }); } const center = canvas.getCenter(); const zoom = loaded || workarea.layout === 'fullscreen' ? 1 : this.handler.canvas.getZoom(); canvas.setViewportTransform([1, 0, 0, 1, 0, 0]); this.handler.zoomHandler.zoomToPoint(new fabric_1.fabric.Point(center.left, center.top), zoom); canvas.renderAll(); resolve(workarea); }, { crossOrigin: 'anonymous' }); }); }; if (!source) { workarea.set({ src: null, file: null, }); return imageFromUrl(source); } if (source instanceof File) { return new Promise(resolve => { const reader = new FileReader(); reader.onload = () => { workarea.set({ file: source, }); imageFromUrl(reader.result).then(resolve); }; reader.readAsDataURL(source); }); } else { workarea.set({ src: source, }); return imageFromUrl(source); } }; /** * Calculate scale to the image * * @param {FabricImage} [image] * @returns */ this.calculateScale = (image) => { const { canvas, workarea } = this.handler; const { workareaWidth, workareaHeight } = workarea; const { _element } = image || workarea; const width = _element?.width || workareaWidth; const height = _element?.height || workareaHeight; let scaleX = canvas.getWidth() / width; let scaleY = canvas.getHeight() / height; if (height >= width) { scaleX = scaleY; if (canvas.getWidth() < width * scaleX) { scaleX = scaleX * (canvas.getWidth() / (width * scaleX)); } } else { scaleY = scaleX; if (canvas.getHeight() < height * scaleX) { scaleX = scaleX * (canvas.getHeight() / (height * scaleX)); } } return { scaleX, scaleY }; }; this.handler = handler; this.initialize(); } /** * Initialize workarea * * @author salgum1114 */ initialize() { const { workareaOption } = this.handler; const image = new Image(workareaOption.width, workareaOption.height); image.width = workareaOption.width; image.height = workareaOption.height; this.handler.workarea = new fabric_1.fabric.Image(image, workareaOption); this.handler.canvas.add(this.handler.workarea); this.handler.objects = this.handler.getObjects(); this.handler.canvas.centerObject(this.handler.workarea); this.handler.canvas.renderAll(); } } exports.default = WorkareaHandler;