Current Path : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/js/ui/stamp/uploader/src/crop/ |
Current File : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/js/ui/stamp/uploader/src/crop/crop.js |
import {BaseEvent, EventEmitter} from 'main.core.events'; import {Dom, Tag, Cache, Loc, Type, Event} from 'main.core'; import './css/style.css'; type PreviewOptions = { events: { [key: string]: (event: BaseEvent) => void, }, }; export default class Crop extends EventEmitter { cache = new Cache.MemoryCache(); constructor(options: PreviewOptions = {}) { super(); this.setEventNamespace('BX.UI.Stamp.Uploader.Crop'); this.subscribeFromOptions(options.events); this.setOptions(options); } static #loadImage(file: File | Blob): Promise<HTMLImageElement> { const fileReader = new FileReader(); return new Promise((resolve) => { fileReader.readAsDataURL(file); Event.bindOnce(fileReader, 'loadend', () => { const image = new Image(); image.src = fileReader.result; Event.bindOnce(image, 'load', () => { resolve(image); }); }); }); } setOptions(options: PreviewOptions) { this.cache.set('options', {...options}); } getOptions(): PreviewOptions { return this.cache.get('options', {}); } getDevicePixelRatio(): number { return window.devicePixelRatio; } getCanvas(): HTMLCanvasElement { const canvas = this.cache.remember('canvas', () => { return Tag.render` <canvas class="ui-stamp-uploader-crop-canvas"></canvas> `; }); const timeoutId = setTimeout(() => { if (Type.isDomNode(canvas.parentElement) && !this.cache.has('adjustCanvas')) { const parentRect = { width: canvas.parentElement.clientWidth, height: canvas.parentElement.clientHeight, }; if (parentRect.width > 0 && parentRect.height > 0) { void this.cache.remember('adjustCanvas', () => { const ratio = this.getDevicePixelRatio(); canvas.width = parentRect.width * ratio; canvas.height = parentRect.height * ratio; Dom.style(canvas, { width: `${parentRect.width}px`, height: `${parentRect.height}px`, }); const context2d = canvas.getContext('2d'); const {context2d: context2dOptions = {}} = this.getOptions(); if (Type.isPlainObject(context2dOptions)) { Object.assign(context2d, context2dOptions); } context2d.scale(ratio, ratio); }); } } clearTimeout(timeoutId); }); return canvas; } clear() { const canvas = this.getCanvas(); const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); } renderImage(file: File | Blob): Promise<any> { return Crop .#loadImage(file) .then((image: HTMLImageElement) => { const canvas: HTMLCanvasElement = this.getLayout(); const context2d: CanvasRenderingContext2D = canvas.getContext('2d'); const wRatio = canvas.clientWidth / image.width; const hRatio = canvas.clientHeight / image.height; const ratio = Math.min(wRatio, hRatio); const offsetX = (canvas.clientWidth - (image.width * ratio)) / 2; const offsetY = (canvas.clientHeight - (image.height * ratio)) / 2; this.clear(); context2d.drawImage( image, 0, 0, image.width, image.height, offsetX, offsetY, (image.width * ratio), (image.height * ratio), ); }); } getImagePreviewLayout(): HTMLDivElement { return this.cache.remember('cropLayout', () => { return Tag.render` <div class="ui-stamp-uploader-crop-image">${this.getCanvas()}</div> `; }); } getLayout(): HTMLDivElement { return this.cache.remember('layout', () => { return Tag.render` <div class="ui-stamp-uploader-crop" title="${Loc.getMessage('UI_STAMP_UPLOADER_PREVIEW_TITLE')}" > ${this.getImagePreviewLayout()} ${this.getCropControl()} </div> `; }); } getCropControl(): HTMLDivElement { return this.cache.remember('cropControl', () => { return Tag.render` <div class="ui-stamp-uploader-crop-control"> <div class="ui-stamp-uploader-crop-control-top"></div> <div class="ui-stamp-uploader-crop-control-right"></div> <div class="ui-stamp-uploader-crop-control-bottom"></div> <div class="ui-stamp-uploader-crop-control-left"></div> <div class="ui-stamp-uploader-crop-control-rotate"></div> </div> `; }); } show() { Dom.addClass(this.getLayout(), 'ui-stamp-uploader-crop-show'); } hide() { Dom.removeClass(this.getLayout(), 'ui-stamp-uploader-crop-show'); } }