PHP Classes

File: plugins/Crop/src/cropit.js

Recommend this page to a friend!
  Classes of Laudir Bispo   PHP Real Estate Website   plugins/Crop/src/cropit.js   Download  
File: plugins/Crop/src/cropit.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: PHP Real Estate Website
Manage the properties of a real estate business
Author: By
Last change:
Date: 3 years ago
Size: 17,098 bytes
 

Contents

Class file image Download
import $ from 'jquery'; import Zoomer from './Zoomer'; import { CLASS_NAMES, ERRORS, EVENTS } from './constants'; import { loadDefaults } from './options'; import { exists, round } from './utils'; class Cropit { constructor(jQuery, element, options) { this.$el = $(element); const defaults = loadDefaults(this.$el); this.options = $.extend({}, defaults, options); this.init(); } init() { this.image = new Image(); this.preImage = new Image(); this.image.onload = this.onImageLoaded.bind(this); this.preImage.onload = this.onPreImageLoaded.bind(this); this.image.onerror = this.preImage.onerror = () => { this.onImageError.call(this, ERRORS.IMAGE_FAILED_TO_LOAD); }; this.$preview = this.options.$preview.css('position', 'relative'); this.$fileInput = this.options.$fileInput.attr({ accept: 'image/*' }); this.$zoomSlider = this.options.$zoomSlider.attr({ min: 0, max: 1, step: 0.01 }); this.previewSize = { width: this.options.width || this.$preview.innerWidth(), height: this.options.height || this.$preview.innerHeight(), }; this.$image = $('<img />') .addClass(CLASS_NAMES.PREVIEW_IMAGE) .attr('alt', '') .css({ transformOrigin: 'top left', webkitTransformOrigin: 'top left', willChange: 'transform', }); this.$imageContainer = $('<div />') .addClass(CLASS_NAMES.PREVIEW_IMAGE_CONTAINER) .css({ position: 'absolute', overflow: 'hidden', left: 0, top: 0, width: '100%', height: '100%', }) .append(this.$image); this.$preview.append(this.$imageContainer); if (this.options.imageBackground) { if ($.isArray(this.options.imageBackgroundBorderWidth)) { this.bgBorderWidthArray = this.options.imageBackgroundBorderWidth; } else { this.bgBorderWidthArray = [0, 1, 2, 3].map(() => this.options.imageBackgroundBorderWidth); } this.$bg = $('<img />') .addClass(CLASS_NAMES.PREVIEW_BACKGROUND) .attr('alt', '') .css({ position: 'relative', left: this.bgBorderWidthArray[3], top: this.bgBorderWidthArray[0], transformOrigin: 'top left', webkitTransformOrigin: 'top left', willChange: 'transform', }); this.$bgContainer = $('<div />') .addClass(CLASS_NAMES.PREVIEW_BACKGROUND_CONTAINER) .css({ position: 'absolute', zIndex: 0, top: -this.bgBorderWidthArray[0], right: -this.bgBorderWidthArray[1], bottom: -this.bgBorderWidthArray[2], left: -this.bgBorderWidthArray[3], }) .append(this.$bg); if (this.bgBorderWidthArray[0] > 0) { this.$bgContainer.css('overflow', 'hidden'); } this.$preview.prepend(this.$bgContainer); } this.initialZoom = this.options.initialZoom; this.imageLoaded = false; this.moveContinue = false; this.zoomer = new Zoomer(); if (this.options.allowDragNDrop) { $.event.props.push('dataTransfer'); } this.bindListeners(); if (this.options.imageState && this.options.imageState.src) { this.loadImage(this.options.imageState.src); } } bindListeners() { this.$fileInput.on('change.cropit', this.onFileChange.bind(this)); this.$imageContainer.on(EVENTS.PREVIEW, this.onPreviewEvent.bind(this)); this.$zoomSlider.on(EVENTS.ZOOM_INPUT, this.onZoomSliderChange.bind(this)); if (this.options.allowDragNDrop) { this.$imageContainer.on('dragover.cropit dragleave.cropit', this.onDragOver.bind(this)); this.$imageContainer.on('drop.cropit', this.onDrop.bind(this)); } } unbindListeners() { this.$fileInput.off('change.cropit'); this.$imageContainer.off(EVENTS.PREVIEW); this.$imageContainer.off('dragover.cropit dragleave.cropit drop.cropit'); this.$zoomSlider.off(EVENTS.ZOOM_INPUT); } onFileChange(e) { this.options.onFileChange(e); if (this.$fileInput.get(0).files) { this.loadFile(this.$fileInput.get(0).files[0]); } } loadFile(file) { const fileReader = new FileReader(); if (file && file.type.match('image')) { fileReader.readAsDataURL(file); fileReader.onload = this.onFileReaderLoaded.bind(this); fileReader.onerror = this.onFileReaderError.bind(this); } else if (file) { this.onFileReaderError(); } } onFileReaderLoaded(e) { this.loadImage(e.target.result); } onFileReaderError() { this.options.onFileReaderError(); } onDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; this.$preview.toggleClass(CLASS_NAMES.DRAG_HOVERED, e.type === 'dragover'); } onDrop(e) { e.preventDefault(); e.stopPropagation(); const files = Array.prototype.slice.call(e.dataTransfer.files, 0); files.some((file) => { if (!file.type.match('image')) { return false; } this.loadFile(file); return true; }); this.$preview.removeClass(CLASS_NAMES.DRAG_HOVERED); } loadImage(imageSrc) { if (!imageSrc) { return; } this.options.onImageLoading(); this.setImageLoadingClass(); if (imageSrc.indexOf('data') === 0) { this.preImage.src = imageSrc; } else { const xhr = new XMLHttpRequest(); xhr.onload = (e) => { if (e.target.status >= 300) { this.onImageError.call(this, ERRORS.IMAGE_FAILED_TO_LOAD); return; } this.loadFile(e.target.response); }; xhr.open('GET', imageSrc); xhr.responseType = 'blob'; xhr.send(); } } onPreImageLoaded() { if (this.shouldRejectImage({ imageWidth: this.preImage.width, imageHeight: this.preImage.height, previewSize: this.previewSize, maxZoom: this.options.maxZoom, exportZoom: this.options.exportZoom, smallImage: this.options.smallImage, })) { this.onImageError(ERRORS.SMALL_IMAGE); if (this.image.src) { this.setImageLoadedClass(); } return; } this.image.src = this.preImage.src; } onImageLoaded() { this.rotation = 0; this.setupZoomer(this.options.imageState && this.options.imageState.zoom || this._initialZoom); if (this.options.imageState && this.options.imageState.offset) { this.offset = this.options.imageState.offset; } else { this.centerImage(); } this.options.imageState = {}; this.$image.attr('src', this.image.src); if (this.options.imageBackground) { this.$bg.attr('src', this.image.src); } this.setImageLoadedClass(); this.imageLoaded = true; this.options.onImageLoaded(); } onImageError() { this.options.onImageError.apply(this, arguments); this.removeImageLoadingClass(); } setImageLoadingClass() { this.$preview .removeClass(CLASS_NAMES.IMAGE_LOADED) .addClass(CLASS_NAMES.IMAGE_LOADING); } setImageLoadedClass() { this.$preview .removeClass(CLASS_NAMES.IMAGE_LOADING) .addClass(CLASS_NAMES.IMAGE_LOADED); } removeImageLoadingClass() { this.$preview .removeClass(CLASS_NAMES.IMAGE_LOADING); } getEventPosition(e) { if (e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]) { e = e.originalEvent.touches[0]; } if (e.clientX && e.clientY) { return { x: e.clientX, y: e.clientY }; } } onPreviewEvent(e) { if (!this.imageLoaded) { return; } this.moveContinue = false; this.$imageContainer.off(EVENTS.PREVIEW_MOVE); if (e.type === 'mousedown' || e.type === 'touchstart') { this.origin = this.getEventPosition(e); this.moveContinue = true; this.$imageContainer.on(EVENTS.PREVIEW_MOVE, this.onMove.bind(this)); } else { $(document.body).focus(); } e.stopPropagation(); return false; } onMove(e) { const eventPosition = this.getEventPosition(e); if (this.moveContinue && eventPosition) { this.offset = { x: this.offset.x + eventPosition.x - this.origin.x, y: this.offset.y + eventPosition.y - this.origin.y, }; } this.origin = eventPosition; e.stopPropagation(); return false; } set offset(position) { if (!position || !exists(position.x) || !exists(position.y)) { return; } this._offset = this.fixOffset(position); this.renderImage(); this.options.onOffsetChange(position); } fixOffset(offset) { if (!this.imageLoaded) { return offset; } const ret = { x: offset.x, y: offset.y }; if (!this.options.freeMove) { if (this.imageWidth * this.zoom >= this.previewSize.width) { ret.x = Math.min(0, Math.max(ret.x, this.previewSize.width - this.imageWidth * this.zoom)); } else { ret.x = Math.max(0, Math.min(ret.x, this.previewSize.width - this.imageWidth * this.zoom)); } if (this.imageHeight * this.zoom >= this.previewSize.height) { ret.y = Math.min(0, Math.max(ret.y, this.previewSize.height - this.imageHeight * this.zoom)); } else { ret.y = Math.max(0, Math.min(ret.y, this.previewSize.height - this.imageHeight * this.zoom)); } } ret.x = round(ret.x); ret.y = round(ret.y); return ret; } centerImage() { if (!this.image.width || !this.image.height || !this.zoom) { return; } this.offset = { x: (this.previewSize.width - this.imageWidth * this.zoom) / 2, y: (this.previewSize.height - this.imageHeight * this.zoom) / 2, }; } onZoomSliderChange() { if (!this.imageLoaded) { return; } this.zoomSliderPos = Number(this.$zoomSlider.val()); const newZoom = this.zoomer.getZoom(this.zoomSliderPos); if (newZoom === this.zoom) { return; } this.zoom = newZoom; } enableZoomSlider() { this.$zoomSlider.removeAttr('disabled'); this.options.onZoomEnabled(); } disableZoomSlider() { this.$zoomSlider.attr('disabled', true); this.options.onZoomDisabled(); } setupZoomer(zoom) { this.zoomer.setup({ imageSize: this.imageSize, previewSize: this.previewSize, exportZoom: this.options.exportZoom, maxZoom: this.options.maxZoom, minZoom: this.options.minZoom, smallImage: this.options.smallImage, }); this.zoom = exists(zoom) ? zoom : this._zoom; if (this.isZoomable()) { this.enableZoomSlider(); } else { this.disableZoomSlider(); } } set zoom(newZoom) { newZoom = this.fixZoom(newZoom); if (this.imageLoaded) { const oldZoom = this.zoom; const newX = this.previewSize.width / 2 - (this.previewSize.width / 2 - this.offset.x) * newZoom / oldZoom; const newY = this.previewSize.height / 2 - (this.previewSize.height / 2 - this.offset.y) * newZoom / oldZoom; this._zoom = newZoom; this.offset = { x: newX, y: newY }; // Triggers renderImage() } else { this._zoom = newZoom; } this.zoomSliderPos = this.zoomer.getSliderPos(this.zoom); this.$zoomSlider.val(this.zoomSliderPos); this.options.onZoomChange(newZoom); } fixZoom(zoom) { return this.zoomer.fixZoom(zoom); } isZoomable() { return this.zoomer.isZoomable(); } get rotatedOffset() { return { x: this.offset.x + (this.rotation === 90 ? this.image.height * this.zoom : 0) + (this.rotation === 180 ? this.image.width * this.zoom : 0), y: this.offset.y + (this.rotation === 180 ? this.image.height * this.zoom : 0) + (this.rotation === 270 ? this.image.width * this.zoom : 0), }; } renderImage() { const transformation = ` translate(${this.rotatedOffset.x}px, ${this.rotatedOffset.y}px) scale(${this.zoom}) rotate(${this.rotation}deg)`; this.$image.css({ transform: transformation, webkitTransform: transformation, }); if (this.options.imageBackground) { this.$bg.css({ transform: transformation, webkitTransform: transformation, }); } } set rotation(newRotation) { this._rotation = newRotation; if (this.imageLoaded) { // Change in image size may lead to change in zoom range this.setupZoomer(); } } get rotation() { return this._rotation; } rotateCW() { if (this.shouldRejectImage({ imageWidth: this.image.height, imageHeight: this.image.width, previewSize: this.previewSize, maxZoom: this.options.maxZoom, exportZoom: this.options.exportZoom, smallImage: this.options.smallImage, })) { this.rotation = (this.rotation + 180) % 360; } else { this.rotation = (this.rotation + 90) % 360; } } rotateCCW() { if (this.shouldRejectImage({ imageWidth: this.image.height, imageHeight: this.image.width, previewSize: this.previewSize, maxZoom: this.options.maxZoom, exportZoom: this.options.exportZoom, smallImage: this.options.smallImage, })) { this.rotation = (this.rotation + 180) % 360; } else { this.rotation = (this.rotation + 270) % 360; } } shouldRejectImage({ imageWidth, imageHeight, previewSize, maxZoom, exportZoom, smallImage }) { if (smallImage !== 'reject') { return false; } return imageWidth * maxZoom < previewSize.width * exportZoom || imageHeight * maxZoom < previewSize.height * exportZoom; } getCroppedImageData(exportOptions) { if (!this.image.src) { return; } const exportDefaults = { type: 'image/png', quality: 0.75, originalSize: false, fillBg: '#fff', }; exportOptions = $.extend({}, exportDefaults, exportOptions); const exportZoom = exportOptions.originalSize ? 1 / this.zoom : this.options.exportZoom; const zoomedSize = { width: this.zoom * exportZoom * this.image.width, height: this.zoom * exportZoom * this.image.height, }; const canvas = $('<canvas />') .attr({ width: this.previewSize.width * exportZoom, height: this.previewSize.height * exportZoom, }) .get(0); const canvasContext = canvas.getContext('2d'); if (exportOptions.type === 'image/jpeg') { canvasContext.fillStyle = exportOptions.fillBg; canvasContext.fillRect(0, 0, canvas.width, canvas.height); } canvasContext.translate( this.rotatedOffset.x * exportZoom, this.rotatedOffset.y * exportZoom); canvasContext.rotate(this.rotation * Math.PI / 180); canvasContext.drawImage(this.image, 0, 0, zoomedSize.width, zoomedSize.height); return canvas.toDataURL(exportOptions.type, exportOptions.quality); } get imageState() { return { src: this.image.src, offset: this.offset, zoom: this.zoom, }; } get imageSrc() { return this.image.src; } set imageSrc(imageSrc) { this.loadImage(imageSrc); } get offset() { return this._offset; } get zoom() { return this._zoom; } get imageWidth() { return this.rotation % 180 === 0 ? this.image.width : this.image.height; } get imageHeight() { return this.rotation % 180 === 0 ? this.image.height : this.image.width; } get imageSize() { return { width: this.imageWidth, height: this.imageHeight, }; } get initialZoom() { return this.options.initialZoom; } set initialZoom(initialZoomOption) { this.options.initialZoom = initialZoomOption; if (initialZoomOption === 'min') { this._initialZoom = 0; // Will be fixed when image loads } else if (initialZoomOption === 'image') { this._initialZoom = 1; } else { this._initialZoom = 0; } } get exportZoom() { return this.options.exportZoom; } set exportZoom(exportZoom) { this.options.exportZoom = exportZoom; this.setupZoomer(); } get minZoom() { return this.options.minZoom; } set minZoom(minZoom) { this.options.minZoom = minZoom; this.setupZoomer(); } get maxZoom() { return this.options.maxZoom; } set maxZoom(maxZoom) { this.options.maxZoom = maxZoom; this.setupZoomer(); } get previewSize() { return this._previewSize; } set previewSize(size) { if (!size || size.width <= 0 || size.height <= 0) { return; } this._previewSize = { width: size.width, height: size.height, }; this.$preview .innerWidth(this.previewSize.width) .innerHeight(this.previewSize.height); if (this.imageLoaded) { this.setupZoomer(); } } disable() { this.unbindListeners(); this.disableZoomSlider(); this.$el.addClass(CLASS_NAMES.DISABLED); } reenable() { this.bindListeners(); this.enableZoomSlider(); this.$el.removeClass(CLASS_NAMES.DISABLED); } $(selector) { if (!this.$el) { return null; } return this.$el.find(selector); } } export default Cropit;