UNPKG

vue-croppa

Version:

A simple straightforward customizable lightweight mobile-friendly image cropper for Vue 2.0.

1,471 lines (1,363 loc) 61 kB
/* * vue-croppa v1.3.8 * https://github.com/zhanziyang/vue-croppa * * Copyright (c) 2018 zhanziyang * Released under the ISC license */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Croppa = factory()); }(this, (function () { 'use strict'; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var canvasExifOrientation = createCommonjsModule(function (module, exports) { (function (root, factory) { if (typeof undefined === 'function' && undefined.amd) { undefined([], factory); } else { module.exports = factory(); } }(commonjsGlobal, function () { 'use strict'; function drawImage(img, orientation, x, y, width, height) { if (!/^[1-8]$/.test(orientation)) throw new Error('orientation should be [1-8]'); if (x == null) x = 0; if (y == null) y = 0; if (width == null) width = img.width; if (height == null) height = img.height; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = width; canvas.height = height; ctx.save(); switch (+orientation) { // 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. case 1: break; // 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. case 2: ctx.translate(width, 0); ctx.scale(-1, 1); break; // 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. case 3: ctx.translate(width, height); ctx.rotate(180 / 180 * Math.PI); break; // 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. case 4: ctx.translate(0, height); ctx.scale(1, -1); break; // 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. case 5: canvas.width = height; canvas.height = width; ctx.rotate(90 / 180 * Math.PI); ctx.scale(1, -1); break; // 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. case 6: canvas.width = height; canvas.height = width; ctx.rotate(90 / 180 * Math.PI); ctx.translate(0, -height); break; // 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. case 7: canvas.width = height; canvas.height = width; ctx.rotate(270 / 180 * Math.PI); ctx.translate(-width, height); ctx.scale(1, -1); break; // 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. case 8: canvas.width = height; canvas.height = width; ctx.translate(0, width); ctx.rotate(270 / 180 * Math.PI); break; } ctx.drawImage(img, x, y, width, height); ctx.restore(); return canvas; } return { drawImage: drawImage }; })); }); var u = { onePointCoord: function onePointCoord(point, vm) { var canvas = vm.canvas, quality = vm.quality; var rect = canvas.getBoundingClientRect(); var clientX = point.clientX; var clientY = point.clientY; return { x: (clientX - rect.left) * quality, y: (clientY - rect.top) * quality }; }, getPointerCoords: function getPointerCoords(evt, vm) { var pointer = void 0; if (evt.touches && evt.touches[0]) { pointer = evt.touches[0]; } else if (evt.changedTouches && evt.changedTouches[0]) { pointer = evt.changedTouches[0]; } else { pointer = evt; } return this.onePointCoord(pointer, vm); }, getPinchDistance: function getPinchDistance(evt, vm) { var pointer1 = evt.touches[0]; var pointer2 = evt.touches[1]; var coord1 = this.onePointCoord(pointer1, vm); var coord2 = this.onePointCoord(pointer2, vm); return Math.sqrt(Math.pow(coord1.x - coord2.x, 2) + Math.pow(coord1.y - coord2.y, 2)); }, getPinchCenterCoord: function getPinchCenterCoord(evt, vm) { var pointer1 = evt.touches[0]; var pointer2 = evt.touches[1]; var coord1 = this.onePointCoord(pointer1, vm); var coord2 = this.onePointCoord(pointer2, vm); return { x: (coord1.x + coord2.x) / 2, y: (coord1.y + coord2.y) / 2 }; }, imageLoaded: function imageLoaded(img) { return img.complete && img.naturalWidth !== 0; }, rAFPolyfill: function rAFPolyfill() { // rAF polyfill if (typeof document == 'undefined' || typeof window == 'undefined') return; var lastTime = 0; var vendors = ['webkit', 'moz']; for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // Webkit中此取消方法的名字变了 window[vendors[x] + 'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (callback) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)); var id = window.setTimeout(function () { var arg = currTime + timeToCall; callback(arg); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (id) { clearTimeout(id); }; } Array.isArray = function (arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; }, toBlobPolyfill: function toBlobPolyfill() { if (typeof document == 'undefined' || typeof window == 'undefined' || !HTMLCanvasElement) return; var binStr, len, arr; if (!HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { value: function value(callback, type, quality) { binStr = atob(this.toDataURL(type, quality).split(',')[1]); len = binStr.length; arr = new Uint8Array(len); for (var i = 0; i < len; i++) { arr[i] = binStr.charCodeAt(i); } callback(new Blob([arr], { type: type || 'image/png' })); } }); } }, eventHasFile: function eventHasFile(evt) { var dt = evt.dataTransfer || evt.originalEvent.dataTransfer; if (dt.types) { for (var i = 0, len = dt.types.length; i < len; i++) { if (dt.types[i] == 'Files') { return true; } } } return false; }, getFileOrientation: function getFileOrientation(arrayBuffer) { var view = new DataView(arrayBuffer); if (view.getUint16(0, false) != 0xFFD8) return -2; var length = view.byteLength; var offset = 2; while (offset < length) { var marker = view.getUint16(offset, false); offset += 2; if (marker == 0xFFE1) { if (view.getUint32(offset += 2, false) != 0x45786966) return -1; var little = view.getUint16(offset += 6, false) == 0x4949; offset += view.getUint32(offset + 4, little); var tags = view.getUint16(offset, little); offset += 2; for (var i = 0; i < tags; i++) { if (view.getUint16(offset + i * 12, little) == 0x0112) { return view.getUint16(offset + i * 12 + 8, little); } } } else if ((marker & 0xFF00) != 0xFF00) break;else offset += view.getUint16(offset, false); } return -1; }, parseDataUrl: function parseDataUrl(url) { var reg = /^data:([^;]+)?(;base64)?,(.*)/gmi; return reg.exec(url)[3]; }, base64ToArrayBuffer: function base64ToArrayBuffer(base64) { var binaryString = atob(base64); var len = binaryString.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; }, getRotatedImage: function getRotatedImage(img, orientation) { var _canvas = canvasExifOrientation.drawImage(img, orientation); var _img = new Image(); _img.src = _canvas.toDataURL(); return _img; }, flipX: function flipX(ori) { if (ori % 2 == 0) { return ori - 1; } return ori + 1; }, flipY: function flipY(ori) { var map = { 1: 4, 4: 1, 2: 3, 3: 2, 5: 8, 8: 5, 6: 7, 7: 6 }; return map[ori]; }, rotate90: function rotate90(ori) { var map = { 1: 6, 2: 7, 3: 8, 4: 5, 5: 2, 6: 3, 7: 4, 8: 1 }; return map[ori]; }, numberValid: function numberValid(n) { return typeof n === 'number' && !isNaN(n); } }; Number.isInteger = Number.isInteger || function (value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }; var initialImageType = String; if (typeof window !== 'undefined' && window.Image) { initialImageType = [String, Image]; } var props = { value: Object, width: { type: Number, default: 200, validator: function validator(val) { return val > 0; } }, height: { type: Number, default: 200, validator: function validator(val) { return val > 0; } }, placeholder: { type: String, default: 'Choose an image' }, placeholderColor: { default: '#606060' }, placeholderFontSize: { type: Number, default: 0, validator: function validator(val) { return val >= 0; } }, canvasColor: { default: 'transparent' }, quality: { type: Number, default: 2, validator: function validator(val) { return val > 0; } }, zoomSpeed: { default: 3, type: Number, validator: function validator(val) { return val > 0; } }, accept: String, fileSizeLimit: { type: Number, default: 0, validator: function validator(val) { return val >= 0; } }, disabled: Boolean, disableDragAndDrop: Boolean, disableClickToChoose: Boolean, disableDragToMove: Boolean, disableScrollToZoom: Boolean, disablePinchToZoom: Boolean, disableRotation: Boolean, reverseScrollToZoom: Boolean, preventWhiteSpace: Boolean, showRemoveButton: { type: Boolean, default: true }, removeButtonColor: { type: String, default: 'red' }, removeButtonSize: { type: Number }, initialImage: initialImageType, initialSize: { type: String, default: 'cover', validator: function validator(val) { return val === 'cover' || val === 'contain' || val === 'natural'; } }, initialPosition: { type: String, default: 'center', validator: function validator(val) { var valids = ['center', 'top', 'bottom', 'left', 'right']; return val.split(' ').every(function (word) { return valids.indexOf(word) >= 0; }) || /^-?\d+% -?\d+%$/.test(val); } }, inputAttrs: Object, showLoading: Boolean, loadingSize: { type: Number, default: 20 }, loadingColor: { type: String, default: '#606060' }, replaceDrop: Boolean, passive: Boolean, imageBorderRadius: { type: [Number, String], default: 0 }, autoSizing: Boolean, videoEnabled: Boolean }; var events = { INIT_EVENT: 'init', FILE_CHOOSE_EVENT: 'file-choose', FILE_SIZE_EXCEED_EVENT: 'file-size-exceed', FILE_TYPE_MISMATCH_EVENT: 'file-type-mismatch', NEW_IMAGE_EVENT: 'new-image', NEW_IMAGE_DRAWN_EVENT: 'new-image-drawn', IMAGE_REMOVE_EVENT: 'image-remove', MOVE_EVENT: 'move', ZOOM_EVENT: 'zoom', DRAW_EVENT: 'draw', INITIAL_IMAGE_LOADED_EVENT: 'initial-image-loaded', LOADING_START_EVENT: 'loading-start', LOADING_END_EVENT: 'loading-end' }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var PCT_PER_ZOOM = 1 / 100000; // The amount of zooming everytime it happens, in percentage of image width. var MIN_MS_PER_CLICK = 500; // If touch duration is shorter than the value, then it is considered as a click. var CLICK_MOVE_THRESHOLD = 100; // If touch move distance is greater than this value, then it will by no mean be considered as a click. var MIN_WIDTH = 10; // The minimal width the user can zoom to. var DEFAULT_PLACEHOLDER_TAKEUP = 2 / 3; // Placeholder text by default takes up this amount of times of canvas width. var PINCH_ACCELERATION = 1; // The amount of times by which the pinching is more sensitive than the scolling var syncData = ['imgData', 'img', 'imgSet', 'originalImage', 'naturalHeight', 'naturalWidth', 'orientation', 'scaleRatio']; // const DEBUG = false var component = { render: function render() { var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('div', { ref: "wrapper", class: 'croppa-container ' + (_vm.img ? 'croppa--has-target' : '') + ' ' + (_vm.passive ? 'croppa--passive' : '') + ' ' + (_vm.disabled ? 'croppa--disabled' : '') + ' ' + (_vm.disableClickToChoose ? 'croppa--disabled-cc' : '') + ' ' + (_vm.disableDragToMove && _vm.disableScrollToZoom ? 'croppa--disabled-mz' : '') + ' ' + (_vm.fileDraggedOver ? 'croppa--dropzone' : ''), on: { "dragenter": function dragenter($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleDragEnter($event); }, "dragleave": function dragleave($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleDragLeave($event); }, "dragover": function dragover($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleDragOver($event); }, "drop": function drop($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleDrop($event); } } }, [_c('input', _vm._b({ ref: "fileInput", staticStyle: { "height": "1px", "width": "1px", "overflow": "hidden", "margin-left": "-99999px", "position": "absolute" }, attrs: { "type": "file", "accept": _vm.accept, "disabled": _vm.disabled }, on: { "change": _vm._handleInputChange } }, 'input', _vm.inputAttrs, false)), _vm._v(" "), _c('div', { staticClass: "slots", staticStyle: { "width": "0", "height": "0", "visibility": "hidden" } }, [_vm._t("initial"), _vm._v(" "), _vm._t("placeholder")], 2), _vm._v(" "), _c('canvas', { ref: "canvas", on: { "click": function click($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleClick($event); }, "dblclick": function dblclick($event) { $event.stopPropagation();$event.preventDefault();return _vm._handleDblClick($event); }, "touchstart": function touchstart($event) { $event.stopPropagation();return _vm._handlePointerStart($event); }, "mousedown": function mousedown($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerStart($event); }, "pointerstart": function pointerstart($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerStart($event); }, "touchend": function touchend($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerEnd($event); }, "touchcancel": function touchcancel($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerEnd($event); }, "mouseup": function mouseup($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerEnd($event); }, "pointerend": function pointerend($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerEnd($event); }, "pointercancel": function pointercancel($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerEnd($event); }, "touchmove": function touchmove($event) { $event.stopPropagation();return _vm._handlePointerMove($event); }, "mousemove": function mousemove($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerMove($event); }, "pointermove": function pointermove($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerMove($event); }, "pointerleave": function pointerleave($event) { $event.stopPropagation();$event.preventDefault();return _vm._handlePointerLeave($event); }, "DOMMouseScroll": function DOMMouseScroll($event) { $event.stopPropagation();return _vm._handleWheel($event); }, "wheel": function wheel($event) { $event.stopPropagation();return _vm._handleWheel($event); }, "mousewheel": function mousewheel($event) { $event.stopPropagation();return _vm._handleWheel($event); } } }), _vm._v(" "), _vm.showRemoveButton && _vm.img && !_vm.passive ? _c('svg', { staticClass: "icon icon-remove", style: 'top: -' + _vm.height / 40 + 'px; right: -' + _vm.width / 40 + 'px', attrs: { "viewBox": "0 0 1024 1024", "version": "1.1", "xmlns": "http://www.w3.org/2000/svg", "xmlns:xlink": "http://www.w3.org/1999/xlink", "width": _vm.removeButtonSize || _vm.width / 10, "height": _vm.removeButtonSize || _vm.width / 10 }, on: { "click": _vm.remove } }, [_c('path', { attrs: { "d": "M511.921231 0C229.179077 0 0 229.257846 0 512 0 794.702769 229.179077 1024 511.921231 1024 794.781538 1024 1024 794.702769 1024 512 1024 229.257846 794.781538 0 511.921231 0ZM732.041846 650.633846 650.515692 732.081231C650.515692 732.081231 521.491692 593.683692 511.881846 593.683692 502.429538 593.683692 373.366154 732.081231 373.366154 732.081231L291.761231 650.633846C291.761231 650.633846 430.316308 523.500308 430.316308 512.196923 430.316308 500.696615 291.761231 373.523692 291.761231 373.523692L373.366154 291.918769C373.366154 291.918769 503.453538 430.395077 511.881846 430.395077 520.349538 430.395077 650.515692 291.918769 650.515692 291.918769L732.041846 373.523692C732.041846 373.523692 593.447385 502.547692 593.447385 512.196923 593.447385 521.412923 732.041846 650.633846 732.041846 650.633846Z", "fill": _vm.removeButtonColor } })]) : _vm._e(), _vm._v(" "), _vm.showLoading && _vm.loading ? _c('div', { staticClass: "sk-fading-circle", style: _vm.loadingStyle }, _vm._l(12, function (i) { return _c('div', { key: i, class: 'sk-circle' + i + ' sk-circle' }, [_c('div', { staticClass: "sk-circle-indicator", style: { backgroundColor: _vm.loadingColor } })]); })) : _vm._e(), _vm._v(" "), _vm._t("default")], 2); }, staticRenderFns: [], model: { prop: 'value', event: events.INIT_EVENT }, props: props, data: function data() { return { canvas: null, ctx: null, originalImage: null, img: null, video: null, dragging: false, lastMovingCoord: null, imgData: { width: 0, height: 0, startX: 0, startY: 0 }, fileDraggedOver: false, tabStart: 0, scrolling: false, pinching: false, rotating: false, pinchDistance: 0, supportTouch: false, pointerMoved: false, pointerStartCoord: null, naturalWidth: 0, naturalHeight: 0, scaleRatio: null, orientation: 1, userMetadata: null, imageSet: false, currentPointerCoord: null, currentIsInitial: false, loading: false, realWidth: 0, // only for when autoSizing is on realHeight: 0, // only for when autoSizing is on chosenFile: null, useAutoSizing: false }; }, computed: { outputWidth: function outputWidth() { var w = this.useAutoSizing ? this.realWidth : this.width; return w * this.quality; }, outputHeight: function outputHeight() { var h = this.useAutoSizing ? this.realHeight : this.height; return h * this.quality; }, computedPlaceholderFontSize: function computedPlaceholderFontSize() { return this.placeholderFontSize * this.quality; }, aspectRatio: function aspectRatio() { return this.naturalWidth / this.naturalHeight; }, loadingStyle: function loadingStyle() { return { width: this.loadingSize + 'px', height: this.loadingSize + 'px', right: '15px', bottom: '10px' }; } }, mounted: function mounted() { var _this = this; this._initialize(); u.rAFPolyfill(); u.toBlobPolyfill(); var supports = this.supportDetection(); if (!supports.basic) { console.warn('Your browser does not support vue-croppa functionality.'); } if (this.passive) { this.$watch('value._data', function (data) { var set$$1 = false; if (!data) return; for (var key in data) { if (syncData.indexOf(key) >= 0) { var val = data[key]; if (val !== _this[key]) { _this.$set(_this, key, val); set$$1 = true; } } } if (set$$1) { if (!_this.img) { _this.remove(); } else { _this.$nextTick(function () { _this._draw(); }); } } }, { deep: true }); } this.useAutoSizing = !!(this.autoSizing && this.$refs.wrapper && getComputedStyle); if (this.useAutoSizing) { this._autoSizingInit(); } }, beforeDestroy: function beforeDestroy() { if (this.useAutoSizing) { this._autoSizingRemove(); } }, watch: { outputWidth: function outputWidth() { this.onDimensionChange(); }, outputHeight: function outputHeight() { this.onDimensionChange(); }, canvasColor: function canvasColor() { if (!this.img) { this._setPlaceholders(); } else { this._draw(); } }, imageBorderRadius: function imageBorderRadius() { if (this.img) { this._draw(); } }, placeholder: function placeholder() { if (!this.img) { this._setPlaceholders(); } }, placeholderColor: function placeholderColor() { if (!this.img) { this._setPlaceholders(); } }, computedPlaceholderFontSize: function computedPlaceholderFontSize() { if (!this.img) { this._setPlaceholders(); } }, preventWhiteSpace: function preventWhiteSpace(val) { if (val) { this.imageSet = false; } this._placeImage(); }, scaleRatio: function scaleRatio(val, oldVal) { if (this.passive) return; if (!this.img) return; if (!u.numberValid(val)) return; var x = 1; if (u.numberValid(oldVal) && oldVal !== 0) { x = val / oldVal; } var pos = this.currentPointerCoord || { x: this.imgData.startX + this.imgData.width / 2, y: this.imgData.startY + this.imgData.height / 2 }; this.imgData.width = this.naturalWidth * val; this.imgData.height = this.naturalHeight * val; if (!this.userMetadata && this.imageSet && !this.rotating) { var offsetX = (x - 1) * (pos.x - this.imgData.startX); var offsetY = (x - 1) * (pos.y - this.imgData.startY); this.imgData.startX = this.imgData.startX - offsetX; this.imgData.startY = this.imgData.startY - offsetY; } if (this.preventWhiteSpace) { this._preventZoomingToWhiteSpace(); this._preventMovingToWhiteSpace(); } }, 'imgData.width': function imgDataWidth(val, oldVal) { // if (this.passive) return if (!u.numberValid(val)) return; this.scaleRatio = val / this.naturalWidth; if (this.hasImage()) { if (Math.abs(val - oldVal) > val * (1 / 100000)) { this.emitEvent(events.ZOOM_EVENT); this._draw(); } } }, 'imgData.height': function imgDataHeight(val) { // if (this.passive) return if (!u.numberValid(val)) return; this.scaleRatio = val / this.naturalHeight; }, 'imgData.startX': function imgDataStartX(val) { // if (this.passive) return if (this.hasImage()) { this.$nextTick(this._draw); } }, 'imgData.startY': function imgDataStartY(val) { // if (this.passive) return if (this.hasImage()) { this.$nextTick(this._draw); } }, loading: function loading(val) { if (this.passive) return; if (val) { this.emitEvent(events.LOADING_START_EVENT); } else { this.emitEvent(events.LOADING_END_EVENT); } }, autoSizing: function autoSizing(val) { this.useAutoSizing = !!(this.autoSizing && this.$refs.wrapper && getComputedStyle); if (val) { this._autoSizingInit(); } else { this._autoSizingRemove(); } } }, methods: { emitEvent: function emitEvent() { // console.log(args[0]) this.$emit.apply(this, arguments); }, getCanvas: function getCanvas() { return this.canvas; }, getContext: function getContext() { return this.ctx; }, getChosenFile: function getChosenFile() { return this.chosenFile || this.$refs.fileInput.files[0]; }, move: function move(offset) { if (!offset || this.passive) return; var oldX = this.imgData.startX; var oldY = this.imgData.startY; this.imgData.startX += offset.x; this.imgData.startY += offset.y; if (this.preventWhiteSpace) { this._preventMovingToWhiteSpace(); } if (this.imgData.startX !== oldX || this.imgData.startY !== oldY) { this.emitEvent(events.MOVE_EVENT); this._draw(); } }, moveUpwards: function moveUpwards() { var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; this.move({ x: 0, y: -amount }); }, moveDownwards: function moveDownwards() { var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; this.move({ x: 0, y: amount }); }, moveLeftwards: function moveLeftwards() { var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; this.move({ x: -amount, y: 0 }); }, moveRightwards: function moveRightwards() { var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; this.move({ x: amount, y: 0 }); }, zoom: function zoom() { var zoomIn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var acceleration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; if (this.passive) return; var realSpeed = this.zoomSpeed * acceleration; var speed = this.outputWidth * PCT_PER_ZOOM * realSpeed; var x = 1; if (zoomIn) { x = 1 + speed; } else if (this.imgData.width > MIN_WIDTH) { x = 1 - speed; } this.scaleRatio *= x; }, zoomIn: function zoomIn() { this.zoom(true); }, zoomOut: function zoomOut() { this.zoom(false); }, rotate: function rotate() { var step = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; if (this.disableRotation || this.disabled || this.passive) return; step = parseInt(step); if (isNaN(step) || step > 3 || step < -3) { console.warn('Invalid argument for rotate() method. It should one of the integers from -3 to 3.'); step = 1; } this._rotateByStep(step); }, flipX: function flipX() { if (this.disableRotation || this.disabled || this.passive) return; this._setOrientation(2); }, flipY: function flipY() { if (this.disableRotation || this.disabled || this.passive) return; this._setOrientation(4); }, refresh: function refresh() { this.$nextTick(this._initialize); }, hasImage: function hasImage() { return !!this.imageSet; }, applyMetadata: function applyMetadata(metadata) { if (!metadata || this.passive) return; this.userMetadata = metadata; var ori = metadata.orientation || this.orientation || 1; this._setOrientation(ori, true); }, generateDataUrl: function generateDataUrl(type, compressionRate) { if (!this.hasImage()) return ''; return this.canvas.toDataURL(type, compressionRate); }, generateBlob: function generateBlob(callback, mimeType, qualityArgument) { if (!this.hasImage()) { callback(null); return; } this.canvas.toBlob(callback, mimeType, qualityArgument); }, promisedBlob: function promisedBlob() { var _this2 = this; for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (typeof Promise == 'undefined') { console.warn('No Promise support. Please add Promise polyfill if you want to use this method.'); return; } return new Promise(function (resolve, reject) { try { _this2.generateBlob.apply(_this2, [function (blob) { resolve(blob); }].concat(args)); } catch (err) { reject(err); } }); }, getMetadata: function getMetadata() { if (!this.hasImage()) return {}; var _imgData = this.imgData, startX = _imgData.startX, startY = _imgData.startY; return { startX: startX, startY: startY, scale: this.scaleRatio, orientation: this.orientation }; }, supportDetection: function supportDetection() { if (typeof window === 'undefined') return; var div = document.createElement('div'); return { 'basic': window.requestAnimationFrame && window.File && window.FileReader && window.FileList && window.Blob, 'dnd': 'ondragstart' in div && 'ondrop' in div }; }, chooseFile: function chooseFile() { if (this.passive) return; this.$refs.fileInput.click(); }, remove: function remove() { if (!this.imageSet) return; this._setPlaceholders(); var hadImage = this.img != null; this.originalImage = null; this.img = null; this.$refs.fileInput.value = ''; this.imgData = { width: 0, height: 0, startX: 0, startY: 0 }; this.orientation = 1; this.scaleRatio = null; this.userMetadata = null; this.imageSet = false; this.chosenFile = null; if (this.video) { this.video.pause(); this.video = null; } if (hadImage) { this.emitEvent(events.IMAGE_REMOVE_EVENT); } }, addClipPlugin: function addClipPlugin(plugin) { if (!this.clipPlugins) { this.clipPlugins = []; } if (typeof plugin === 'function' && this.clipPlugins.indexOf(plugin) < 0) { this.clipPlugins.push(plugin); } else { throw Error('Clip plugins should be functions'); } }, emitNativeEvent: function emitNativeEvent(evt) { this.emitEvent(evt.type, evt); }, _setContainerSize: function _setContainerSize() { if (this.useAutoSizing) { this.realWidth = +getComputedStyle(this.$refs.wrapper).width.slice(0, -2); this.realHeight = +getComputedStyle(this.$refs.wrapper).height.slice(0, -2); } }, _autoSizingInit: function _autoSizingInit() { this._setContainerSize(); window.addEventListener('resize', this._setContainerSize); }, _autoSizingRemove: function _autoSizingRemove() { this._setContainerSize(); window.removeEventListener('resize', this._setContainerSize); }, _initialize: function _initialize() { this.canvas = this.$refs.canvas; this._setSize(); this.canvas.style.backgroundColor = !this.canvasColor || this.canvasColor == 'default' ? 'transparent' : typeof this.canvasColor === 'string' ? this.canvasColor : ''; this.ctx = this.canvas.getContext('2d'); this.ctx.imageSmoothingEnabled = true; this.ctx.imageSmoothingQuality = "high"; this.ctx.webkitImageSmoothingEnabled = true; this.ctx.msImageSmoothingEnabled = true; this.ctx.imageSmoothingEnabled = true; this.originalImage = null; this.img = null; this.$refs.fileInput.value = ''; this.imageSet = false; this.chosenFile = null; this._setInitial(); if (!this.passive) { this.emitEvent(events.INIT_EVENT, this); } }, _setSize: function _setSize() { this.canvas.width = this.outputWidth; this.canvas.height = this.outputHeight; this.canvas.style.width = (this.useAutoSizing ? this.realWidth : this.width) + 'px'; this.canvas.style.height = (this.useAutoSizing ? this.realHeight : this.height) + 'px'; }, _rotateByStep: function _rotateByStep(step) { var orientation = 1; switch (step) { case 1: orientation = 6; break; case 2: orientation = 3; break; case 3: orientation = 8; break; case -1: orientation = 8; break; case -2: orientation = 3; break; case -3: orientation = 6; break; } this._setOrientation(orientation); }, _setImagePlaceholder: function _setImagePlaceholder() { var _this3 = this; var img = void 0; if (this.$slots.placeholder && this.$slots.placeholder[0]) { var vNode = this.$slots.placeholder[0]; var tag = vNode.tag, elm = vNode.elm; if (tag == 'img' && elm) { img = elm; } } if (!img) return; var onLoad = function onLoad() { _this3.ctx.drawImage(img, 0, 0, _this3.outputWidth, _this3.outputHeight); }; if (u.imageLoaded(img)) { onLoad(); } else { img.onload = onLoad; } }, _setTextPlaceholder: function _setTextPlaceholder() { var ctx = this.ctx; ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; var defaultFontSize = this.outputWidth * DEFAULT_PLACEHOLDER_TAKEUP / this.placeholder.length; var fontSize = !this.computedPlaceholderFontSize || this.computedPlaceholderFontSize == 0 ? defaultFontSize : this.computedPlaceholderFontSize; ctx.font = fontSize + 'px sans-serif'; ctx.fillStyle = !this.placeholderColor || this.placeholderColor == 'default' ? '#606060' : this.placeholderColor; ctx.fillText(this.placeholder, this.outputWidth / 2, this.outputHeight / 2); }, _setPlaceholders: function _setPlaceholders() { this._paintBackground(); this._setImagePlaceholder(); this._setTextPlaceholder(); }, _setInitial: function _setInitial() { var _this4 = this; var src = void 0, img = void 0; if (this.$slots.initial && this.$slots.initial[0]) { var vNode = this.$slots.initial[0]; var tag = vNode.tag, elm = vNode.elm; if (tag == 'img' && elm) { img = elm; } } if (this.initialImage && typeof this.initialImage === 'string') { src = this.initialImage; img = new Image(); if (!/^data:/.test(src) && !/^blob:/.test(src)) { img.setAttribute('crossOrigin', 'anonymous'); } img.src = src; } else if (_typeof(this.initialImage) === 'object' && this.initialImage instanceof Image) { img = this.initialImage; } if (!src && !img) { this._setPlaceholders(); return; } this.currentIsInitial = true; if (u.imageLoaded(img)) { // this.emitEvent(events.INITIAL_IMAGE_LOADED_EVENT) this._onload(img, +img.dataset['exifOrientation'], true); } else { this.loading = true; img.onload = function () { // this.emitEvent(events.INITIAL_IMAGE_LOADED_EVENT) _this4._onload(img, +img.dataset['exifOrientation'], true); }; img.onerror = function () { _this4._setPlaceholders(); }; } }, _onload: function _onload(img) { var orientation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var initial = arguments[2]; if (this.imageSet) { this.remove(); } this.originalImage = img; this.img = img; if (isNaN(orientation)) { orientation = 1; } this._setOrientation(orientation); if (initial) { this.emitEvent(events.INITIAL_IMAGE_LOADED_EVENT); } }, _onVideoLoad: function _onVideoLoad(video, initial) { var _this5 = this; this.video = video; var canvas = document.createElement('canvas'); var videoWidth = video.videoWidth, videoHeight = video.videoHeight; canvas.width = videoWidth; canvas.height = videoHeight; var ctx = canvas.getContext('2d'); this.loading = false; var drawFrame = function drawFrame(initial) { if (!_this5.video) return; ctx.drawImage(_this5.video, 0, 0, videoWidth, videoHeight); var frame = new Image(); frame.src = canvas.toDataURL(); frame.onload = function () { _this5.img = frame; // this._placeImage() if (initial) { _this5._placeImage(); } else { _this5._draw(); } }; }; drawFrame(true); var keepDrawing = function keepDrawing() { _this5.$nextTick(function () { drawFrame(); if (!_this5.video || _this5.video.ended || _this5.video.paused) return; requestAnimationFrame(keepDrawing); }); }; this.video.addEventListener('play', function () { requestAnimationFrame(keepDrawing); }); }, _handleClick: function _handleClick(evt) { this.emitNativeEvent(evt); if (!this.hasImage() && !this.disableClickToChoose && !this.disabled && !this.supportTouch && !this.passive) { this.chooseFile(); } }, _handleDblClick: function _handleDblClick(evt) { this.emitNativeEvent(evt); if (this.videoEnabled && this.video) { if (this.video.paused || this.video.ended) { this.video.play(); } else { this.video.pause(); } return; } }, _handleInputChange: function _handleInputChange() { var input = this.$refs.fileInput; if (!input.files.length || this.passive) return; var file = input.files[0]; this._onNewFileIn(file); }, _onNewFileIn: function _onNewFileIn(file) { var _this6 = this; this.currentIsInitial = false; this.loading = true; this.emitEvent(events.FILE_CHOOSE_EVENT, file); this.chosenFile = file; if (!this._fileSizeIsValid(file)) { this.loading = false; this.emitEvent(events.FILE_SIZE_EXCEED_EVENT, file); return false; } if (!this._fileTypeIsValid(file)) { this.loading = false; this.emitEvent(events.FILE_TYPE_MISMATCH_EVENT, file); var type = file.type || file.name.toLowerCase().split('.').pop(); return false; } if (typeof window !== 'undefined' && typeof window.FileReader !== 'undefined') { var fr = new FileReader(); fr.onload = function (e) { var fileData = e.target.result; var base64 = u.parseDataUrl(fileData); var isVideo = /^video/.test(file.type); if (isVideo) { var video = document.createElement('video'); video.src = fileData; fileData = null; if (video.readyState >= video.HAVE_FUTURE_DATA) { _this6._onVideoLoad(video); } else { video.addEventListener('canplay', function () { console.log('can play event'); _this6._onVideoLoad(video); }, false); } } else { var orientation = 1; try { orientation = u.getFileOrientation(u.base64ToArrayBuffer(base64)); } catch (err) {} if (orientation < 1) orientation = 1; var img = new Image(); img.src = fileData; fileData = null; img.onload = function () { _this6._onload(img, orientation); _this6.emitEvent(events.NEW_IMAGE_EVENT); }; } }; fr.readAsDataURL(file); } }, _fileSizeIsValid: function _fileSizeIsValid(file) { if (!file) return false; if (!this.fileSizeLimit || this.fileSizeLimit == 0) return true; return file.size < this.fileSizeLimit; }, _fileTypeIsValid: function _fileTypeIsValid(file) { var acceptableMimeType = this.videoEnabled && /^video/.test(file.type) && document.createElement('video').canPlayType(file.type) || /^image/.test(file.type); if (!acceptableMimeType) return false; if (!this.accept) return true; var accept = this.accept; var baseMimetype = accept.replace(/\/.*$/, ''); var types = accept.split(','); for (var i = 0, len = types.length; i < len; i++) { var type = types[i]; var t = type.trim(); if (t.charAt(0) == '.') { if (file.name.toLowerCase().split('.').pop() === t.toLowerCase().slice(1)) return true; } else if (/\/\*$/.test(t)) { var fileBaseType = file.type.replace(/\/.*$/, ''); if (fileBaseType === baseMimetype) { return true; } } else if (file.type === type) { return true; } } return false; }, _placeImage: function _placeImage(applyMetadata) { if (!this.img) return; var imgData = this.imgData; this.naturalWidth = this.img.naturalWidth; this.naturalHeight = this.img.naturalHeight; imgData.startX = u.numberValid(imgData.startX) ? imgData.startX : 0; imgData.startY = u.numberValid(imgData.startY) ? imgData.startY : 0; if (this.preventWhiteSpace) { this._aspectFill(); } else if (!this.imageSet) { if (this.initialSize == 'contain') { this._aspectFit(); } else if (this.initialSize == 'natural') { this._naturalSize(); } else { this._aspectFill(); } } else { this.imgData.width = this.naturalWidth * this.scaleRatio; this.imgData.height = this.naturalHeight * this.scaleRatio; } if (!this.imageSet) { if (/top/.test(this.initialPosition)) { imgData.startY = 0; } else if (/bottom/.test(this.initialPosition)) { imgData.startY = this.outputHeight - imgData.height; } if (/left/.test(this.initialPosition)) { imgData.startX = 0; } else if (/right/.test(this.initialPosition)) { imgData.startX = this.outputWidth - imgData.width; } if (/^-?\d+% -?\d+%$/.test(this.initialPosition)) { var result = /^(-?\d+)% (-?\d+)%$/.exec(this.initialPosition); var x = +result[1] / 100; var y = +result[2] / 100; imgData.startX = x * (this.outputWidth - imgData.width); imgData.startY = y * (this.outputHeight - imgData.height); } } applyMetadata && this._applyMetadata(); if (applyMetadata && this.preventWhiteSpace) { this.zoom(false, 0); } else { this.move({ x: 0, y: 0 }); this._draw(); } }, _aspectFill: function _aspectFill() { var imgWidth = this.naturalWidth; var imgHeight = this.naturalHeight; var canvasRatio = this.outputWidth / this.outputHeight; var scaleRatio = void 0; if (this.aspectRatio > canvasRatio) { scaleRatio = imgHeight / this.outputHeight; this.imgData.width = imgWidth / scaleRatio; this.imgData.height = this.outputHeight; this.imgData.startX = -(this.imgData.width - this.outputWidth) / 2; this.imgData.startY = 0; } else { scaleRatio = imgWidth / this.outputWidth; this.imgData.height = imgHeight / scaleRatio; this.imgData.width = this.outputWidth; this.imgData.startY = -(this.imgData.height - this.outputHeight) / 2; this.imgData.startX = 0; } }, _aspectFit: function _aspectFit() { var imgWidth = this.naturalWidth; var imgHeight = this.naturalHeight; var canvasRatio = this.outputWidth / this.outputHeight; var scaleRatio = void 0; if (this.aspectRatio > canvasRatio) { scaleRatio = imgWidth / this.outputWidth; this.imgData.height = imgHeight / scaleRatio; this.imgData.width = this.outputWidth; this.imgData.startY = -(this.imgData.height - this.outputHeight) / 2; this.imgData.startX = 0; } else { scaleRatio = imgHeight / this.outputHeight; this.imgData.width = imgWidth / scaleRatio; this.imgData.height = this.outputHeight; this.imgData.startX = -(this.imgData.width - this.outputWidth) / 2; this.imgData.startY = 0; } }, _naturalSize: function _naturalSize() { var imgWidth = this.naturalWidth; var imgHeight = this.naturalHeight; this.imgData.width = imgWidth; this.imgData.height = imgHeight; this.imgData.startX = -(this.imgData.width - this.outputWidth) / 2; this.imgData.startY = -(this.imgData.height - this.outputHeight) / 2; }, _handlePointerStart: function _handlePointerStart(evt) { this.emitNativeEvent(evt); if (this.passive) return; this.supportTouch = true; this.pointerMoved = false; var pointerCoord = u.getPointerCoords(evt, this); this.pointerStartCoord = pointerCoord; if (this.disabled) return; // simulate click with touch on mobile devices if (!this.hasImage() && !this.disableClickToChoose) { this.tabStart = new Date().valueOf(); return; } // ignore mouse right click and middle click if (evt.which && evt.which > 1) return; if (!evt.touches || evt.touches.length === 1) { this.dragging = true; this.pinching = false; var coord = u.getPointerCoords(evt, this); this.lastMovingCoord = coord; } if (evt.touches && evt.touches.length === 2 && !this.disablePinchToZoom) { this.dragging = false; this.pinching = true; this.pinchDistance = u.getPinchDistance(evt, this); } var cancelEvents = ['mouseup', 'touchend', 'touchcancel', 'pointerend', 'pointercancel']; for (var i = 0, len = cancelEvents.length; i < len; i++) { var e = cancelEvents[i]; document.addEventListener(e, this._handlePointerEnd); } }, _handlePointerEnd: function _handlePointerEnd(evt) { this.emitNativeEvent(evt); if (this.passive) return; var pointerMoveDistance = 0; if (this.pointerStartCoord) { var pointerCoord = u.getPointerCoords(evt, this); pointerMoveDistance = Math.sqrt(Math.pow(pointerCoord.x - this.pointerStartCoord.x, 2) + Math.pow(pointerCoord.y - this.pointerStartCoord.y, 2)) || 0; } if (this.disabled) return; if (!this.hasImage() && !this.disableClickToChoose) { var tabEnd = new Date().valueOf(); if (pointerMoveDistance < CLICK_MOVE_THRESHOLD && tabEnd - this.tabStart < MIN_MS_PER_CLICK && this.supportTouch) { this.chooseFile(); } this.tabStart = 0; return; } this.dragging = false; this.pinching = false; this.pinchDistance = 0; this.lastMovingCoord = null; this.pointerMoved = false; this.pointerStartCoord = null; }, _handlePointerMove: function _handlePointerMove(evt) { this.emitNativeEvent(evt); if (this.passive) return; this.pointerMoved = true; if (!this.hasImage()) return; var coord = u.getPointerCoords(evt, this); this.currentPointerCoord = coord; if (this.disabled || this.disableDragToMove) return; evt.preventDefault(); if (!evt.touches || evt.touches.length === 1) { if (!this.dragging) return; if (this.lastMovingCoord) { this.move({ x: coord.x - this.lastMovingCoord.x, y: coord.y - this.lastMovingCoord.y }); } this.lastMovingCoord = coord; } if (evt.touches && evt.touches.length === 2 && !this.disablePinchToZoom) { if (!this.pinching) return; var distance = u.getPinchDistance(evt, this); var delta = distance - this.pinchDistance; this.zoom(delta > 0, PINCH_ACCELERATION); this.pinchDistance = distance; } }, _handlePointerLeave: function _handlePointerLeave(evt) { this.emitNativeEvent(evt); if (this.passive) return; this.currentPointerCoord = null; }, _handleWheel: function _handleWheel(evt) { var _this7 = this; this.emitNativeEvent(evt); if (this.passive) return; if (this.disabled || this.disableScr