/*!
* ZUI: 图片裁剪工具 - v1.9.2 - 2020-07-09
* http://openzui.com
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2020 cnezsoft.com; Licensed MIT
*/
/* ========================================================================
* ZUI: img-cutter.js
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($, Math, undefined) {
'use strict';
if(!$.fn.draggable) console.error('img-cutter requires draggable.js');
if(!$.zui.imgReady) console.error('img-cutter requires image.ready.js');
var NAME = 'zui.imgCutter';
var ImgCutter = function(element, options) {
this.$ = $(element);
this.initOptions(options);
this.init();
};
ImgCutter.DEFAULTS = {
coverColor: '#000',
coverOpacity: 0.6,
// fixedRatio: false,
defaultWidth: 128,
defaultHeight: 128,
minWidth: 48,
minHeight: 48,
// onSizeError: null
}; // default options
ImgCutter.prototype.callEvent = function(name, params) {
var result = this.$.callEvent(name + '.' + NAME, params, this);
return !(result.result !== undefined && (!result.result));
};
ImgCutter.prototype.initOptions = function(options) {
this.options = $.extend({}, ImgCutter.DEFAULTS, this.$.data(), options);
this.options.coverOpacityIE = this.options.coverOpacity * 100;
this.clipWidth = this.options.defaultWidth;
this.clipHeight = this.options.defaultHeight;
};
ImgCutter.prototype.init = function() {
this.initDom();
this.initSize();
this.bindEvents();
};
ImgCutter.prototype.initDom = function() {
this.$canvas = this.$.children('.canvas');
this.$img = this.$canvas.children('img');
this.$actions = this.$.children('.actions');
this.$btn = this.$.find('.img-cutter-submit');
this.$preview = this.$.find('.img-cutter-preview');
this.options.img = this.$img.attr('src');
this.$canvas.append('
'.format(this.options));
this.$cover = this.$canvas.children('.cover');
this.$controller = this.$canvas.children('.controller');
this.$cliper = this.$canvas.children('.cliper');
this.$chipImg = this.$cliper.children('img');
if(this.options.fixedRatio) {
this.$.addClass('fixed-ratio');
}
};
ImgCutter.prototype.resetImage = function(img) {
var that = this;
that.options.img = img;
that.$img.attr('src', img);
that.$chipImg.attr('src', img);
that.imgWidth = undefined;
that.left = undefined;
that.initSize();
};
ImgCutter.prototype.initSize = function() {
var that = this;
if(!that.imgWidth) {
$.zui.imgReady(that.options.img, function() {
that.imgWidth = this.width;
that.imgHeight = this.height;
if (this.width < that.options.minWidth || this.height < that.options.minHeight) {
if (that.options.onSizeError) {
that.options.onSizeError({width: this.width, height: this.height});
}
that.options.minWidth = Math.min(this.width, that.options.minWidth);
that.options.minHeight = Math.min(this.height, that.options.minHeight);
}
that.callEvent('ready');
});
}
var waitImgWidth = setInterval(function() {
if(that.imgWidth) {
clearInterval(waitImgWidth);
that.width = Math.min(that.imgWidth, that.$.width());
that.$canvas.css('width', this.width);
that.$cliper.css('width', this.width);
that.height = that.$canvas.height();
if(that.left === undefined) {
that.left = Math.floor((that.width - that.$controller.width()) / 2);
that.top = Math.floor((that.height - that.$controller.height()) / 2);
}
that.refreshSize();
}
}, 0);
};
ImgCutter.prototype.refreshSize = function(ratioSide) {
var options = this.options;
this.clipWidth = Math.max(options.minWidth, Math.min(this.width, this.clipWidth));
this.clipHeight = Math.max(options.minHeight, Math.min(this.height, this.clipHeight));
if(options.fixedRatio) {
if(ratioSide && ratioSide === 'height') {
this.clipWidth = Math.max(options.minWidth, Math.min(this.width, this.clipHeight * options.defaultWidth / options.defaultHeight));
this.clipHeight = this.clipWidth * options.defaultHeight / options.defaultWidth;
} else {
this.clipHeight = Math.max(options.minHeight, Math.min(this.height, this.clipWidth * options.defaultHeight / options.defaultWidth));
this.clipWidth = this.clipHeight * options.defaultWidth / options.defaultHeight;
}
}
this.left = Math.min(this.width - this.clipWidth, Math.max(0, this.left));
this.top = Math.min(this.height - this.clipHeight, Math.max(0, this.top));
this.right = this.left + this.clipWidth;
this.bottom = this.top + this.clipHeight;
this.$controller.css({
left: this.left,
top: this.top,
width: this.clipWidth,
height: this.clipHeight
});
this.$cliper.css('clip', 'rect({0}px {1}px {2}px {3}px'.format(this.top, this.left + this.clipWidth, this.top + this.clipHeight, this.left));
this.callEvent('change', {
top: this.top,
left: this.left,
bottom: this.bottom,
right: this.right,
width: this.clipWidth,
height: this.clipHeight
});
};
ImgCutter.prototype.getData = function() {
var that = this;
that.data = {
originWidth: that.imgWidth,
originHeight: that.imgHeight,
scaleWidth: that.width,
scaleHeight: that.height,
width: that.right - that.left,
height: that.bottom - that.top,
left: that.left,
top: that.top,
right: that.right,
bottom: that.bottom,
scaled: that.imgWidth != that.width || that.imgHeight != that.height
};
return that.data;
};
ImgCutter.prototype.bindEvents = function() {
var that = this,
options = this.options;
this.$.resize($.proxy(this.initSize, this));
this.$btn.hover(function() {
that.$.toggleClass('hover');
}).click(function() {
var data = that.getData();
if(!that.callEvent('before', data)) return;
var url = options.post || options.get || options.url || null;
if(url !== null) {
$.ajax({
type: options.post ? 'POST' : 'GET',
url: url,
data: data
})
.done(function(e) {
that.callEvent('done', e);
}).fail(function(e) {
that.callEvent('fail', e);
}).always(function(e) {
that.callEvent('always', e);
});
}
});
this.$controller.draggable({
move: false,
container: this.$canvas,
drag: function(e) {
that.left += e.smallOffset.x;
that.top += e.smallOffset.y;
that.refreshSize();
}
});
this.$controller.children('.control').draggable({
move: false,
container: this.$canvas,
stopPropagation: true,
drag: function(e) {
var dr = e.element.data('direction');
var offset = e.smallOffset;
var ratioSide = false;
switch(dr) {
case 'left':
case 'top-left':
case 'bottom-left':
that.left += offset.x;
that.left = Math.min(that.right - options.minWidth, Math.max(0, that.left));
that.clipWidth = that.right - that.left;
break;
case 'right':
case 'top-right':
case 'bottom-right':
that.clipWidth += offset.x;
that.clipWidth = Math.min(that.width - that.left, Math.max(options.minWidth, that.clipWidth));
break;
}
switch(dr) {
case 'top':
case 'top-left':
case 'top-right':
that.top += offset.y;
that.top = Math.min(that.bottom - options.minHeight, Math.max(0, that.top));
that.clipHeight = that.bottom - that.top;
ratioSide = true;
break;
case 'bottom':
case 'bottom-left':
case 'bottom-right':
that.clipHeight += offset.y;
that.clipHeight = Math.min(that.height - that.top, Math.max(options.minHeight, that.clipHeight));
ratioSide = true;
break;
}
that.refreshSize(ratioSide);
}
});
};
$.fn.imgCutter = function(option) {
return this.each(function() {
var $this = $(this);
var data = $this.data(NAME);
var options = typeof option == 'object' && option;
if(!data) $this.data(NAME, (data = new ImgCutter(this, options)));
if(typeof option == 'string') data[option]();
});
};
$.fn.imgCutter.Constructor = ImgCutter;
$(function() {
$('[data-toggle="imgCutter"]').imgCutter();
});
}(jQuery, Math, undefined));