vue-poster-editor
Version:
A poster editor based on Vue.js
275 lines (214 loc) • 9.55 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _debounce2 = require('lodash/debounce');
var _debounce3 = _interopRequireDefault(_debounce2);
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _utils = require('../utils/utils');
var _utils2 = _interopRequireDefault(_utils);
var _vueInherit = require('../utils/vue-inherit');
var _vueInherit2 = _interopRequireDefault(_vueInherit);
var _canvas = require('../utils/canvas');
var _editorElement = require('./editor-element');
var _editorElement2 = _interopRequireDefault(_editorElement);
var _editorElementMask = require('./editor-element-mask.html');
var _editorElementMask2 = _interopRequireDefault(_editorElementMask);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var max = Math.max,
round = Math.round;
exports.default = (0, _vueInherit2.default)(_editorElement2.default, {
template: _editorElementMask2.default,
computed: {
zoom: function zoom() {
return this.global.zoom;
},
imageUrl: function imageUrl() {
var model = this.model,
options = this.options;
return _utils2.default.getComputedUrl(model.imageUrl, options.fitCrossOrigin);
},
cssStyle: function cssStyle() {
var rect = this.rect;
var padding = rect.padding;
return {
height: rect.height + padding[0] + padding[2] + 'px',
width: rect.width + padding[1] + padding[3] + 'px',
transform: this.transform.toString(),
left: rect.left + 'px',
top: rect.top + 'px',
opacity: this.opacity
};
},
'urlAndMask': function urlAndMask() {
return this.model.url + this.model.mask;
},
'imageWidthAndImageHeight': function imageWidthAndImageHeight() {
return this.model.imageWidth + this.model.imageHeight;
},
'modelWidthAndModelHeight': function modelWidthAndModelHeight() {
return this.model.width + this.model.height;
},
'imageTransformPosition': function imageTransformPosition() {
return this.model.imageTransform.position.x + this.model.imageTransform.position.y;
},
'imageTransformRotation': function imageTransformRotation() {
return this.model.imageTransform.rotation;
}
},
methods: {
load: function load() {
var model = this.model,
options = this.options;
var fitCrossOrigin = options.fitCrossOrigin;
var loadImage = _utils2.default.loadImage;
var promise = model.imageUrl ? loadImage(model.imageUrl, fitCrossOrigin) : this.updateMask();
if (!model.imageUrl || options.mode !== 'mirror') {
promise = promise.then(function () {
return loadImage(model.url, fitCrossOrigin);
}).then(function (originalImg) {
model.$naturalHeight = originalImg.naturalHeight;
model.$naturalWidth = originalImg.naturalWidth;
});
}
return promise;
},
getCanvas: function getCanvas() {
var canvas = this.$canvas;
if (!canvas) {
canvas = this.$canvas = (0, _canvas.createCanvas)(100, 100);
}
return _bluebird2.default.resolve(canvas);
},
getContext: function getContext() {
var _this = this;
var model = this.model,
options = this.options;
return _bluebird2.default.all([_utils2.default.loadImage(model.url, options.fitCrossOrigin), _utils2.default.loadImage(model.mask, options.fitCrossOrigin)]).spread(function (img, mask) {
_this.$img = img;
_this.$mask = mask;
return _this.updateStage();
});
},
updateStage: function updateStage() {
var _this2 = this;
return this.getCanvas().then(function (canvas) {
var model = _this2.model;
var context = canvas.getContext('2d');
var _options = _this2.options,
maskResizeOptions = _options.maskResizeOptions,
maskPixelRatio = _options.maskPixelRatio;
var mask = _this2.$mask;
var img = _this2.$img;
if (!mask) {
return;
}
var imageTransform = model.imageTransform;
var imageWidth = model.imageWidth,
imageHeight = model.imageHeight,
width = model.width,
height = model.height;
var _imageTransform$posit = imageTransform.position,
translateX = _imageTransform$posit.x,
translateY = _imageTransform$posit.y;
var pixelRatio = max(1, +maskPixelRatio || 1);
var canvasWidth = round(width * pixelRatio);
var canvasHeight = round(height * pixelRatio);
canvas.width = canvasWidth;
canvas.height = canvasHeight;
context.scale(pixelRatio, pixelRatio);
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.drawImage(mask, 0, 0, canvasWidth, canvasHeight);
context.globalCompositeOperation = 'source-over';
var imageSize = {
width: imageWidth,
height: imageHeight
};
var imageCenter = {
x: translateX + imageSize.width / 2,
y: translateY + imageSize.height / 2
};
return _bluebird2.default.try(function () {
return (0, _canvas.resizeImageByCanvas)(img, imageWidth, imageHeight, maskResizeOptions);
}).then(function (imgCanvas) {
(0, _canvas.drawImageToCanvas)(canvas, imgCanvas, imageCenter, imageSize, imageTransform.rotation);
return context;
});
});
},
renderToImage: function renderToImage() {
var _this3 = this;
return this.getContext().then(function (context) {
return _this3.rendererToBase64(context) || null;
});
},
rendererToBase64: function rendererToBase64(context) {
var hasOpacity = false;
var pixels = null;
pixels = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
pixels = pixels.data;
var index = pixels.length - 1;
while (index > 0) {
if (pixels[index] !== 255) {
hasOpacity = true;
break;
}
index -= 4;
}
hasOpacity = true;
var imageType = 'image/' + (hasOpacity ? 'png' : 'jpeg');
return context.canvas.toDataURL(imageType, 1) || null;
},
updateMask: function updateMask() {
var _this4 = this;
var fitCrossOrigin = this.options.fitCrossOrigin;
return this.renderToImage().tap(function (url) {
return _utils2.default.loadImage(url, fitCrossOrigin);
}).then(function (url) {
_this4.model.imageUrl = url;
return url;
});
},
destoryRenderer: function destoryRenderer() {}
},
events: {
'editor.transform.inactive': function editorTransformInactive(model, drag, datas) {
if (this.model === model && datas.action === 'resize') {
var widthRatio = model.width / drag.width;
var heightRatio = model.height / drag.height;
var position = model.imageTransform.position;
model.imageWidth *= widthRatio;
model.imageHeight *= heightRatio;
position.x *= widthRatio;
position.y *= heightRatio;
}
}
},
mounted: function mounted() {
var _this5 = this;
this.model.$resizeLimit = true;
this.model.$getResizeLimit = function () {
return {
maxWidth: Infinity,
minWidth: 2,
maxHeight: Infinity,
minHeight: 2
};
};
var updateMaskImmediately = (0, _debounce3.default)(this.updateMask, 350, { 'leading': true, 'trailing': false });
var updateMaskFinished = (0, _debounce3.default)(this.updateMask, 350, { 'leading': false, 'trailing': true });
this.$watch('urlAndMask', function () {
updateMaskImmediately();
_utils2.default.loadImage(_this5.model.url).then(function (img) {
_this5.model.$naturalWidth = img.naturalWidth;
_this5.model.$naturalHeight = img.naturalHeight;
});
});
this.$watch('imageWidthAndImageHeight', updateMaskFinished);
this.$watch('modelWidthAndModelHeight', updateMaskImmediately);
this.$watch('imageTransformPosition', updateMaskImmediately);
this.$watch('imageTransformRotation', updateMaskImmediately);
}
});
module.exports = exports['default'];