123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 |
- /*!
- * Cropper v0.3.2
- * https://github.com/fengyuanchen/cropper
- *
- * Copyright 2014 Fengyuan Chen
- * Released under the MIT license
- */
- (function(factory) {
- if (typeof define === "function" && define.amd) {
- // AMD. Register as anonymous module.
- define(["jquery"], factory);
- } else {
- // Browser globals.
- factory(jQuery);
- }
- }(function($) {
- "use strict";
- var $window = $(window),
- Cropper = function(element, options) {
- options = $.isPlainObject(options) ? options : {};
- this.$image = $(element);
- this.defaults = $.extend({}, Cropper.defaults, this.$image.data(), options);
- this.init();
- };
- Cropper.prototype = {
- construstor: Cropper,
- init: function() {
- this.setAspectRatio(this.defaults.aspectRatio);
- this.render();
- },
- render: function(callback) {
- var that = this,
- $image = this.$image,
- $clone,
- src;
- if (this.active) {
- return;
- }
- if (this.$clone) {
- this.$clone.remove(); // Remove the old clone
- }
- src = $image.attr("src"); // Don't use "prop"
- $clone = $('<img src="' + src + '">');
- $clone.on("load", function() {
- var image;
- $clone.off("load");
- if (this.naturalWidth && this.naturalHeight) {
- image = {
- naturalHeight: this.naturalHeight,
- naturalWidth: this.naturalWidth
- };
- } else {
- Cropper.fn.size($clone, {
- height: "auto",
- width: "auto"
- });
- image = Cropper.fn.size($clone);
- image = {
- naturalHeight: image.height,
- naturalWidth: image.width
- };
- }
- Cropper.fn.size($clone, {
- height: "100%",
- width: "100%"
- });
- image.aspectRatio = image.naturalWidth / image.naturalHeight;
- that.src = src;
- that.image = image;
- that.active = true;
- that.createCropper();
- });
- if ($.isFunction(callback)) {
- $image.on("ready.cropper", callback);
- }
- this.$clone = $clone;
- $image.after($clone);
- },
- unrender: function() {
- if (this.active) {
- this.active = false;
- this.removeCropper();
- this.src = "";
- this.image = null;
- this.cropper = null;
- this.dragger = null;
- }
- },
- rerender: function() {
- this.unrender();
- this.render();
- },
- resize: function() {
- clearTimeout(this.resizing);
- this.resizing = setTimeout($.proxy(this.rerender, this), 200);
- },
- createCropper: function() {
- this.$cropper = $(Cropper.template);
- this.$dragger = this.$cropper.find(".cropper-dragger");
- Cropper.fn.toggle(this.$image);
- this.$image.after(this.$cropper);
- this.$cropper.prepend(this.$clone);
- if (!this.defaults.modal) {
- Cropper.fn.toggle(this.$cropper.find(".cropper-modal"));
- }
- this.setPreview();
- this.addListener();
- },
- removeCropper: function() {
- this.removeListener();
- this.$preview = null;
- this.$clone.remove();
- this.$clone = null;
- this.$dragger = null;
- this.$cropper.remove();
- this.$cropper = null;
- Cropper.fn.toggle(this.$image);
- },
- addListener: function() {
- this.$cropper.bind("mousedown touchstart", $.proxy(this.dragstart, this));
- this.$cropper.bind("mousemove touchmove", $.proxy(this.dragmove, this));
- this.$cropper.bind("mouseup mouseleave touchend touchleave", $.proxy(this.dragend, this));
- $window.on("resize", $.proxy(this.resize, this));
- },
- removeListener: function() {
- this.$cropper.unbind("mousedown touchstart", this.dragstart);
- this.$cropper.unbind("mousemove touchmove", this.dragmove);
- this.$cropper.unbind("mouseup mouseleave touchend touchleave", this.dragend);
- $window.off("resize", this.resize);
- },
- setPreview: function() {
- var preview = this.defaults.preview;
- this.$preview = this.$cropper.find(".cropper-preview");
- if (typeof preview === "string" && preview.length > 0) {
- this.$preview = this.$preview.add(preview);
- }
- this.$preview.html('<img src="' + this.src + '">');
- this.setCropper();
- },
- setCropper: function() {
- var $container = this.$image.parent(),
- container = Cropper.fn.size($container),
- image = this.image,
- cropper;
- if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {
- cropper = {
- height: container.width / image.aspectRatio,
- width: container.width,
- left: 0
- };
- cropper.top = (container.height - cropper.height) / 2;
- } else {
- cropper = {
- height: container.height,
- width: container.height * image.aspectRatio,
- top: 0
- };
- cropper.left = (container.width - cropper.width) / 2;
- }
- $.each(cropper, function(i, n) {
- cropper[i] = Math.round(n);
- });
- image.height = cropper.height;
- image.width = cropper.width;
- image.ratio = image.width / image.naturalWidth;
- Cropper.fn.position($container);
- this.$cropper.css({
- height: cropper.height,
- left: cropper.left,
- top: cropper.top,
- width: cropper.width
- });
- this.cropper = cropper;
- this.setDragger();
- },
- setDragger: function() {
- var cropper = this.cropper,
- // If not set, use the original aspect ratio of the image.
- aspectRatio = this.defaults.aspectRatio || this.image.aspectRatio,
- dragger;
- if (((cropper.height * aspectRatio) - cropper.width) >= 0) {
- dragger = {
- height: cropper.width / aspectRatio,
- width: cropper.width,
- left: 0,
- top: (cropper.height - (cropper.width / aspectRatio)) / 2,
- maxWidth: cropper.width,
- maxHeight: cropper.width / aspectRatio
- };
- } else {
- dragger = {
- height: cropper.height,
- width: cropper.height * aspectRatio,
- left: (cropper.width - (cropper.height * aspectRatio)) / 2,
- top: 0,
- maxHeight: cropper.height,
- maxWidth: cropper.height * aspectRatio
- };
- }
- dragger.height *= 0.8;
- dragger.width *= 0.8;
- dragger.left = (cropper.width - dragger.width) / 2;
- dragger.top = (cropper.height - dragger.height) / 2;
- this.dragger = Cropper.fn.round(dragger);
- this.setData(this.defaults.data);
- this.$image.trigger("ready.cropper").off("ready.cropper");
- },
- resetDragger: function() {
- var dragger = this.dragger,
- cropper = this.cropper;
- dragger.width = dragger.width > dragger.maxWidth ? dragger.maxWidth : Math.abs(dragger.width);
- dragger.height = dragger.height > dragger.maxHeight ? dragger.maxHeight : Math.abs(dragger.height);
- dragger.maxLeft = cropper.width - dragger.width;
- dragger.maxTop = cropper.height - dragger.height;
- dragger.left = dragger.left < 0 ? 0 : dragger.left > dragger.maxLeft ? dragger.maxLeft : dragger.left;
- dragger.top = dragger.top < 0 ? 0 : dragger.top > dragger.maxTop ? dragger.maxTop : dragger.top;
- dragger = Cropper.fn.round(dragger);
- this.$dragger.css({
- height: dragger.height,
- left: dragger.left,
- top: dragger.top,
- width: dragger.width
- });
- this.dragger = dragger;
- this.preview();
- this.output();
- },
- dragging: function() {
- var direction = this.direction,
- dragger = this.dragger,
- aspectRatio = this.defaults.aspectRatio,
- range = {
- x: this.endX - this.startX,
- y: this.endY - this.startY
- };
- if (aspectRatio) {
- range.X = range.y * aspectRatio;
- range.Y = range.x / aspectRatio;
- }
- switch (direction) {
- // dragging
- case "e":
- dragger.width += range.x;
- if (aspectRatio) {
- dragger.height = dragger.width / aspectRatio;
- dragger.top -= range.Y / 2;
- }
- if (dragger.width < 0) {
- this.direction = "w";
- dragger.width = 0;
- }
- break;
- case "n":
- dragger.height -= range.y;
- dragger.top += range.y;
- if (aspectRatio) {
- dragger.width = dragger.height * aspectRatio;
- dragger.left += range.X / 2;
- }
- if (dragger.height < 0) {
- this.direction = "s";
- dragger.height = 0;
- }
- break;
- case "w":
- dragger.width -= range.x;
- dragger.left += range.x;
- if (aspectRatio) {
- dragger.height = dragger.width / aspectRatio;
- dragger.top += range.Y / 2;
- }
- if (dragger.width < 0) {
- this.direction = "e";
- dragger.width = 0;
- }
- break;
- case "s":
- dragger.height += range.y;
- if (aspectRatio) {
- dragger.width = dragger.height * aspectRatio;
- dragger.left -= range.X / 2;
- }
- if (dragger.height < 0) {
- this.direction = "n";
- dragger.height = 0;
- }
- break;
- case "ne":
- dragger.height -= range.y;
- dragger.top += range.y;
- if (aspectRatio) {
- dragger.width = dragger.height * aspectRatio;
- } else {
- dragger.width += range.x;
- }
- if (dragger.height < 0) {
- this.direction = "sw";
- dragger.height = 0;
- dragger.width = 0;
- }
- break;
- case "nw":
- dragger.height -= range.y;
- dragger.top += range.y;
- if (aspectRatio) {
- dragger.width = dragger.height * aspectRatio;
- dragger.left += range.X;
- } else {
- dragger.width -= range.x;
- dragger.left += range.x;
- }
- if (dragger.height < 0) {
- this.direction = "se";
- dragger.height = 0;
- dragger.width = 0;
- }
- break;
- case "sw":
- dragger.width -= range.x;
- dragger.left += range.x;
- if (aspectRatio) {
- dragger.height = dragger.width / aspectRatio;
- } else {
- dragger.height += range.y;
- }
- if (dragger.width < 0) {
- this.direction = "ne";
- dragger.height = 0;
- dragger.width = 0;
- }
- break;
- case "se":
- dragger.width += range.x;
- if (aspectRatio) {
- dragger.height = dragger.width / aspectRatio;
- } else {
- dragger.height += range.y;
- }
- if (dragger.width < 0) {
- this.direction = "nw";
- dragger.height = 0;
- dragger.width = 0;
- }
- break;
- // moving
- default:
- dragger.left += range.x;
- dragger.top += range.y;
- }
- this.resetDragger();
- this.startX = this.endX;
- this.startY = this.endY;
- },
- output: function() {
- this.defaults.done(this.getData());
- },
- preview: function() {
- var that = this,
- cropper = that.cropper,
- dragger = that.dragger;
- this.$preview.each(function() {
- var $this = $(this),
- ratio = $this.outerWidth() / dragger.width,
- styles = {
- height: cropper.height,
- marginLeft: - dragger.left,
- marginTop: - dragger.top,
- width: cropper.width
- };
- $this.css({overflow: "hidden"});
- $this.find("img").css(Cropper.fn.round(styles, function(n) {
- return n * ratio;
- }));
- });
- },
- // Public methods
- enable: function(callback) {
- this.render(callback);
- },
- disable: function() {
- this.unrender();
- },
- setAspectRatio: function(aspectRatio) {
- if (aspectRatio === "auto" || ($.isNumeric(aspectRatio) && aspectRatio > 0)) {
- this.defaults.aspectRatio = aspectRatio === "auto" ? NaN : aspectRatio;
- if (this.active) {
- this.setDragger();
- }
- }
- },
- setData: function(data) {
- var cropper = this.cropper,
- dragger = this.dragger,
- aspectRatio = this.defaults.aspectRatio,
- isNumber = function(n) {
- return typeof n === "number";
- };
- if (!this.active) {
- return;
- }
- if ($.isPlainObject(data) && !$.isEmptyObject(data)) {
- data = Cropper.fn.transformData(data, this.image.ratio);
- if (isNumber(data.x1) && data.x1 <= cropper.width) {
- dragger.left = data.x1;
- }
- if (isNumber(data.y1) && data.y1 <= cropper.height) {
- dragger.top = data.y1;
- }
- if (aspectRatio){
- if (isNumber(data.width) && data.width <= cropper.width) {
- dragger.width = data.width;
- dragger.height = dragger.width / aspectRatio;
- } else if (isNumber(data.height) && data.height <= cropper.height) {
- dragger.height = data.height;
- dragger.width = dragger.height * aspectRatio;
- } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
- dragger.width = data.x2 - dragger.left;
- dragger.height = dragger.width / aspectRatio;
- } else if (isNumber(data.y2) && data.y2 <= cropper.height) {
- dragger.height = data.y2 - dragger.top;
- dragger.width = dragger.height * aspectRatio;
- }
- } else {
- if (isNumber(data.width) && data.width <= cropper.width) {
- dragger.width = data.width;
- } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
- dragger.width = data.x2 - dragger.left;
- }
- if (isNumber(data.height) && data.height <= cropper.height) {
- dragger.height = data.height;
- } else if (isNumber(data.y2) && data.height <= cropper.height) {
- dragger.height = data.y2 - dragger.top;
- }
- }
- }
- this.dragger = dragger;
- this.resetDragger();
- },
- getData: function() {
- var dragger = this.dragger,
- data = {};
- if (this.active) {
- data = {
- x1: dragger.left,
- y1: dragger.top,
- width: dragger.width,
- height: dragger.height,
- x2: dragger.left + dragger.width,
- y2: dragger.top + dragger.height
- };
- data = Cropper.fn.transformData(data, (1 / this.image.ratio));
- }
- return data;
- },
- setImgSrc: function(src) {
- if (typeof src === "string" && src.length > 0 && src !== this.src) {
- this.$image.attr("src", src);
- this.rerender();
- }
- },
- getImgInfo: function() {
- return this.image || {};
- },
- // Public events
- dragstart: function(event) {
- var touches = Cropper.fn.getOriginalEvent(event).touches,
- e = event,
- touching,
- direction;
- if (touches && touches.length === 1) {
- e = touches[0];
- this.touchId = e.identifier;
- touching = true;
- }
- direction = $(e.target).data().direction;
- if (Cropper.fn.isDirection(direction)) {
- this.startX = e.pageX;
- this.startY = e.pageY;
- this.direction = direction;
- this.$image.trigger("dragstart");
- touching && event.preventDefault();
- }
- },
- dragmove: function(event) {
- var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
- e = event,
- touching;
- if (touches && touches.length === 1) {
- e = touches[0];
- touching = true;
- if (e.identifier !== this.touchId) {
- return;
- }
- }
- if (this.direction) {
- this.$image.trigger("dragmove");
- touching && event.preventDefault();
- this.endX = e.pageX;
- this.endY = e.pageY;
- this.dragging();
- }
- },
- dragend: function(event) {
- var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
- e = event,
- touching;
- if (touches && touches.length === 1) {
- e = touches[0];
- touching = true;
- if (e.identifier !== this.touchId) {
- return;
- }
- }
- if (this.direction) {
- this.direction = "";
- this.$image.trigger("dragend");
- touching && event.preventDefault();
- }
- }
- };
- // Common methods
- Cropper.fn = {
- toggle: function($e) {
- $e.toggleClass("cropper-hidden");
- },
- position: function($e, option) {
- var position = $e.css("position");
- if (position === "static") {
- $e.css("position", option || "relative");
- }
- },
- size: function($e, options) {
- if ($.isPlainObject(options)) {
- $e.css(options);
- } else {
- return {
- height: $e.height(),
- width: $e.width()
- };
- }
- },
- round: function(data, fn) {
- var value,
- i;
- for (i in data) {
- value = data[i];
- if (data.hasOwnProperty(i) && typeof value === "number") {
- data[i] = Math.round($.isFunction(fn) ? fn(value) : value);
- }
- }
- return data;
- },
- transformData: function(data, ratio) {
- var that = this,
- result = {};
- $.each(data, function(i, n) {
- if (that.isDataOption(i) && $.isNumeric(n) && n >= 0) {
- result[i] = Math.round(n * ratio);
- }
- });
- return result;
- },
- getOriginalEvent: function(event) {
- if (event && typeof event.originalEvent !== "undefined") {
- event = event.originalEvent;
- }
- return event;
- },
- isDataOption: function(s) {
- return /^(x1|y1|x2|y2|width|height)$/i.test(s);
- },
- isDirection: function(s) {
- return /^(\*|e|n|w|s|ne|nw|sw|se)$/i.test(s);
- }
- };
- Cropper.template = [
- '<div class="cropper-container">',
- '<div class="cropper-modal"></div>',
- '<div class="cropper-dragger">',
- '<span class="cropper-preview"></span>',
- '<span class="cropper-dashed dashed-h"></span>',
- '<span class="cropper-dashed dashed-v"></span>',
- '<span class="cropper-face" data-direction="*"></span>',
- '<span class="cropper-line line-e" data-direction="e"></span>',
- '<span class="cropper-line line-n" data-direction="n"></span>',
- '<span class="cropper-line line-w" data-direction="w"></span>',
- '<span class="cropper-line line-s" data-direction="s"></span>',
- '<span class="cropper-point point-e" data-direction="e"></span>',
- '<span class="cropper-point point-n" data-direction="n"></span>',
- '<span class="cropper-point point-w" data-direction="w"></span>',
- '<span class="cropper-point point-s" data-direction="s"></span>',
- '<span class="cropper-point point-ne" data-direction="ne"></span>',
- '<span class="cropper-point point-nw" data-direction="nw"></span>',
- '<span class="cropper-point point-sw" data-direction="sw"></span>',
- '<span class="cropper-point point-se" data-direction="se"></span>',
- '</div>',
- '</div>'
- ].join("");
- Cropper.defaults = {
- aspectRatio: "auto",
- data: {},
- done: function(/* data */) {},
- modal: true,
- preview: ""
- };
- Cropper.setDefaults = function(options) {
- $.extend(Cropper.defaults, options);
- };
- // Register as jQuery plugin
- $.fn.cropper = function(options, settings) {
- var result = this;
- this.each(function() {
- var $this = $(this),
- data = $this.data("cropper");
- if (!data) {
- data = new Cropper(this, options);
- $this.data("cropper", data);
- }
- if (typeof options === "string" && $.isFunction(data[options])) {
- result = data[options](settings);
- }
- });
- return (typeof result !== "undefined" ? result : this);
- };
- $.fn.cropper.Constructor = Cropper;
- $.fn.cropper.setDefaults = Cropper.setDefaults;
- $(function() {
- $("img[cropper]").cropper();
- });
- }));
|