vue-poster-editor
Version:
A poster editor based on Vue.js
499 lines (420 loc) • 17.5 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _clone2 = require('lodash/clone');
var _clone3 = _interopRequireDefault(_clone2);
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _jquery = require('jquery');
var _jquery2 = _interopRequireDefault(_jquery);
var _utils = require('../utils/utils');
var _utils2 = _interopRequireDefault(_utils);
var _editorSelector = require('./editor-selector.html');
var _editorSelector2 = _interopRequireDefault(_editorSelector);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = {
template: _editorSelector2.default,
props: ['layout', 'currentElement'],
data: function data() {
return {
selector: null,
clickLocked: false,
maskActived: false,
mask: {
height: 0,
width: 0,
left: 0,
top: 0
},
keepElementCache: {},
bboxCaches: {},
rectCaches: {}
};
},
computed: {
editor: function editor() {
return this.$parent;
},
currentLayout: function currentLayout() {
return this.editor.currentLayout;
},
elements: function elements() {
var layout = this.currentLayout;
return layout ? layout.elements : [];
},
selectedElements: function selectedElements() {
return this.editor.selectedElements;
}
},
methods: {
add: function add(element) {
if (element && !element.$selected) {
element.$selected = true;
}
},
remove: function remove(element) {
if (element && element.$selected) {
element.$selected = false;
}
},
clearSelectedElements: function clearSelectedElements() {
this.editor.clearSelectedElements();
},
showSelector: function showSelector() {
var editor = this.editor;
var elements = this.selectedElements;
if (!elements.length) {
return;
}
this.preventEditorClick();
if (elements.length === 1) {
editor.focusElement(elements[0]);
return;
}
var bbox = _utils2.default.getBBoxByElements(elements, 1);
var selector = editor.createElement({
type: '$selector',
rotatable: true,
resize: 1,
height: bbox.height,
width: bbox.width,
left: bbox.left,
top: bbox.top,
elements: elements,
$guider: { show: false, snapTo: false }
});
editor.focusElement(selector);
this.selector = selector;
},
hideSelector: function hideSelector() {
this.clearSelectedElements();
this.selector = null;
},
preventEditorClick: function preventEditorClick() {
var _this = this;
this.clickLocked = true;
setTimeout(function () {
_this.clickLocked = false;
}, 160);
},
checkClickPrevent: function checkClickPrevent(e) {
if (this.clickLocked) {
e.preventDefault();
}
this.clickLocked = false;
},
activeMask: function activeMask(e) {
var self = this;
var doc = (0, _jquery2.default)(document);
var editor = this.editor;
var containerRect = editor.containerRect;
var drag = this.drag = {
pageX: e.pageX,
pageY: e.pageY,
startX: e.pageX - containerRect.left + containerRect.scrollLeft,
startY: e.pageY - containerRect.top + containerRect.scrollTop,
bboxList: null,
draging: false,
append: false,
cancel: function cancel(e) {
doc.off('mousemove.editor-selector', drag.move);
if (drag.draging) {
drag.draging = false;
self.drag = null;
self.$emit('mask.inactive', e, drag);
}
},
move: function move(e) {
e.preventDefault();
drag.dx = e.pageX - drag.pageX;
drag.dy = e.pageY - drag.pageY;
var dOffsetMin = 3;
if (!drag.draging && (Math.abs(drag.dx) >= dOffsetMin || Math.abs(drag.dy) >= dOffsetMin)) {
drag.draging = true;
self.$emit('mask.active', e, drag);
}
if (drag.draging) {
self.$emit('mask.moving', e, drag);
}
}
};
doc.on('mousemove.editor-selector', drag.move);
doc.one('mouseup.editor-selector', drag.cancel);
},
checkElements: function checkElements() {
var self = this;
var mask = this.mask;
var editor = this.editor;
var containerRect = editor.containerRect;
var selectedElements = this.selectedElements;
var shellRect = editor.shellRect;
var zoom = editor.zoom;
var maskRect = {
left: (mask.left - containerRect.scrollLeft - shellRect.left) / zoom,
top: (mask.top - containerRect.scrollTop - shellRect.top) / zoom - self.currentLayout.top,
height: mask.height / zoom,
width: mask.width / zoom,
rotate: 0
};
var keepElementsCache = this.keepElementsCache;
var elements = this.elements;
elements.forEach(function (element) {
if (keepElementsCache[element.$id]) {
return;
}
if (element.lock || element.frozen) {
return;
}
var intersection = _utils2.default.getRectIntersection(maskRect, element);
if (intersection) {
self.add(element);
} else {
self.remove(element);
}
});
selectedElements.forEach(function (selectedElement) {
if (selectedElement.lock) editor.unselectElement(selectedElement);
});
},
getElementBBox: function getElementBBox(element) {
var bboxCaches = this.bboxCaches;
if (bboxCaches[element.$id]) {
return bboxCaches[element.$id];
}
bboxCaches[element.$id] = _utils2.default.getBBoxByElement(element);
return bboxCaches[element.$id];
},
setCaches: function setCaches() {
var selector = this.selector;
var elements = this.selectedElements;
var rectCaches = this.rectCaches = {};
elements.forEach(function (element) {
var cache = {
top: element.top,
left: element.left,
width: element.width,
height: element.height,
fontSize: element.fontSize,
imageWidth: element.imageWidth,
imageHeight: element.imageHeight,
rotate: element.rotate,
contents: element.contents
};
cache.padding = (0, _clone3.default)(element.padding);
cache.clip = (0, _clone3.default)(element.clip);
if (element.type === 'mask') {
cache.imagePosition = (0, _clone3.default)(element.imageTransform.position);
}
rectCaches[element.$id] = cache;
});
rectCaches['selector'] = {
top: selector.top,
left: selector.left,
width: selector.width,
height: selector.height,
rotate: selector.rotate
};
},
clearCaches: function clearCaches() {
delete this.rectCaches;
}
},
events: {
'editor.mousedown': function editorMousedown(e) {
var ignoreElements = ['.editor-element', '.editor-transform-wrap', '.editor-toolbar-wrap'].join(',');
var editor = this.editor;
if (!editor.options.selector || e.ctrlKey || e.button !== 0 || e.isDefaultPrevented() || !editor.currentLayout || editor.currentCropElement || editor.currentEditMask || (0, _jquery2.default)(e.target).closest(ignoreElements).length && !e.altKey) {
return;
}
this.activeMask(e);
},
'editor.click': function editorClick(e) {
this.checkClickPrevent(e);
},
'editor.drag.active': function editorDragActive(element) {
var selector = this.selector;
if (!selector || element !== selector) {
return;
}
this.setCaches();
},
'editor.drag.moving': function editorDragMoving(drag, element) {
var editor = this.editor;
var selector = this.selector;
if (!selector || element.$id !== selector.$id) {
return;
}
var rectCaches = this.rectCaches;
var elements = this.selectedElements;
elements.forEach(function (element) {
var cache = rectCaches[element.$id];
editor.changeElement({
left: cache.left + drag.dx,
top: cache.top + drag.dy
}, element);
});
},
'editor.transform.active': function editorTransformActive(element) {
var selector = this.selector;
if (!selector || element !== selector) {
return;
}
this.setCaches();
},
'editor.transform.resizing': function editorTransformResizing(drag, element) {
var editor = this.editor;
var selector = this.selector;
if (!selector || element.$id !== selector.$id) {
return;
}
var rectCaches = this.rectCaches;
var elements = this.selectedElements;
var widthRatio = selector.width / rectCaches.selector.width;
var heightRatio = selector.height / rectCaches.selector.height;
elements.forEach(function (element) {
var cache = rectCaches[element.$id];
editor.changeElement({
width: cache.width * widthRatio,
height: cache.height * heightRatio,
left: (cache.left - rectCaches.selector.left) * widthRatio + selector.left,
top: (cache.top - rectCaches.selector.top) * heightRatio + selector.top
}, element);
var prePadding = cache.padding;
var newPadding = element.padding;
newPadding[0] = prePadding[0] * heightRatio;
newPadding[2] = prePadding[2] * heightRatio;
newPadding[1] = prePadding[1] * widthRatio;
newPadding[3] = prePadding[3] * widthRatio;
if (element.type === 'text') {
var fitFontSize = function fitFontSize(fontSize, ratio) {
fontSize = fontSize * ratio;
if (fontSize % 1 !== 0) {
fontSize = Math.floor(fontSize * 10) / 10;
}
return fontSize;
};
element.fontSize = fitFontSize(cache.fontSize, widthRatio);
element.contents = element.contents.map(function (item, i) {
return _extends({}, item, {
fontSize: fitFontSize(cache.contents[i].fontSize, widthRatio)
});
});
}
if (element.type === 'image' && cache.clip) {
var preClip = cache.clip;
var newClip = element.clip;
newClip.left = preClip.left * widthRatio;
newClip.right = preClip.right * widthRatio;
newClip.top = preClip.top * heightRatio;
newClip.bottom = preClip.bottom * heightRatio;
}
if (element.type === 'mask') {
var prePosition = cache.imagePosition;
var newPosition = element.imageTransform.position;
newPosition.x = prePosition.x * widthRatio;
newPosition.y = prePosition.y * heightRatio;
element.imageWidth = cache.imageWidth * widthRatio;
element.imageHeight = cache.imageHeight * heightRatio;
}
});
},
'editor.transform.rotating': function editorTransformRotating(drag, element) {
var selector = this.selector;
if (!selector || element.$id !== selector.$id) {
return;
}
var rectCaches = this.rectCaches;
var elements = this.selectedElements;
var pivot = {
x: selector.left + selector.width / 2,
y: selector.top + selector.height / 2
};
elements.forEach(function (element) {
var cache = rectCaches[element.$id];
var rotateChange = selector.rotate - rectCaches.selector.rotate;
element.rotate = cache.rotate + rotateChange;
var prePoint = {
x: cache.left + cache.width / 2,
y: cache.top + cache.height / 2
};
var newPoint = _utils2.default.getPointPosition(prePoint, pivot, rotateChange);
element.left = cache.left + (newPoint.x - prePoint.x);
element.top = cache.top + (newPoint.y - prePoint.y);
});
},
'editor.drag.inactive': function editorDragInactive() {
this.clearCaches();
this.selector && this.editor.makeSnapshot('change_element');
},
'editor.transform.inactive': function editorTransformInactive() {
this.clearCaches();
this.selector && this.editor.makeSnapshot('change_element');
},
'editor.paste': function editorPaste(elements) {
if (elements.length <= 1) {
return;
}
elements.forEach(function (element) {
element.$selected = true;
});
this.showSelector();
}
},
watch: {
currentElement: function currentElement(element) {
if (!this.maskActived && element !== this.selector) {
this.hideSelector();
}
}
},
mounted: function mounted() {
var _this2 = this;
this.$on('mask.active', function (e) {
if (!e.shiftKey && !e.metaKey) {
_this2.clearSelectedElements();
}
if (_this2.editor.mode === 'flow') {
var point = _this2.editor.pointFromEvent(e);
var layout = _this2.editor.getLayoutByPoint(point);
if (layout && layout !== _this2.currentLayout) {
_this2.editor.toggleLayout(layout);
}
}
_this2.bboxCaches = {};
var currentElement = _this2.currentElement;
if (currentElement) {
if (e.shiftKey || e.metaKey) {
_this2.add(currentElement);
}
_this2.editor.focusElement(null);
}
var keepElementsCache = _this2.keepElementsCache = {};
var selectedElements = _this2.editor.getSelectedElements();
if (selectedElements.length > 0) {
selectedElements.forEach(function (element) {
keepElementsCache[element.$id] = true;
});
}
_this2.maskActived = true;
});
this.$on('mask.inactive', function () {
_this2.maskActived = false;
_this2.showSelector();
_this2.preventEditorClick();
});
this.$on('mask.moving', function (e, drag) {
var mask = _this2.mask;
var dx = drag.dx;
var dy = drag.dy;
mask.top = dy > 0 ? drag.startY : drag.startY + dy;
mask.left = dx > 0 ? drag.startX : drag.startX + dx;
mask.height = Math.abs(dy);
mask.width = Math.abs(dx);
_this2.checkElements(drag);
});
},
beforeDestroy: function beforeDestroy() {
this.$emit('destroy');
}
};
module.exports = exports['default'];