jquery-cropper 0.3.31 → 2.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/LICENSE.md +21 -0
- data/README.md +7 -11
- data/app/assets/javascripts/cropper.js +2703 -501
- data/app/assets/stylesheets/cropper.scss +244 -86
- data/lib/jquery/cropper/engine.rb +2 -2
- data/lib/jquery/cropper/version.rb +1 -1
- metadata +13 -14
- data/LICENSE.txt +0 -22
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZjI5NWM4MzRlZmExMzM3NmYyODhlMTcyOWYwY2E0ZDM5MWY5M2IxYw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e6ee7401215e8d55df0e0635218ef3ec72fe2c6
|
4
|
+
data.tar.gz: 9acdf34a0136bfb7b3e44e49830745773a79ebf9
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YmZiNDIzODZlYjliMjBhMDM0Mjk5NGZjZDcwY2Q1Nzg2YzcyYWNhZWVhODdk
|
11
|
-
NTAxMjgyMzliNDczZTJlMGM0YTNiY2YzZmMwYTFkNjdjMWI2NGQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
OWM1MTE2OWY2ZjdjZmQyOTkzN2Q5MjhkNDcyMTBhYjllYjYzMzIwYzQ0ZGI1
|
14
|
-
ZDc3MTYzMDBmNDU3NDg1ZGNkZTM4ZjYwMTI1ZTA3NDlhNTg3OTMzYzFhMDMx
|
15
|
-
Y2U2OWY2MDdjNTEzYjMzOGZlNDliMjk5OGEzMTgzYzg2YjMwOWE=
|
6
|
+
metadata.gz: 5a90c6e0225c8d5454400feb5d308c2ee2a53fe738115195a30eb5b678cd22c2425883adbec48cbdcda81006f991bce1cf9ce8146f4dc3c993c8d69e15cfdee5
|
7
|
+
data.tar.gz: 4d5fc527fb7ce4ff8e72bc847a7f6332ccc0dab7e94a07a36c9f49a6ea2c763ddbd967be439e9968ea81bbf4c5fd5e3bf17813115199f6f74ea2ee33ce9443a7
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Fengyuan Chen and other contributors.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Jquery::Cropper
|
2
2
|
|
3
|
-
|
3
|
+
It is a assets pipeline wrapper of jquery cropper plugin https://github.com/fengyuanchen/cropper
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -12,18 +12,14 @@ And then execute:
|
|
12
12
|
|
13
13
|
$ bundle
|
14
14
|
|
15
|
-
|
15
|
+
Add line to application.js
|
16
16
|
|
17
|
-
|
17
|
+
//= require cropper
|
18
18
|
|
19
|
-
|
19
|
+
Add line to application.scss
|
20
20
|
|
21
|
-
|
21
|
+
*= require cropper
|
22
22
|
|
23
|
-
##
|
23
|
+
## License
|
24
24
|
|
25
|
-
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
25
|
+
Released under the [MIT](http://opensource.org/licenses/mit-license.html) license.
|
@@ -1,770 +1,2972 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/*!
|
2
|
+
* Cropper v2.2.5
|
3
|
+
* https://github.com/fengyuanchen/cropper
|
4
|
+
*
|
5
|
+
* Copyright (c) 2014-2016 Fengyuan Chen and contributors
|
6
|
+
* Released under the MIT license
|
7
|
+
*
|
8
|
+
* Date: 2016-01-18T05:42:50.800Z
|
9
|
+
*/
|
10
|
+
|
11
|
+
(function (factory) {
|
12
|
+
if (typeof define === 'function' && define.amd) {
|
3
13
|
// AMD. Register as anonymous module.
|
4
|
-
define([
|
14
|
+
define(['jquery'], factory);
|
15
|
+
} else if (typeof exports === 'object') {
|
16
|
+
// Node / CommonJS
|
17
|
+
factory(require('jquery'));
|
5
18
|
} else {
|
6
19
|
// Browser globals.
|
7
20
|
factory(jQuery);
|
8
21
|
}
|
9
|
-
}(function($) {
|
22
|
+
})(function ($) {
|
23
|
+
|
24
|
+
'use strict';
|
25
|
+
|
26
|
+
// Globals
|
27
|
+
var $window = $(window);
|
28
|
+
var $document = $(document);
|
29
|
+
var location = window.location;
|
30
|
+
var ArrayBuffer = window.ArrayBuffer;
|
31
|
+
var Uint8Array = window.Uint8Array;
|
32
|
+
var DataView = window.DataView;
|
33
|
+
var btoa = window.btoa;
|
34
|
+
|
35
|
+
// Constants
|
36
|
+
var NAMESPACE = 'cropper';
|
37
|
+
|
38
|
+
// Classes
|
39
|
+
var CLASS_MODAL = 'cropper-modal';
|
40
|
+
var CLASS_HIDE = 'cropper-hide';
|
41
|
+
var CLASS_HIDDEN = 'cropper-hidden';
|
42
|
+
var CLASS_INVISIBLE = 'cropper-invisible';
|
43
|
+
var CLASS_MOVE = 'cropper-move';
|
44
|
+
var CLASS_CROP = 'cropper-crop';
|
45
|
+
var CLASS_DISABLED = 'cropper-disabled';
|
46
|
+
var CLASS_BG = 'cropper-bg';
|
47
|
+
|
48
|
+
// Events
|
49
|
+
var EVENT_MOUSE_DOWN = 'mousedown touchstart pointerdown MSPointerDown';
|
50
|
+
var EVENT_MOUSE_MOVE = 'mousemove touchmove pointermove MSPointerMove';
|
51
|
+
var EVENT_MOUSE_UP = 'mouseup touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel';
|
52
|
+
var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll';
|
53
|
+
var EVENT_DBLCLICK = 'dblclick';
|
54
|
+
var EVENT_LOAD = 'load.' + NAMESPACE;
|
55
|
+
var EVENT_ERROR = 'error.' + NAMESPACE;
|
56
|
+
var EVENT_RESIZE = 'resize.' + NAMESPACE; // Bind to window with namespace
|
57
|
+
var EVENT_BUILD = 'build.' + NAMESPACE;
|
58
|
+
var EVENT_BUILT = 'built.' + NAMESPACE;
|
59
|
+
var EVENT_CROP_START = 'cropstart.' + NAMESPACE;
|
60
|
+
var EVENT_CROP_MOVE = 'cropmove.' + NAMESPACE;
|
61
|
+
var EVENT_CROP_END = 'cropend.' + NAMESPACE;
|
62
|
+
var EVENT_CROP = 'crop.' + NAMESPACE;
|
63
|
+
var EVENT_ZOOM = 'zoom.' + NAMESPACE;
|
64
|
+
|
65
|
+
// RegExps
|
66
|
+
var REGEXP_ACTIONS = /e|w|s|n|se|sw|ne|nw|all|crop|move|zoom/;
|
67
|
+
var REGEXP_DATA_URL = /^data\:/;
|
68
|
+
var REGEXP_DATA_URL_HEAD = /^data\:([^\;]+)\;base64,/;
|
69
|
+
var REGEXP_DATA_URL_JPEG = /^data\:image\/jpeg.*;base64,/;
|
70
|
+
|
71
|
+
// Data keys
|
72
|
+
var DATA_PREVIEW = 'preview';
|
73
|
+
var DATA_ACTION = 'action';
|
74
|
+
|
75
|
+
// Actions
|
76
|
+
var ACTION_EAST = 'e';
|
77
|
+
var ACTION_WEST = 'w';
|
78
|
+
var ACTION_SOUTH = 's';
|
79
|
+
var ACTION_NORTH = 'n';
|
80
|
+
var ACTION_SOUTH_EAST = 'se';
|
81
|
+
var ACTION_SOUTH_WEST = 'sw';
|
82
|
+
var ACTION_NORTH_EAST = 'ne';
|
83
|
+
var ACTION_NORTH_WEST = 'nw';
|
84
|
+
var ACTION_ALL = 'all';
|
85
|
+
var ACTION_CROP = 'crop';
|
86
|
+
var ACTION_MOVE = 'move';
|
87
|
+
var ACTION_ZOOM = 'zoom';
|
88
|
+
var ACTION_NONE = 'none';
|
89
|
+
|
90
|
+
// Supports
|
91
|
+
var SUPPORT_CANVAS = $.isFunction($('<canvas>')[0].getContext);
|
92
|
+
|
93
|
+
// Maths
|
94
|
+
var num = Number;
|
95
|
+
var min = Math.min;
|
96
|
+
var max = Math.max;
|
97
|
+
var abs = Math.abs;
|
98
|
+
var sin = Math.sin;
|
99
|
+
var cos = Math.cos;
|
100
|
+
var sqrt = Math.sqrt;
|
101
|
+
var round = Math.round;
|
102
|
+
var floor = Math.floor;
|
103
|
+
|
104
|
+
// Utilities
|
105
|
+
var fromCharCode = String.fromCharCode;
|
106
|
+
|
107
|
+
function isNumber(n) {
|
108
|
+
return typeof n === 'number' && !isNaN(n);
|
109
|
+
}
|
110
|
+
|
111
|
+
function isUndefined(n) {
|
112
|
+
return typeof n === 'undefined';
|
113
|
+
}
|
114
|
+
|
115
|
+
function toArray(obj, offset) {
|
116
|
+
var args = [];
|
117
|
+
|
118
|
+
// This is necessary for IE8
|
119
|
+
if (isNumber(offset)) {
|
120
|
+
args.push(offset);
|
121
|
+
}
|
122
|
+
|
123
|
+
return args.slice.apply(obj, args);
|
124
|
+
}
|
125
|
+
|
126
|
+
// Custom proxy to avoid jQuery's guid
|
127
|
+
function proxy(fn, context) {
|
128
|
+
var args = toArray(arguments, 2);
|
129
|
+
|
130
|
+
return function () {
|
131
|
+
return fn.apply(context, args.concat(toArray(arguments)));
|
132
|
+
};
|
133
|
+
}
|
134
|
+
|
135
|
+
function isCrossOriginURL(url) {
|
136
|
+
var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);
|
137
|
+
|
138
|
+
return parts && (
|
139
|
+
parts[1] !== location.protocol ||
|
140
|
+
parts[2] !== location.hostname ||
|
141
|
+
parts[3] !== location.port
|
142
|
+
);
|
143
|
+
}
|
144
|
+
|
145
|
+
function addTimestamp(url) {
|
146
|
+
var timestamp = 'timestamp=' + (new Date()).getTime();
|
147
|
+
|
148
|
+
return (url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp);
|
149
|
+
}
|
150
|
+
|
151
|
+
function getCrossOrigin(crossOrigin) {
|
152
|
+
return crossOrigin ? ' crossOrigin="' + crossOrigin + '"' : '';
|
153
|
+
}
|
154
|
+
|
155
|
+
function getImageSize(image, callback) {
|
156
|
+
var newImage;
|
157
|
+
|
158
|
+
// Modern browsers
|
159
|
+
if (image.naturalWidth) {
|
160
|
+
return callback(image.naturalWidth, image.naturalHeight);
|
161
|
+
}
|
162
|
+
|
163
|
+
// IE8: Don't use `new Image()` here (#319)
|
164
|
+
newImage = document.createElement('img');
|
165
|
+
|
166
|
+
newImage.onload = function () {
|
167
|
+
callback(this.width, this.height);
|
168
|
+
};
|
169
|
+
|
170
|
+
newImage.src = image.src;
|
171
|
+
}
|
172
|
+
|
173
|
+
function getTransform(options) {
|
174
|
+
var transforms = [];
|
175
|
+
var rotate = options.rotate;
|
176
|
+
var scaleX = options.scaleX;
|
177
|
+
var scaleY = options.scaleY;
|
178
|
+
|
179
|
+
if (isNumber(rotate)) {
|
180
|
+
transforms.push('rotate(' + rotate + 'deg)');
|
181
|
+
}
|
182
|
+
|
183
|
+
if (isNumber(scaleX) && isNumber(scaleY)) {
|
184
|
+
transforms.push('scale(' + scaleX + ',' + scaleY + ')');
|
185
|
+
}
|
186
|
+
|
187
|
+
return transforms.length ? transforms.join(' ') : 'none';
|
188
|
+
}
|
189
|
+
|
190
|
+
function getRotatedSizes(data, isReversed) {
|
191
|
+
var deg = abs(data.degree) % 180;
|
192
|
+
var arc = (deg > 90 ? (180 - deg) : deg) * Math.PI / 180;
|
193
|
+
var sinArc = sin(arc);
|
194
|
+
var cosArc = cos(arc);
|
195
|
+
var width = data.width;
|
196
|
+
var height = data.height;
|
197
|
+
var aspectRatio = data.aspectRatio;
|
198
|
+
var newWidth;
|
199
|
+
var newHeight;
|
200
|
+
|
201
|
+
if (!isReversed) {
|
202
|
+
newWidth = width * cosArc + height * sinArc;
|
203
|
+
newHeight = width * sinArc + height * cosArc;
|
204
|
+
} else {
|
205
|
+
newWidth = width / (cosArc + sinArc / aspectRatio);
|
206
|
+
newHeight = newWidth / aspectRatio;
|
207
|
+
}
|
208
|
+
|
209
|
+
return {
|
210
|
+
width: newWidth,
|
211
|
+
height: newHeight
|
212
|
+
};
|
213
|
+
}
|
214
|
+
|
215
|
+
function getSourceCanvas(image, data) {
|
216
|
+
var canvas = $('<canvas>')[0];
|
217
|
+
var context = canvas.getContext('2d');
|
218
|
+
var x = 0;
|
219
|
+
var y = 0;
|
220
|
+
var width = data.naturalWidth;
|
221
|
+
var height = data.naturalHeight;
|
222
|
+
var rotate = data.rotate;
|
223
|
+
var scaleX = data.scaleX;
|
224
|
+
var scaleY = data.scaleY;
|
225
|
+
var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1);
|
226
|
+
var rotatable = isNumber(rotate) && rotate !== 0;
|
227
|
+
var advanced = rotatable || scalable;
|
228
|
+
var canvasWidth = width;
|
229
|
+
var canvasHeight = height;
|
230
|
+
var translateX;
|
231
|
+
var translateY;
|
232
|
+
var rotated;
|
233
|
+
|
234
|
+
if (scalable) {
|
235
|
+
translateX = width / 2;
|
236
|
+
translateY = height / 2;
|
237
|
+
}
|
238
|
+
|
239
|
+
if (rotatable) {
|
240
|
+
rotated = getRotatedSizes({
|
241
|
+
width: width,
|
242
|
+
height: height,
|
243
|
+
degree: rotate
|
244
|
+
});
|
245
|
+
|
246
|
+
canvasWidth = rotated.width;
|
247
|
+
canvasHeight = rotated.height;
|
248
|
+
translateX = rotated.width / 2;
|
249
|
+
translateY = rotated.height / 2;
|
250
|
+
}
|
251
|
+
|
252
|
+
canvas.width = canvasWidth;
|
253
|
+
canvas.height = canvasHeight;
|
254
|
+
|
255
|
+
if (advanced) {
|
256
|
+
x = -width / 2;
|
257
|
+
y = -height / 2;
|
258
|
+
|
259
|
+
context.save();
|
260
|
+
context.translate(translateX, translateY);
|
261
|
+
}
|
262
|
+
|
263
|
+
if (rotatable) {
|
264
|
+
context.rotate(rotate * Math.PI / 180);
|
265
|
+
}
|
10
266
|
|
11
|
-
|
267
|
+
// Should call `scale` after rotated
|
268
|
+
if (scalable) {
|
269
|
+
context.scale(scaleX, scaleY);
|
270
|
+
}
|
271
|
+
|
272
|
+
context.drawImage(image, floor(x), floor(y), floor(width), floor(height));
|
273
|
+
|
274
|
+
if (advanced) {
|
275
|
+
context.restore();
|
276
|
+
}
|
277
|
+
|
278
|
+
return canvas;
|
279
|
+
}
|
280
|
+
|
281
|
+
function getTouchesCenter(touches) {
|
282
|
+
var length = touches.length;
|
283
|
+
var pageX = 0;
|
284
|
+
var pageY = 0;
|
12
285
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
286
|
+
if (length) {
|
287
|
+
$.each(touches, function (i, touch) {
|
288
|
+
pageX += touch.pageX;
|
289
|
+
pageY += touch.pageY;
|
290
|
+
});
|
291
|
+
|
292
|
+
pageX /= length;
|
293
|
+
pageY /= length;
|
294
|
+
}
|
295
|
+
|
296
|
+
return {
|
297
|
+
pageX: pageX,
|
298
|
+
pageY: pageY
|
19
299
|
};
|
300
|
+
}
|
301
|
+
|
302
|
+
function getStringFromCharCode(dataView, start, length) {
|
303
|
+
var str = '';
|
304
|
+
var i;
|
305
|
+
|
306
|
+
for (i = start, length += start; i < length; i++) {
|
307
|
+
str += fromCharCode(dataView.getUint8(i));
|
308
|
+
}
|
309
|
+
|
310
|
+
return str;
|
311
|
+
}
|
312
|
+
|
313
|
+
function getOrientation(arrayBuffer) {
|
314
|
+
var dataView = new DataView(arrayBuffer);
|
315
|
+
var length = dataView.byteLength;
|
316
|
+
var orientation;
|
317
|
+
var exifIDCode;
|
318
|
+
var tiffOffset;
|
319
|
+
var firstIFDOffset;
|
320
|
+
var littleEndian;
|
321
|
+
var endianness;
|
322
|
+
var app1Start;
|
323
|
+
var ifdStart;
|
324
|
+
var offset;
|
325
|
+
var i;
|
326
|
+
|
327
|
+
// Only handle JPEG image (start by 0xFFD8)
|
328
|
+
if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
|
329
|
+
offset = 2;
|
330
|
+
|
331
|
+
while (offset < length) {
|
332
|
+
if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
|
333
|
+
app1Start = offset;
|
334
|
+
break;
|
335
|
+
}
|
336
|
+
|
337
|
+
offset++;
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
if (app1Start) {
|
342
|
+
exifIDCode = app1Start + 4;
|
343
|
+
tiffOffset = app1Start + 10;
|
344
|
+
|
345
|
+
if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
|
346
|
+
endianness = dataView.getUint16(tiffOffset);
|
347
|
+
littleEndian = endianness === 0x4949;
|
348
|
+
|
349
|
+
if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
|
350
|
+
if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
|
351
|
+
firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
|
352
|
+
|
353
|
+
if (firstIFDOffset >= 0x00000008) {
|
354
|
+
ifdStart = tiffOffset + firstIFDOffset;
|
355
|
+
}
|
356
|
+
}
|
357
|
+
}
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
if (ifdStart) {
|
362
|
+
length = dataView.getUint16(ifdStart, littleEndian);
|
363
|
+
|
364
|
+
for (i = 0; i < length; i++) {
|
365
|
+
offset = ifdStart + i * 12 + 2;
|
366
|
+
|
367
|
+
if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {
|
368
|
+
|
369
|
+
// 8 is the offset of the current tag's value
|
370
|
+
offset += 8;
|
371
|
+
|
372
|
+
// Get the original orientation value
|
373
|
+
orientation = dataView.getUint16(offset, littleEndian);
|
374
|
+
|
375
|
+
// Override the orientation with the default value: 1
|
376
|
+
dataView.setUint16(offset, 1, littleEndian);
|
377
|
+
break;
|
378
|
+
}
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
return orientation;
|
383
|
+
}
|
384
|
+
|
385
|
+
function dataURLToArrayBuffer(dataURL) {
|
386
|
+
var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');
|
387
|
+
var binary = atob(base64);
|
388
|
+
var length = binary.length;
|
389
|
+
var arrayBuffer = new ArrayBuffer(length);
|
390
|
+
var dataView = new Uint8Array(arrayBuffer);
|
391
|
+
var i;
|
392
|
+
|
393
|
+
for (i = 0; i < length; i++) {
|
394
|
+
dataView[i] = binary.charCodeAt(i);
|
395
|
+
}
|
396
|
+
|
397
|
+
return arrayBuffer;
|
398
|
+
}
|
399
|
+
|
400
|
+
// Only available for JPEG image
|
401
|
+
function arrayBufferToDataURL(arrayBuffer) {
|
402
|
+
var dataView = new Uint8Array(arrayBuffer);
|
403
|
+
var length = dataView.length;
|
404
|
+
var base64 = '';
|
405
|
+
var i;
|
406
|
+
|
407
|
+
for (i = 0; i < length; i++) {
|
408
|
+
base64 += fromCharCode(dataView[i]);
|
409
|
+
}
|
410
|
+
|
411
|
+
return 'data:image/jpeg;base64,' + btoa(base64);
|
412
|
+
}
|
413
|
+
|
414
|
+
function Cropper(element, options) {
|
415
|
+
this.$element = $(element);
|
416
|
+
this.options = $.extend({}, Cropper.DEFAULTS, $.isPlainObject(options) && options);
|
417
|
+
this.isLoaded = false;
|
418
|
+
this.isBuilt = false;
|
419
|
+
this.isCompleted = false;
|
420
|
+
this.isRotated = false;
|
421
|
+
this.isCropped = false;
|
422
|
+
this.isDisabled = false;
|
423
|
+
this.isReplaced = false;
|
424
|
+
this.isLimited = false;
|
425
|
+
this.wheeling = false;
|
426
|
+
this.isImg = false;
|
427
|
+
this.originalUrl = '';
|
428
|
+
this.canvas = null;
|
429
|
+
this.cropBox = null;
|
430
|
+
this.init();
|
431
|
+
}
|
20
432
|
|
21
433
|
Cropper.prototype = {
|
22
|
-
|
434
|
+
constructor: Cropper,
|
23
435
|
|
24
|
-
init: function() {
|
25
|
-
this
|
26
|
-
|
436
|
+
init: function () {
|
437
|
+
var $this = this.$element;
|
438
|
+
var url;
|
439
|
+
|
440
|
+
if ($this.is('img')) {
|
441
|
+
this.isImg = true;
|
442
|
+
|
443
|
+
// Should use `$.fn.attr` here. e.g.: "img/picture.jpg"
|
444
|
+
this.originalUrl = url = $this.attr('src');
|
445
|
+
|
446
|
+
// Stop when it's a blank image
|
447
|
+
if (!url) {
|
448
|
+
return;
|
449
|
+
}
|
450
|
+
|
451
|
+
// Should use `$.fn.prop` here. e.g.: "http://example.com/img/picture.jpg"
|
452
|
+
url = $this.prop('src');
|
453
|
+
} else if ($this.is('canvas') && SUPPORT_CANVAS) {
|
454
|
+
url = $this[0].toDataURL();
|
455
|
+
}
|
456
|
+
|
457
|
+
this.load(url);
|
458
|
+
},
|
459
|
+
|
460
|
+
// A shortcut for triggering custom events
|
461
|
+
trigger: function (type, data) {
|
462
|
+
var e = $.Event(type, data);
|
463
|
+
|
464
|
+
this.$element.trigger(e);
|
465
|
+
|
466
|
+
return e;
|
27
467
|
},
|
28
468
|
|
29
|
-
|
30
|
-
var
|
31
|
-
|
32
|
-
|
33
|
-
|
469
|
+
load: function (url) {
|
470
|
+
var options = this.options;
|
471
|
+
var $this = this.$element;
|
472
|
+
var read;
|
473
|
+
var xhr;
|
34
474
|
|
35
|
-
if (
|
475
|
+
if (!url) {
|
36
476
|
return;
|
37
477
|
}
|
38
478
|
|
39
|
-
|
40
|
-
|
479
|
+
// Trigger build event first
|
480
|
+
$this.one(EVENT_BUILD, options.build);
|
481
|
+
|
482
|
+
if (this.trigger(EVENT_BUILD).isDefaultPrevented()) {
|
483
|
+
return;
|
41
484
|
}
|
42
485
|
|
43
|
-
|
44
|
-
|
486
|
+
this.url = url;
|
487
|
+
this.image = {};
|
45
488
|
|
46
|
-
|
47
|
-
|
489
|
+
if (!options.checkOrientation || !ArrayBuffer) {
|
490
|
+
return this.clone();
|
491
|
+
}
|
48
492
|
|
49
|
-
|
493
|
+
read = $.proxy(this.read, this);
|
50
494
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
Cropper.fn.size($clone, {
|
58
|
-
height: "auto",
|
59
|
-
width: "auto"
|
60
|
-
});
|
61
|
-
|
62
|
-
image = Cropper.fn.size($clone);
|
63
|
-
image = {
|
64
|
-
naturalHeight: image.height,
|
65
|
-
naturalWidth: image.width
|
66
|
-
};
|
67
|
-
}
|
495
|
+
// XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari
|
496
|
+
if (REGEXP_DATA_URL.test(url)) {
|
497
|
+
return REGEXP_DATA_URL_JPEG.test(url) ?
|
498
|
+
read(dataURLToArrayBuffer(url)) :
|
499
|
+
this.clone();
|
500
|
+
}
|
68
501
|
|
69
|
-
|
70
|
-
height: "100%",
|
71
|
-
width: "100%"
|
72
|
-
});
|
502
|
+
xhr = new XMLHttpRequest();
|
73
503
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
that.active = true;
|
78
|
-
that.createCropper();
|
79
|
-
});
|
504
|
+
xhr.onerror = xhr.onabort = $.proxy(function () {
|
505
|
+
this.clone();
|
506
|
+
}, this);
|
80
507
|
|
81
|
-
|
82
|
-
|
508
|
+
xhr.onload = function () {
|
509
|
+
read(this.response);
|
510
|
+
};
|
511
|
+
|
512
|
+
xhr.open('get', url);
|
513
|
+
xhr.responseType = 'arraybuffer';
|
514
|
+
xhr.send();
|
515
|
+
},
|
516
|
+
|
517
|
+
read: function (arrayBuffer) {
|
518
|
+
var options = this.options;
|
519
|
+
var orientation = getOrientation(arrayBuffer);
|
520
|
+
var image = this.image;
|
521
|
+
var rotate;
|
522
|
+
var scaleX;
|
523
|
+
var scaleY;
|
524
|
+
|
525
|
+
if (orientation > 1) {
|
526
|
+
this.url = arrayBufferToDataURL(arrayBuffer);
|
527
|
+
|
528
|
+
switch (orientation) {
|
529
|
+
|
530
|
+
// flip horizontal
|
531
|
+
case 2:
|
532
|
+
scaleX = -1;
|
533
|
+
break;
|
534
|
+
|
535
|
+
// rotate left 180°
|
536
|
+
case 3:
|
537
|
+
rotate = -180;
|
538
|
+
break;
|
539
|
+
|
540
|
+
// flip vertical
|
541
|
+
case 4:
|
542
|
+
scaleY = -1;
|
543
|
+
break;
|
544
|
+
|
545
|
+
// flip vertical + rotate right 90°
|
546
|
+
case 5:
|
547
|
+
rotate = 90;
|
548
|
+
scaleY = -1;
|
549
|
+
break;
|
550
|
+
|
551
|
+
// rotate right 90°
|
552
|
+
case 6:
|
553
|
+
rotate = 90;
|
554
|
+
break;
|
555
|
+
|
556
|
+
// flip horizontal + rotate right 90°
|
557
|
+
case 7:
|
558
|
+
rotate = 90;
|
559
|
+
scaleX = -1;
|
560
|
+
break;
|
561
|
+
|
562
|
+
// rotate left 90°
|
563
|
+
case 8:
|
564
|
+
rotate = -90;
|
565
|
+
break;
|
566
|
+
}
|
83
567
|
}
|
84
568
|
|
85
|
-
|
86
|
-
|
569
|
+
if (options.rotatable) {
|
570
|
+
image.rotate = rotate;
|
571
|
+
}
|
572
|
+
|
573
|
+
if (options.scalable) {
|
574
|
+
image.scaleX = scaleX;
|
575
|
+
image.scaleY = scaleY;
|
576
|
+
}
|
577
|
+
|
578
|
+
this.clone();
|
87
579
|
},
|
88
580
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
581
|
+
clone: function () {
|
582
|
+
var options = this.options;
|
583
|
+
var $this = this.$element;
|
584
|
+
var url = this.url;
|
585
|
+
var crossOrigin = '';
|
586
|
+
var crossOriginUrl;
|
587
|
+
var $clone;
|
588
|
+
|
589
|
+
if (options.checkCrossOrigin && isCrossOriginURL(url)) {
|
590
|
+
crossOrigin = $this.prop('crossOrigin');
|
591
|
+
|
592
|
+
if (crossOrigin) {
|
593
|
+
crossOriginUrl = url;
|
594
|
+
} else {
|
595
|
+
crossOrigin = 'anonymous';
|
596
|
+
|
597
|
+
// Bust cache (#148) when there is not a "crossOrigin" property
|
598
|
+
crossOriginUrl = addTimestamp(url);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
this.crossOrigin = crossOrigin;
|
603
|
+
this.crossOriginUrl = crossOriginUrl;
|
604
|
+
this.$clone = $clone = $('<img' + getCrossOrigin(crossOrigin) + ' src="' + (crossOriginUrl || url) + '">');
|
605
|
+
|
606
|
+
if (this.isImg) {
|
607
|
+
if ($this[0].complete) {
|
608
|
+
this.start();
|
609
|
+
} else {
|
610
|
+
$this.one(EVENT_LOAD, $.proxy(this.start, this));
|
611
|
+
}
|
612
|
+
} else {
|
613
|
+
$clone.
|
614
|
+
one(EVENT_LOAD, $.proxy(this.start, this)).
|
615
|
+
one(EVENT_ERROR, $.proxy(this.stop, this)).
|
616
|
+
addClass(CLASS_HIDE).
|
617
|
+
insertAfter($this);
|
97
618
|
}
|
98
619
|
},
|
99
620
|
|
100
|
-
|
101
|
-
this
|
102
|
-
this
|
621
|
+
start: function () {
|
622
|
+
var $image = this.$element;
|
623
|
+
var $clone = this.$clone;
|
624
|
+
|
625
|
+
if (!this.isImg) {
|
626
|
+
$clone.off(EVENT_ERROR, this.stop);
|
627
|
+
$image = $clone;
|
628
|
+
}
|
629
|
+
|
630
|
+
getImageSize($image[0], $.proxy(function (naturalWidth, naturalHeight) {
|
631
|
+
$.extend(this.image, {
|
632
|
+
naturalWidth: naturalWidth,
|
633
|
+
naturalHeight: naturalHeight,
|
634
|
+
aspectRatio: naturalWidth / naturalHeight
|
635
|
+
});
|
636
|
+
|
637
|
+
this.isLoaded = true;
|
638
|
+
this.build();
|
639
|
+
}, this));
|
103
640
|
},
|
104
641
|
|
105
|
-
|
106
|
-
|
107
|
-
this
|
642
|
+
stop: function () {
|
643
|
+
this.$clone.remove();
|
644
|
+
this.$clone = null;
|
108
645
|
},
|
109
646
|
|
110
|
-
|
111
|
-
|
112
|
-
this
|
113
|
-
|
114
|
-
|
115
|
-
|
647
|
+
build: function () {
|
648
|
+
var options = this.options;
|
649
|
+
var $this = this.$element;
|
650
|
+
var $clone = this.$clone;
|
651
|
+
var $cropper;
|
652
|
+
var $cropBox;
|
653
|
+
var $face;
|
654
|
+
|
655
|
+
if (!this.isLoaded) {
|
656
|
+
return;
|
657
|
+
}
|
658
|
+
|
659
|
+
// Unbuild first when replace
|
660
|
+
if (this.isBuilt) {
|
661
|
+
this.unbuild();
|
662
|
+
}
|
663
|
+
|
664
|
+
// Create cropper elements
|
665
|
+
this.$container = $this.parent();
|
666
|
+
this.$cropper = $cropper = $(Cropper.TEMPLATE);
|
667
|
+
this.$canvas = $cropper.find('.cropper-canvas').append($clone);
|
668
|
+
this.$dragBox = $cropper.find('.cropper-drag-box');
|
669
|
+
this.$cropBox = $cropBox = $cropper.find('.cropper-crop-box');
|
670
|
+
this.$viewBox = $cropper.find('.cropper-view-box');
|
671
|
+
this.$face = $face = $cropBox.find('.cropper-face');
|
672
|
+
|
673
|
+
// Hide the original image
|
674
|
+
$this.addClass(CLASS_HIDDEN).after($cropper);
|
675
|
+
|
676
|
+
// Show the clone image if is hidden
|
677
|
+
if (!this.isImg) {
|
678
|
+
$clone.removeClass(CLASS_HIDE);
|
679
|
+
}
|
680
|
+
|
681
|
+
this.initPreview();
|
682
|
+
this.bind();
|
683
|
+
|
684
|
+
options.aspectRatio = max(0, options.aspectRatio) || NaN;
|
685
|
+
options.viewMode = max(0, min(3, round(options.viewMode))) || 0;
|
686
|
+
|
687
|
+
if (options.autoCrop) {
|
688
|
+
this.isCropped = true;
|
689
|
+
|
690
|
+
if (options.modal) {
|
691
|
+
this.$dragBox.addClass(CLASS_MODAL);
|
692
|
+
}
|
693
|
+
} else {
|
694
|
+
$cropBox.addClass(CLASS_HIDDEN);
|
695
|
+
}
|
696
|
+
|
697
|
+
if (!options.guides) {
|
698
|
+
$cropBox.find('.cropper-dashed').addClass(CLASS_HIDDEN);
|
699
|
+
}
|
116
700
|
|
117
|
-
if (!
|
118
|
-
|
701
|
+
if (!options.center) {
|
702
|
+
$cropBox.find('.cropper-center').addClass(CLASS_HIDDEN);
|
119
703
|
}
|
120
704
|
|
121
|
-
|
122
|
-
|
705
|
+
if (options.cropBoxMovable) {
|
706
|
+
$face.addClass(CLASS_MOVE).data(DATA_ACTION, ACTION_ALL);
|
707
|
+
}
|
708
|
+
|
709
|
+
if (!options.highlight) {
|
710
|
+
$face.addClass(CLASS_INVISIBLE);
|
711
|
+
}
|
712
|
+
|
713
|
+
if (options.background) {
|
714
|
+
$cropper.addClass(CLASS_BG);
|
715
|
+
}
|
716
|
+
|
717
|
+
if (!options.cropBoxResizable) {
|
718
|
+
$cropBox.find('.cropper-line, .cropper-point').addClass(CLASS_HIDDEN);
|
719
|
+
}
|
720
|
+
|
721
|
+
this.setDragMode(options.dragMode);
|
722
|
+
this.render();
|
723
|
+
this.isBuilt = true;
|
724
|
+
this.setData(options.data);
|
725
|
+
$this.one(EVENT_BUILT, options.built);
|
726
|
+
|
727
|
+
// Trigger the built event asynchronously to keep `data('cropper')` is defined
|
728
|
+
setTimeout($.proxy(function () {
|
729
|
+
this.trigger(EVENT_BUILT);
|
730
|
+
this.isCompleted = true;
|
731
|
+
}, this), 0);
|
123
732
|
},
|
124
733
|
|
125
|
-
|
126
|
-
this.
|
734
|
+
unbuild: function () {
|
735
|
+
if (!this.isBuilt) {
|
736
|
+
return;
|
737
|
+
}
|
738
|
+
|
739
|
+
this.isBuilt = false;
|
740
|
+
this.isCompleted = false;
|
741
|
+
this.initialImage = null;
|
742
|
+
|
743
|
+
// Clear `initialCanvas` is necessary when replace
|
744
|
+
this.initialCanvas = null;
|
745
|
+
this.initialCropBox = null;
|
746
|
+
this.container = null;
|
747
|
+
this.canvas = null;
|
748
|
+
|
749
|
+
// Clear `cropBox` is necessary when replace
|
750
|
+
this.cropBox = null;
|
751
|
+
this.unbind();
|
752
|
+
|
753
|
+
this.resetPreview();
|
127
754
|
this.$preview = null;
|
128
|
-
|
129
|
-
this.$
|
130
|
-
this.$
|
755
|
+
|
756
|
+
this.$viewBox = null;
|
757
|
+
this.$cropBox = null;
|
758
|
+
this.$dragBox = null;
|
759
|
+
this.$canvas = null;
|
760
|
+
this.$container = null;
|
761
|
+
|
131
762
|
this.$cropper.remove();
|
132
763
|
this.$cropper = null;
|
133
|
-
Cropper.fn.toggle(this.$image);
|
134
764
|
},
|
135
765
|
|
136
|
-
|
137
|
-
this
|
138
|
-
this
|
139
|
-
this
|
140
|
-
|
766
|
+
render: function () {
|
767
|
+
this.initContainer();
|
768
|
+
this.initCanvas();
|
769
|
+
this.initCropBox();
|
770
|
+
|
771
|
+
this.renderCanvas();
|
772
|
+
|
773
|
+
if (this.isCropped) {
|
774
|
+
this.renderCropBox();
|
775
|
+
}
|
776
|
+
},
|
777
|
+
|
778
|
+
initContainer: function () {
|
779
|
+
var options = this.options;
|
780
|
+
var $this = this.$element;
|
781
|
+
var $container = this.$container;
|
782
|
+
var $cropper = this.$cropper;
|
783
|
+
|
784
|
+
$cropper.addClass(CLASS_HIDDEN);
|
785
|
+
$this.removeClass(CLASS_HIDDEN);
|
786
|
+
|
787
|
+
$cropper.css((this.container = {
|
788
|
+
width: max($container.width(), num(options.minContainerWidth) || 200),
|
789
|
+
height: max($container.height(), num(options.minContainerHeight) || 100)
|
790
|
+
}));
|
791
|
+
|
792
|
+
$this.addClass(CLASS_HIDDEN);
|
793
|
+
$cropper.removeClass(CLASS_HIDDEN);
|
794
|
+
},
|
795
|
+
|
796
|
+
// Canvas (image wrapper)
|
797
|
+
initCanvas: function () {
|
798
|
+
var viewMode = this.options.viewMode;
|
799
|
+
var container = this.container;
|
800
|
+
var containerWidth = container.width;
|
801
|
+
var containerHeight = container.height;
|
802
|
+
var image = this.image;
|
803
|
+
var imageNaturalWidth = image.naturalWidth;
|
804
|
+
var imageNaturalHeight = image.naturalHeight;
|
805
|
+
var is90Degree = abs(image.rotate) === 90;
|
806
|
+
var naturalWidth = is90Degree ? imageNaturalHeight : imageNaturalWidth;
|
807
|
+
var naturalHeight = is90Degree ? imageNaturalWidth : imageNaturalHeight;
|
808
|
+
var aspectRatio = naturalWidth / naturalHeight;
|
809
|
+
var canvasWidth = containerWidth;
|
810
|
+
var canvasHeight = containerHeight;
|
811
|
+
var canvas;
|
812
|
+
|
813
|
+
if (containerHeight * aspectRatio > containerWidth) {
|
814
|
+
if (viewMode === 3) {
|
815
|
+
canvasWidth = containerHeight * aspectRatio;
|
816
|
+
} else {
|
817
|
+
canvasHeight = containerWidth / aspectRatio;
|
818
|
+
}
|
819
|
+
} else {
|
820
|
+
if (viewMode === 3) {
|
821
|
+
canvasHeight = containerWidth / aspectRatio;
|
822
|
+
} else {
|
823
|
+
canvasWidth = containerHeight * aspectRatio;
|
824
|
+
}
|
825
|
+
}
|
826
|
+
|
827
|
+
canvas = {
|
828
|
+
naturalWidth: naturalWidth,
|
829
|
+
naturalHeight: naturalHeight,
|
830
|
+
aspectRatio: aspectRatio,
|
831
|
+
width: canvasWidth,
|
832
|
+
height: canvasHeight
|
833
|
+
};
|
834
|
+
|
835
|
+
canvas.oldLeft = canvas.left = (containerWidth - canvasWidth) / 2;
|
836
|
+
canvas.oldTop = canvas.top = (containerHeight - canvasHeight) / 2;
|
837
|
+
|
838
|
+
this.canvas = canvas;
|
839
|
+
this.isLimited = (viewMode === 1 || viewMode === 2);
|
840
|
+
this.limitCanvas(true, true);
|
841
|
+
this.initialImage = $.extend({}, image);
|
842
|
+
this.initialCanvas = $.extend({}, canvas);
|
843
|
+
},
|
844
|
+
|
845
|
+
limitCanvas: function (isSizeLimited, isPositionLimited) {
|
846
|
+
var options = this.options;
|
847
|
+
var viewMode = options.viewMode;
|
848
|
+
var container = this.container;
|
849
|
+
var containerWidth = container.width;
|
850
|
+
var containerHeight = container.height;
|
851
|
+
var canvas = this.canvas;
|
852
|
+
var aspectRatio = canvas.aspectRatio;
|
853
|
+
var cropBox = this.cropBox;
|
854
|
+
var isCropped = this.isCropped && cropBox;
|
855
|
+
var minCanvasWidth;
|
856
|
+
var minCanvasHeight;
|
857
|
+
var newCanvasLeft;
|
858
|
+
var newCanvasTop;
|
859
|
+
|
860
|
+
if (isSizeLimited) {
|
861
|
+
minCanvasWidth = num(options.minCanvasWidth) || 0;
|
862
|
+
minCanvasHeight = num(options.minCanvasHeight) || 0;
|
863
|
+
|
864
|
+
if (viewMode) {
|
865
|
+
if (viewMode > 1) {
|
866
|
+
minCanvasWidth = max(minCanvasWidth, containerWidth);
|
867
|
+
minCanvasHeight = max(minCanvasHeight, containerHeight);
|
868
|
+
|
869
|
+
if (viewMode === 3) {
|
870
|
+
if (minCanvasHeight * aspectRatio > minCanvasWidth) {
|
871
|
+
minCanvasWidth = minCanvasHeight * aspectRatio;
|
872
|
+
} else {
|
873
|
+
minCanvasHeight = minCanvasWidth / aspectRatio;
|
874
|
+
}
|
875
|
+
}
|
876
|
+
} else {
|
877
|
+
if (minCanvasWidth) {
|
878
|
+
minCanvasWidth = max(minCanvasWidth, isCropped ? cropBox.width : 0);
|
879
|
+
} else if (minCanvasHeight) {
|
880
|
+
minCanvasHeight = max(minCanvasHeight, isCropped ? cropBox.height : 0);
|
881
|
+
} else if (isCropped) {
|
882
|
+
minCanvasWidth = cropBox.width;
|
883
|
+
minCanvasHeight = cropBox.height;
|
884
|
+
|
885
|
+
if (minCanvasHeight * aspectRatio > minCanvasWidth) {
|
886
|
+
minCanvasWidth = minCanvasHeight * aspectRatio;
|
887
|
+
} else {
|
888
|
+
minCanvasHeight = minCanvasWidth / aspectRatio;
|
889
|
+
}
|
890
|
+
}
|
891
|
+
}
|
892
|
+
}
|
893
|
+
|
894
|
+
if (minCanvasWidth && minCanvasHeight) {
|
895
|
+
if (minCanvasHeight * aspectRatio > minCanvasWidth) {
|
896
|
+
minCanvasHeight = minCanvasWidth / aspectRatio;
|
897
|
+
} else {
|
898
|
+
minCanvasWidth = minCanvasHeight * aspectRatio;
|
899
|
+
}
|
900
|
+
} else if (minCanvasWidth) {
|
901
|
+
minCanvasHeight = minCanvasWidth / aspectRatio;
|
902
|
+
} else if (minCanvasHeight) {
|
903
|
+
minCanvasWidth = minCanvasHeight * aspectRatio;
|
904
|
+
}
|
905
|
+
|
906
|
+
canvas.minWidth = minCanvasWidth;
|
907
|
+
canvas.minHeight = minCanvasHeight;
|
908
|
+
canvas.maxWidth = Infinity;
|
909
|
+
canvas.maxHeight = Infinity;
|
910
|
+
}
|
911
|
+
|
912
|
+
if (isPositionLimited) {
|
913
|
+
if (viewMode) {
|
914
|
+
newCanvasLeft = containerWidth - canvas.width;
|
915
|
+
newCanvasTop = containerHeight - canvas.height;
|
916
|
+
|
917
|
+
canvas.minLeft = min(0, newCanvasLeft);
|
918
|
+
canvas.minTop = min(0, newCanvasTop);
|
919
|
+
canvas.maxLeft = max(0, newCanvasLeft);
|
920
|
+
canvas.maxTop = max(0, newCanvasTop);
|
921
|
+
|
922
|
+
if (isCropped && this.isLimited) {
|
923
|
+
canvas.minLeft = min(
|
924
|
+
cropBox.left,
|
925
|
+
cropBox.left + cropBox.width - canvas.width
|
926
|
+
);
|
927
|
+
canvas.minTop = min(
|
928
|
+
cropBox.top,
|
929
|
+
cropBox.top + cropBox.height - canvas.height
|
930
|
+
);
|
931
|
+
canvas.maxLeft = cropBox.left;
|
932
|
+
canvas.maxTop = cropBox.top;
|
933
|
+
|
934
|
+
if (viewMode === 2) {
|
935
|
+
if (canvas.width >= containerWidth) {
|
936
|
+
canvas.minLeft = min(0, newCanvasLeft);
|
937
|
+
canvas.maxLeft = max(0, newCanvasLeft);
|
938
|
+
}
|
939
|
+
|
940
|
+
if (canvas.height >= containerHeight) {
|
941
|
+
canvas.minTop = min(0, newCanvasTop);
|
942
|
+
canvas.maxTop = max(0, newCanvasTop);
|
943
|
+
}
|
944
|
+
}
|
945
|
+
}
|
946
|
+
} else {
|
947
|
+
canvas.minLeft = -canvas.width;
|
948
|
+
canvas.minTop = -canvas.height;
|
949
|
+
canvas.maxLeft = containerWidth;
|
950
|
+
canvas.maxTop = containerHeight;
|
951
|
+
}
|
952
|
+
}
|
953
|
+
},
|
954
|
+
|
955
|
+
renderCanvas: function (isChanged) {
|
956
|
+
var canvas = this.canvas;
|
957
|
+
var image = this.image;
|
958
|
+
var rotate = image.rotate;
|
959
|
+
var naturalWidth = image.naturalWidth;
|
960
|
+
var naturalHeight = image.naturalHeight;
|
961
|
+
var aspectRatio;
|
962
|
+
var rotated;
|
963
|
+
|
964
|
+
if (this.isRotated) {
|
965
|
+
this.isRotated = false;
|
966
|
+
|
967
|
+
// Computes rotated sizes with image sizes
|
968
|
+
rotated = getRotatedSizes({
|
969
|
+
width: image.width,
|
970
|
+
height: image.height,
|
971
|
+
degree: rotate
|
972
|
+
});
|
973
|
+
|
974
|
+
aspectRatio = rotated.width / rotated.height;
|
975
|
+
|
976
|
+
if (aspectRatio !== canvas.aspectRatio) {
|
977
|
+
canvas.left -= (rotated.width - canvas.width) / 2;
|
978
|
+
canvas.top -= (rotated.height - canvas.height) / 2;
|
979
|
+
canvas.width = rotated.width;
|
980
|
+
canvas.height = rotated.height;
|
981
|
+
canvas.aspectRatio = aspectRatio;
|
982
|
+
canvas.naturalWidth = naturalWidth;
|
983
|
+
canvas.naturalHeight = naturalHeight;
|
984
|
+
|
985
|
+
// Computes rotated sizes with natural image sizes
|
986
|
+
if (rotate % 180) {
|
987
|
+
rotated = getRotatedSizes({
|
988
|
+
width: naturalWidth,
|
989
|
+
height: naturalHeight,
|
990
|
+
degree: rotate
|
991
|
+
});
|
992
|
+
|
993
|
+
canvas.naturalWidth = rotated.width;
|
994
|
+
canvas.naturalHeight = rotated.height;
|
995
|
+
}
|
996
|
+
|
997
|
+
this.limitCanvas(true, false);
|
998
|
+
}
|
999
|
+
}
|
1000
|
+
|
1001
|
+
if (canvas.width > canvas.maxWidth || canvas.width < canvas.minWidth) {
|
1002
|
+
canvas.left = canvas.oldLeft;
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
if (canvas.height > canvas.maxHeight || canvas.height < canvas.minHeight) {
|
1006
|
+
canvas.top = canvas.oldTop;
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
canvas.width = min(max(canvas.width, canvas.minWidth), canvas.maxWidth);
|
1010
|
+
canvas.height = min(max(canvas.height, canvas.minHeight), canvas.maxHeight);
|
1011
|
+
|
1012
|
+
this.limitCanvas(false, true);
|
1013
|
+
|
1014
|
+
canvas.oldLeft = canvas.left = min(max(canvas.left, canvas.minLeft), canvas.maxLeft);
|
1015
|
+
canvas.oldTop = canvas.top = min(max(canvas.top, canvas.minTop), canvas.maxTop);
|
1016
|
+
|
1017
|
+
this.$canvas.css({
|
1018
|
+
width: canvas.width,
|
1019
|
+
height: canvas.height,
|
1020
|
+
left: canvas.left,
|
1021
|
+
top: canvas.top
|
1022
|
+
});
|
1023
|
+
|
1024
|
+
this.renderImage();
|
1025
|
+
|
1026
|
+
if (this.isCropped && this.isLimited) {
|
1027
|
+
this.limitCropBox(true, true);
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
if (isChanged) {
|
1031
|
+
this.output();
|
1032
|
+
}
|
1033
|
+
},
|
1034
|
+
|
1035
|
+
renderImage: function (isChanged) {
|
1036
|
+
var canvas = this.canvas;
|
1037
|
+
var image = this.image;
|
1038
|
+
var reversed;
|
1039
|
+
|
1040
|
+
if (image.rotate) {
|
1041
|
+
reversed = getRotatedSizes({
|
1042
|
+
width: canvas.width,
|
1043
|
+
height: canvas.height,
|
1044
|
+
degree: image.rotate,
|
1045
|
+
aspectRatio: image.aspectRatio
|
1046
|
+
}, true);
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
$.extend(image, reversed ? {
|
1050
|
+
width: reversed.width,
|
1051
|
+
height: reversed.height,
|
1052
|
+
left: (canvas.width - reversed.width) / 2,
|
1053
|
+
top: (canvas.height - reversed.height) / 2
|
1054
|
+
} : {
|
1055
|
+
width: canvas.width,
|
1056
|
+
height: canvas.height,
|
1057
|
+
left: 0,
|
1058
|
+
top: 0
|
1059
|
+
});
|
1060
|
+
|
1061
|
+
this.$clone.css({
|
1062
|
+
width: image.width,
|
1063
|
+
height: image.height,
|
1064
|
+
marginLeft: image.left,
|
1065
|
+
marginTop: image.top,
|
1066
|
+
transform: getTransform(image)
|
1067
|
+
});
|
1068
|
+
|
1069
|
+
if (isChanged) {
|
1070
|
+
this.output();
|
1071
|
+
}
|
141
1072
|
},
|
142
1073
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
1074
|
+
initCropBox: function () {
|
1075
|
+
var options = this.options;
|
1076
|
+
var canvas = this.canvas;
|
1077
|
+
var aspectRatio = options.aspectRatio;
|
1078
|
+
var autoCropArea = num(options.autoCropArea) || 0.8;
|
1079
|
+
var cropBox = {
|
1080
|
+
width: canvas.width,
|
1081
|
+
height: canvas.height
|
1082
|
+
};
|
1083
|
+
|
1084
|
+
if (aspectRatio) {
|
1085
|
+
if (canvas.height * aspectRatio > canvas.width) {
|
1086
|
+
cropBox.height = cropBox.width / aspectRatio;
|
1087
|
+
} else {
|
1088
|
+
cropBox.width = cropBox.height * aspectRatio;
|
1089
|
+
}
|
1090
|
+
}
|
1091
|
+
|
1092
|
+
this.cropBox = cropBox;
|
1093
|
+
this.limitCropBox(true, true);
|
1094
|
+
|
1095
|
+
// Initialize auto crop area
|
1096
|
+
cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);
|
1097
|
+
cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);
|
1098
|
+
|
1099
|
+
// The width of auto crop area must large than "minWidth", and the height too. (#164)
|
1100
|
+
cropBox.width = max(cropBox.minWidth, cropBox.width * autoCropArea);
|
1101
|
+
cropBox.height = max(cropBox.minHeight, cropBox.height * autoCropArea);
|
1102
|
+
cropBox.oldLeft = cropBox.left = canvas.left + (canvas.width - cropBox.width) / 2;
|
1103
|
+
cropBox.oldTop = cropBox.top = canvas.top + (canvas.height - cropBox.height) / 2;
|
1104
|
+
|
1105
|
+
this.initialCropBox = $.extend({}, cropBox);
|
148
1106
|
},
|
149
1107
|
|
150
|
-
|
151
|
-
var
|
1108
|
+
limitCropBox: function (isSizeLimited, isPositionLimited) {
|
1109
|
+
var options = this.options;
|
1110
|
+
var aspectRatio = options.aspectRatio;
|
1111
|
+
var container = this.container;
|
1112
|
+
var containerWidth = container.width;
|
1113
|
+
var containerHeight = container.height;
|
1114
|
+
var canvas = this.canvas;
|
1115
|
+
var cropBox = this.cropBox;
|
1116
|
+
var isLimited = this.isLimited;
|
1117
|
+
var minCropBoxWidth;
|
1118
|
+
var minCropBoxHeight;
|
1119
|
+
var maxCropBoxWidth;
|
1120
|
+
var maxCropBoxHeight;
|
1121
|
+
|
1122
|
+
if (isSizeLimited) {
|
1123
|
+
minCropBoxWidth = num(options.minCropBoxWidth) || 0;
|
1124
|
+
minCropBoxHeight = num(options.minCropBoxHeight) || 0;
|
1125
|
+
|
1126
|
+
// The min/maxCropBoxWidth/Height must be less than containerWidth/Height
|
1127
|
+
minCropBoxWidth = min(minCropBoxWidth, containerWidth);
|
1128
|
+
minCropBoxHeight = min(minCropBoxHeight, containerHeight);
|
1129
|
+
maxCropBoxWidth = min(containerWidth, isLimited ? canvas.width : containerWidth);
|
1130
|
+
maxCropBoxHeight = min(containerHeight, isLimited ? canvas.height : containerHeight);
|
1131
|
+
|
1132
|
+
if (aspectRatio) {
|
1133
|
+
if (minCropBoxWidth && minCropBoxHeight) {
|
1134
|
+
if (minCropBoxHeight * aspectRatio > minCropBoxWidth) {
|
1135
|
+
minCropBoxHeight = minCropBoxWidth / aspectRatio;
|
1136
|
+
} else {
|
1137
|
+
minCropBoxWidth = minCropBoxHeight * aspectRatio;
|
1138
|
+
}
|
1139
|
+
} else if (minCropBoxWidth) {
|
1140
|
+
minCropBoxHeight = minCropBoxWidth / aspectRatio;
|
1141
|
+
} else if (minCropBoxHeight) {
|
1142
|
+
minCropBoxWidth = minCropBoxHeight * aspectRatio;
|
1143
|
+
}
|
152
1144
|
|
153
|
-
|
1145
|
+
if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) {
|
1146
|
+
maxCropBoxHeight = maxCropBoxWidth / aspectRatio;
|
1147
|
+
} else {
|
1148
|
+
maxCropBoxWidth = maxCropBoxHeight * aspectRatio;
|
1149
|
+
}
|
1150
|
+
}
|
154
1151
|
|
155
|
-
|
156
|
-
|
1152
|
+
// The minWidth/Height must be less than maxWidth/Height
|
1153
|
+
cropBox.minWidth = min(minCropBoxWidth, maxCropBoxWidth);
|
1154
|
+
cropBox.minHeight = min(minCropBoxHeight, maxCropBoxHeight);
|
1155
|
+
cropBox.maxWidth = maxCropBoxWidth;
|
1156
|
+
cropBox.maxHeight = maxCropBoxHeight;
|
157
1157
|
}
|
158
1158
|
|
159
|
-
|
160
|
-
|
1159
|
+
if (isPositionLimited) {
|
1160
|
+
if (isLimited) {
|
1161
|
+
cropBox.minLeft = max(0, canvas.left);
|
1162
|
+
cropBox.minTop = max(0, canvas.top);
|
1163
|
+
cropBox.maxLeft = min(containerWidth, canvas.left + canvas.width) - cropBox.width;
|
1164
|
+
cropBox.maxTop = min(containerHeight, canvas.top + canvas.height) - cropBox.height;
|
1165
|
+
} else {
|
1166
|
+
cropBox.minLeft = 0;
|
1167
|
+
cropBox.minTop = 0;
|
1168
|
+
cropBox.maxLeft = containerWidth - cropBox.width;
|
1169
|
+
cropBox.maxTop = containerHeight - cropBox.height;
|
1170
|
+
}
|
1171
|
+
}
|
161
1172
|
},
|
162
1173
|
|
163
|
-
|
164
|
-
var
|
165
|
-
|
166
|
-
|
167
|
-
|
1174
|
+
renderCropBox: function () {
|
1175
|
+
var options = this.options;
|
1176
|
+
var container = this.container;
|
1177
|
+
var containerWidth = container.width;
|
1178
|
+
var containerHeight = container.height;
|
1179
|
+
var cropBox = this.cropBox;
|
168
1180
|
|
169
|
-
if (
|
170
|
-
|
171
|
-
|
172
|
-
width: container.width,
|
173
|
-
left: 0
|
174
|
-
};
|
1181
|
+
if (cropBox.width > cropBox.maxWidth || cropBox.width < cropBox.minWidth) {
|
1182
|
+
cropBox.left = cropBox.oldLeft;
|
1183
|
+
}
|
175
1184
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
1185
|
+
if (cropBox.height > cropBox.maxHeight || cropBox.height < cropBox.minHeight) {
|
1186
|
+
cropBox.top = cropBox.oldTop;
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);
|
1190
|
+
cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);
|
1191
|
+
|
1192
|
+
this.limitCropBox(false, true);
|
1193
|
+
|
1194
|
+
cropBox.oldLeft = cropBox.left = min(max(cropBox.left, cropBox.minLeft), cropBox.maxLeft);
|
1195
|
+
cropBox.oldTop = cropBox.top = min(max(cropBox.top, cropBox.minTop), cropBox.maxTop);
|
1196
|
+
|
1197
|
+
if (options.movable && options.cropBoxMovable) {
|
1198
|
+
|
1199
|
+
// Turn to move the canvas when the crop box is equal to the container
|
1200
|
+
this.$face.data(DATA_ACTION, (cropBox.width === containerWidth && cropBox.height === containerHeight) ? ACTION_MOVE : ACTION_ALL);
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
this.$cropBox.css({
|
1204
|
+
width: cropBox.width,
|
1205
|
+
height: cropBox.height,
|
1206
|
+
left: cropBox.left,
|
1207
|
+
top: cropBox.top
|
1208
|
+
});
|
1209
|
+
|
1210
|
+
if (this.isCropped && this.isLimited) {
|
1211
|
+
this.limitCanvas(true, true);
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
if (!this.isDisabled) {
|
1215
|
+
this.output();
|
1216
|
+
}
|
1217
|
+
},
|
1218
|
+
|
1219
|
+
output: function () {
|
1220
|
+
this.preview();
|
1221
|
+
|
1222
|
+
if (this.isCompleted) {
|
1223
|
+
this.trigger(EVENT_CROP, this.getData());
|
1224
|
+
} else if (!this.isBuilt) {
|
183
1225
|
|
184
|
-
|
1226
|
+
// Only trigger one crop event before complete
|
1227
|
+
this.$element.one(EVENT_BUILT, $.proxy(function () {
|
1228
|
+
this.trigger(EVENT_CROP, this.getData());
|
1229
|
+
}, this));
|
185
1230
|
}
|
1231
|
+
},
|
1232
|
+
|
1233
|
+
initPreview: function () {
|
1234
|
+
var crossOrigin = getCrossOrigin(this.crossOrigin);
|
1235
|
+
var url = crossOrigin ? this.crossOriginUrl : this.url;
|
1236
|
+
|
1237
|
+
this.$preview = $(this.options.preview);
|
1238
|
+
this.$viewBox.html('<img' + crossOrigin + ' src="' + url + '">');
|
1239
|
+
this.$preview.each(function () {
|
1240
|
+
var $this = $(this);
|
1241
|
+
|
1242
|
+
// Save the original size for recover
|
1243
|
+
$this.data(DATA_PREVIEW, {
|
1244
|
+
width: $this.width(),
|
1245
|
+
height: $this.height(),
|
1246
|
+
html: $this.html()
|
1247
|
+
});
|
1248
|
+
|
1249
|
+
/**
|
1250
|
+
* Override img element styles
|
1251
|
+
* Add `display:block` to avoid margin top issue
|
1252
|
+
* (Occur only when margin-top <= -height)
|
1253
|
+
*/
|
1254
|
+
$this.html(
|
1255
|
+
'<img' + crossOrigin + ' src="' + url + '" style="' +
|
1256
|
+
'display:block;width:100%;height:auto;' +
|
1257
|
+
'min-width:0!important;min-height:0!important;' +
|
1258
|
+
'max-width:none!important;max-height:none!important;' +
|
1259
|
+
'image-orientation:0deg!important;">'
|
1260
|
+
);
|
1261
|
+
});
|
1262
|
+
},
|
186
1263
|
|
187
|
-
|
188
|
-
|
1264
|
+
resetPreview: function () {
|
1265
|
+
this.$preview.each(function () {
|
1266
|
+
var $this = $(this);
|
1267
|
+
var data = $this.data(DATA_PREVIEW);
|
1268
|
+
|
1269
|
+
$this.css({
|
1270
|
+
width: data.width,
|
1271
|
+
height: data.height
|
1272
|
+
}).html(data.html).removeData(DATA_PREVIEW);
|
189
1273
|
});
|
1274
|
+
},
|
190
1275
|
|
191
|
-
|
192
|
-
image
|
193
|
-
|
1276
|
+
preview: function () {
|
1277
|
+
var image = this.image;
|
1278
|
+
var canvas = this.canvas;
|
1279
|
+
var cropBox = this.cropBox;
|
1280
|
+
var cropBoxWidth = cropBox.width;
|
1281
|
+
var cropBoxHeight = cropBox.height;
|
1282
|
+
var width = image.width;
|
1283
|
+
var height = image.height;
|
1284
|
+
var left = cropBox.left - canvas.left - image.left;
|
1285
|
+
var top = cropBox.top - canvas.top - image.top;
|
1286
|
+
|
1287
|
+
if (!this.isCropped || this.isDisabled) {
|
1288
|
+
return;
|
1289
|
+
}
|
194
1290
|
|
195
|
-
|
196
|
-
|
197
|
-
height:
|
198
|
-
|
199
|
-
|
200
|
-
|
1291
|
+
this.$viewBox.find('img').css({
|
1292
|
+
width: width,
|
1293
|
+
height: height,
|
1294
|
+
marginLeft: -left,
|
1295
|
+
marginTop: -top,
|
1296
|
+
transform: getTransform(image)
|
201
1297
|
});
|
202
1298
|
|
203
|
-
this.
|
204
|
-
|
1299
|
+
this.$preview.each(function () {
|
1300
|
+
var $this = $(this);
|
1301
|
+
var data = $this.data(DATA_PREVIEW);
|
1302
|
+
var originalWidth = data.width;
|
1303
|
+
var originalHeight = data.height;
|
1304
|
+
var newWidth = originalWidth;
|
1305
|
+
var newHeight = originalHeight;
|
1306
|
+
var ratio = 1;
|
1307
|
+
|
1308
|
+
if (cropBoxWidth) {
|
1309
|
+
ratio = originalWidth / cropBoxWidth;
|
1310
|
+
newHeight = cropBoxHeight * ratio;
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
if (cropBoxHeight && newHeight > originalHeight) {
|
1314
|
+
ratio = originalHeight / cropBoxHeight;
|
1315
|
+
newWidth = cropBoxWidth * ratio;
|
1316
|
+
newHeight = originalHeight;
|
1317
|
+
}
|
1318
|
+
|
1319
|
+
$this.css({
|
1320
|
+
width: newWidth,
|
1321
|
+
height: newHeight
|
1322
|
+
}).find('img').css({
|
1323
|
+
width: width * ratio,
|
1324
|
+
height: height * ratio,
|
1325
|
+
marginLeft: -left * ratio,
|
1326
|
+
marginTop: -top * ratio,
|
1327
|
+
transform: getTransform(image)
|
1328
|
+
});
|
1329
|
+
});
|
205
1330
|
},
|
206
1331
|
|
207
|
-
|
208
|
-
var
|
209
|
-
|
210
|
-
|
211
|
-
dragger;
|
1332
|
+
bind: function () {
|
1333
|
+
var options = this.options;
|
1334
|
+
var $this = this.$element;
|
1335
|
+
var $cropper = this.$cropper;
|
212
1336
|
|
213
|
-
if ((
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
1337
|
+
if ($.isFunction(options.cropstart)) {
|
1338
|
+
$this.on(EVENT_CROP_START, options.cropstart);
|
1339
|
+
}
|
1340
|
+
|
1341
|
+
if ($.isFunction(options.cropmove)) {
|
1342
|
+
$this.on(EVENT_CROP_MOVE, options.cropmove);
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
if ($.isFunction(options.cropend)) {
|
1346
|
+
$this.on(EVENT_CROP_END, options.cropend);
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
if ($.isFunction(options.crop)) {
|
1350
|
+
$this.on(EVENT_CROP, options.crop);
|
1351
|
+
}
|
1352
|
+
|
1353
|
+
if ($.isFunction(options.zoom)) {
|
1354
|
+
$this.on(EVENT_ZOOM, options.zoom);
|
1355
|
+
}
|
1356
|
+
|
1357
|
+
$cropper.on(EVENT_MOUSE_DOWN, $.proxy(this.cropStart, this));
|
1358
|
+
|
1359
|
+
if (options.zoomable && options.zoomOnWheel) {
|
1360
|
+
$cropper.on(EVENT_WHEEL, $.proxy(this.wheel, this));
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
if (options.toggleDragModeOnDblclick) {
|
1364
|
+
$cropper.on(EVENT_DBLCLICK, $.proxy(this.dblclick, this));
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
$document.
|
1368
|
+
on(EVENT_MOUSE_MOVE, (this._cropMove = proxy(this.cropMove, this))).
|
1369
|
+
on(EVENT_MOUSE_UP, (this._cropEnd = proxy(this.cropEnd, this)));
|
1370
|
+
|
1371
|
+
if (options.responsive) {
|
1372
|
+
$window.on(EVENT_RESIZE, (this._resize = proxy(this.resize, this)));
|
1373
|
+
}
|
1374
|
+
},
|
1375
|
+
|
1376
|
+
unbind: function () {
|
1377
|
+
var options = this.options;
|
1378
|
+
var $this = this.$element;
|
1379
|
+
var $cropper = this.$cropper;
|
1380
|
+
|
1381
|
+
if ($.isFunction(options.cropstart)) {
|
1382
|
+
$this.off(EVENT_CROP_START, options.cropstart);
|
1383
|
+
}
|
1384
|
+
|
1385
|
+
if ($.isFunction(options.cropmove)) {
|
1386
|
+
$this.off(EVENT_CROP_MOVE, options.cropmove);
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
if ($.isFunction(options.cropend)) {
|
1390
|
+
$this.off(EVENT_CROP_END, options.cropend);
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
if ($.isFunction(options.crop)) {
|
1394
|
+
$this.off(EVENT_CROP, options.crop);
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
if ($.isFunction(options.zoom)) {
|
1398
|
+
$this.off(EVENT_ZOOM, options.zoom);
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
$cropper.off(EVENT_MOUSE_DOWN, this.cropStart);
|
1402
|
+
|
1403
|
+
if (options.zoomable && options.zoomOnWheel) {
|
1404
|
+
$cropper.off(EVENT_WHEEL, this.wheel);
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
if (options.toggleDragModeOnDblclick) {
|
1408
|
+
$cropper.off(EVENT_DBLCLICK, this.dblclick);
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
$document.
|
1412
|
+
off(EVENT_MOUSE_MOVE, this._cropMove).
|
1413
|
+
off(EVENT_MOUSE_UP, this._cropEnd);
|
1414
|
+
|
1415
|
+
if (options.responsive) {
|
1416
|
+
$window.off(EVENT_RESIZE, this._resize);
|
1417
|
+
}
|
1418
|
+
},
|
1419
|
+
|
1420
|
+
resize: function () {
|
1421
|
+
var restore = this.options.restore;
|
1422
|
+
var $container = this.$container;
|
1423
|
+
var container = this.container;
|
1424
|
+
var canvasData;
|
1425
|
+
var cropBoxData;
|
1426
|
+
var ratio;
|
1427
|
+
|
1428
|
+
// Check `container` is necessary for IE8
|
1429
|
+
if (this.isDisabled || !container) {
|
1430
|
+
return;
|
1431
|
+
}
|
1432
|
+
|
1433
|
+
ratio = $container.width() / container.width;
|
1434
|
+
|
1435
|
+
// Resize when width changed or height changed
|
1436
|
+
if (ratio !== 1 || $container.height() !== container.height) {
|
1437
|
+
if (restore) {
|
1438
|
+
canvasData = this.getCanvasData();
|
1439
|
+
cropBoxData = this.getCropBoxData();
|
1440
|
+
}
|
1441
|
+
|
1442
|
+
this.render();
|
1443
|
+
|
1444
|
+
if (restore) {
|
1445
|
+
this.setCanvasData($.each(canvasData, function (i, n) {
|
1446
|
+
canvasData[i] = n * ratio;
|
1447
|
+
}));
|
1448
|
+
this.setCropBoxData($.each(cropBoxData, function (i, n) {
|
1449
|
+
cropBoxData[i] = n * ratio;
|
1450
|
+
}));
|
1451
|
+
}
|
1452
|
+
}
|
1453
|
+
},
|
1454
|
+
|
1455
|
+
dblclick: function () {
|
1456
|
+
if (this.isDisabled) {
|
1457
|
+
return;
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
if (this.$dragBox.hasClass(CLASS_CROP)) {
|
1461
|
+
this.setDragMode(ACTION_MOVE);
|
222
1462
|
} else {
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
1463
|
+
this.setDragMode(ACTION_CROP);
|
1464
|
+
}
|
1465
|
+
},
|
1466
|
+
|
1467
|
+
wheel: function (event) {
|
1468
|
+
var e = event.originalEvent || event;
|
1469
|
+
var ratio = num(this.options.wheelZoomRatio) || 0.1;
|
1470
|
+
var delta = 1;
|
1471
|
+
|
1472
|
+
if (this.isDisabled) {
|
1473
|
+
return;
|
1474
|
+
}
|
1475
|
+
|
1476
|
+
event.preventDefault();
|
1477
|
+
|
1478
|
+
// Limit wheel speed to prevent zoom too fast
|
1479
|
+
if (this.wheeling) {
|
1480
|
+
return;
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
this.wheeling = true;
|
1484
|
+
|
1485
|
+
setTimeout($.proxy(function () {
|
1486
|
+
this.wheeling = false;
|
1487
|
+
}, this), 50);
|
1488
|
+
|
1489
|
+
if (e.deltaY) {
|
1490
|
+
delta = e.deltaY > 0 ? 1 : -1;
|
1491
|
+
} else if (e.wheelDelta) {
|
1492
|
+
delta = -e.wheelDelta / 120;
|
1493
|
+
} else if (e.detail) {
|
1494
|
+
delta = e.detail > 0 ? 1 : -1;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
this.zoom(-delta * ratio, event);
|
1498
|
+
},
|
1499
|
+
|
1500
|
+
cropStart: function (event) {
|
1501
|
+
var options = this.options;
|
1502
|
+
var originalEvent = event.originalEvent;
|
1503
|
+
var touches = originalEvent && originalEvent.touches;
|
1504
|
+
var e = event;
|
1505
|
+
var touchesLength;
|
1506
|
+
var action;
|
1507
|
+
|
1508
|
+
if (this.isDisabled) {
|
1509
|
+
return;
|
1510
|
+
}
|
1511
|
+
|
1512
|
+
if (touches) {
|
1513
|
+
touchesLength = touches.length;
|
1514
|
+
|
1515
|
+
if (touchesLength > 1) {
|
1516
|
+
if (options.zoomable && options.zoomOnTouch && touchesLength === 2) {
|
1517
|
+
e = touches[1];
|
1518
|
+
this.startX2 = e.pageX;
|
1519
|
+
this.startY2 = e.pageY;
|
1520
|
+
action = ACTION_ZOOM;
|
1521
|
+
} else {
|
1522
|
+
return;
|
1523
|
+
}
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
e = touches[0];
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
action = action || $(e.target).data(DATA_ACTION);
|
1530
|
+
|
1531
|
+
if (REGEXP_ACTIONS.test(action)) {
|
1532
|
+
if (this.trigger(EVENT_CROP_START, {
|
1533
|
+
originalEvent: originalEvent,
|
1534
|
+
action: action
|
1535
|
+
}).isDefaultPrevented()) {
|
1536
|
+
return;
|
1537
|
+
}
|
1538
|
+
|
1539
|
+
event.preventDefault();
|
1540
|
+
|
1541
|
+
this.action = action;
|
1542
|
+
this.cropping = false;
|
1543
|
+
|
1544
|
+
// IE8 has `event.pageX/Y`, but not `event.originalEvent.pageX/Y`
|
1545
|
+
// IE10 has `event.originalEvent.pageX/Y`, but not `event.pageX/Y`
|
1546
|
+
this.startX = e.pageX || originalEvent && originalEvent.pageX;
|
1547
|
+
this.startY = e.pageY || originalEvent && originalEvent.pageY;
|
1548
|
+
|
1549
|
+
if (action === ACTION_CROP) {
|
1550
|
+
this.cropping = true;
|
1551
|
+
this.$dragBox.addClass(CLASS_MODAL);
|
1552
|
+
}
|
1553
|
+
}
|
1554
|
+
},
|
1555
|
+
|
1556
|
+
cropMove: function (event) {
|
1557
|
+
var options = this.options;
|
1558
|
+
var originalEvent = event.originalEvent;
|
1559
|
+
var touches = originalEvent && originalEvent.touches;
|
1560
|
+
var e = event;
|
1561
|
+
var action = this.action;
|
1562
|
+
var touchesLength;
|
1563
|
+
|
1564
|
+
if (this.isDisabled) {
|
1565
|
+
return;
|
1566
|
+
}
|
1567
|
+
|
1568
|
+
if (touches) {
|
1569
|
+
touchesLength = touches.length;
|
1570
|
+
|
1571
|
+
if (touchesLength > 1) {
|
1572
|
+
if (options.zoomable && options.zoomOnTouch && touchesLength === 2) {
|
1573
|
+
e = touches[1];
|
1574
|
+
this.endX2 = e.pageX;
|
1575
|
+
this.endY2 = e.pageY;
|
1576
|
+
} else {
|
1577
|
+
return;
|
1578
|
+
}
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
e = touches[0];
|
231
1582
|
}
|
232
1583
|
|
233
|
-
|
234
|
-
|
1584
|
+
if (action) {
|
1585
|
+
if (this.trigger(EVENT_CROP_MOVE, {
|
1586
|
+
originalEvent: originalEvent,
|
1587
|
+
action: action
|
1588
|
+
}).isDefaultPrevented()) {
|
1589
|
+
return;
|
1590
|
+
}
|
235
1591
|
|
236
|
-
|
237
|
-
dragger.top = (cropper.height - dragger.height) / 2;
|
1592
|
+
event.preventDefault();
|
238
1593
|
|
239
|
-
|
240
|
-
|
241
|
-
this.$image.trigger("ready.cropper").off("ready.cropper");
|
242
|
-
},
|
1594
|
+
this.endX = e.pageX || originalEvent && originalEvent.pageX;
|
1595
|
+
this.endY = e.pageY || originalEvent && originalEvent.pageY;
|
243
1596
|
|
244
|
-
|
245
|
-
|
246
|
-
|
1597
|
+
this.change(e.shiftKey, action === ACTION_ZOOM ? event : null);
|
1598
|
+
}
|
1599
|
+
},
|
247
1600
|
|
248
|
-
|
249
|
-
|
1601
|
+
cropEnd: function (event) {
|
1602
|
+
var originalEvent = event.originalEvent;
|
1603
|
+
var action = this.action;
|
250
1604
|
|
251
|
-
|
252
|
-
|
1605
|
+
if (this.isDisabled) {
|
1606
|
+
return;
|
1607
|
+
}
|
253
1608
|
|
254
|
-
|
255
|
-
|
1609
|
+
if (action) {
|
1610
|
+
event.preventDefault();
|
256
1611
|
|
257
|
-
|
1612
|
+
if (this.cropping) {
|
1613
|
+
this.cropping = false;
|
1614
|
+
this.$dragBox.toggleClass(CLASS_MODAL, this.isCropped && this.options.modal);
|
1615
|
+
}
|
258
1616
|
|
259
|
-
|
260
|
-
height: dragger.height,
|
261
|
-
left: dragger.left,
|
262
|
-
top: dragger.top,
|
263
|
-
width: dragger.width
|
264
|
-
});
|
1617
|
+
this.action = '';
|
265
1618
|
|
266
|
-
|
267
|
-
|
268
|
-
|
1619
|
+
this.trigger(EVENT_CROP_END, {
|
1620
|
+
originalEvent: originalEvent,
|
1621
|
+
action: action
|
1622
|
+
});
|
1623
|
+
}
|
269
1624
|
},
|
270
1625
|
|
271
|
-
|
272
|
-
var
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
1626
|
+
change: function (shiftKey, event) {
|
1627
|
+
var options = this.options;
|
1628
|
+
var aspectRatio = options.aspectRatio;
|
1629
|
+
var action = this.action;
|
1630
|
+
var container = this.container;
|
1631
|
+
var canvas = this.canvas;
|
1632
|
+
var cropBox = this.cropBox;
|
1633
|
+
var width = cropBox.width;
|
1634
|
+
var height = cropBox.height;
|
1635
|
+
var left = cropBox.left;
|
1636
|
+
var top = cropBox.top;
|
1637
|
+
var right = left + width;
|
1638
|
+
var bottom = top + height;
|
1639
|
+
var minLeft = 0;
|
1640
|
+
var minTop = 0;
|
1641
|
+
var maxWidth = container.width;
|
1642
|
+
var maxHeight = container.height;
|
1643
|
+
var renderable = true;
|
1644
|
+
var offset;
|
1645
|
+
var range;
|
1646
|
+
|
1647
|
+
// Locking aspect ratio in "free mode" by holding shift key (#259)
|
1648
|
+
if (!aspectRatio && shiftKey) {
|
1649
|
+
aspectRatio = width && height ? width / height : 1;
|
1650
|
+
}
|
1651
|
+
|
1652
|
+
if (this.limited) {
|
1653
|
+
minLeft = cropBox.minLeft;
|
1654
|
+
minTop = cropBox.minTop;
|
1655
|
+
maxWidth = minLeft + min(container.width, canvas.width);
|
1656
|
+
maxHeight = minTop + min(container.height, canvas.height);
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
range = {
|
1660
|
+
x: this.endX - this.startX,
|
1661
|
+
y: this.endY - this.startY
|
1662
|
+
};
|
279
1663
|
|
280
1664
|
if (aspectRatio) {
|
281
1665
|
range.X = range.y * aspectRatio;
|
282
1666
|
range.Y = range.x / aspectRatio;
|
283
1667
|
}
|
284
1668
|
|
285
|
-
switch (
|
1669
|
+
switch (action) {
|
1670
|
+
// Move crop box
|
1671
|
+
case ACTION_ALL:
|
1672
|
+
left += range.x;
|
1673
|
+
top += range.y;
|
1674
|
+
break;
|
1675
|
+
|
1676
|
+
// Resize crop box
|
1677
|
+
case ACTION_EAST:
|
1678
|
+
if (range.x >= 0 && (right >= maxWidth || aspectRatio &&
|
1679
|
+
(top <= minTop || bottom >= maxHeight))) {
|
286
1680
|
|
287
|
-
|
288
|
-
|
289
|
-
|
1681
|
+
renderable = false;
|
1682
|
+
break;
|
1683
|
+
}
|
1684
|
+
|
1685
|
+
width += range.x;
|
290
1686
|
|
291
1687
|
if (aspectRatio) {
|
292
|
-
|
293
|
-
|
1688
|
+
height = width / aspectRatio;
|
1689
|
+
top -= range.Y / 2;
|
294
1690
|
}
|
295
1691
|
|
296
|
-
if (
|
297
|
-
|
298
|
-
|
1692
|
+
if (width < 0) {
|
1693
|
+
action = ACTION_WEST;
|
1694
|
+
width = 0;
|
299
1695
|
}
|
300
1696
|
|
301
1697
|
break;
|
302
1698
|
|
303
|
-
case
|
304
|
-
|
305
|
-
|
1699
|
+
case ACTION_NORTH:
|
1700
|
+
if (range.y <= 0 && (top <= minTop || aspectRatio &&
|
1701
|
+
(left <= minLeft || right >= maxWidth))) {
|
1702
|
+
|
1703
|
+
renderable = false;
|
1704
|
+
break;
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
height -= range.y;
|
1708
|
+
top += range.y;
|
306
1709
|
|
307
1710
|
if (aspectRatio) {
|
308
|
-
|
309
|
-
|
1711
|
+
width = height * aspectRatio;
|
1712
|
+
left += range.X / 2;
|
310
1713
|
}
|
311
1714
|
|
312
|
-
if (
|
313
|
-
|
314
|
-
|
1715
|
+
if (height < 0) {
|
1716
|
+
action = ACTION_SOUTH;
|
1717
|
+
height = 0;
|
315
1718
|
}
|
316
1719
|
|
317
1720
|
break;
|
318
1721
|
|
319
|
-
case
|
320
|
-
|
321
|
-
|
1722
|
+
case ACTION_WEST:
|
1723
|
+
if (range.x <= 0 && (left <= minLeft || aspectRatio &&
|
1724
|
+
(top <= minTop || bottom >= maxHeight))) {
|
1725
|
+
|
1726
|
+
renderable = false;
|
1727
|
+
break;
|
1728
|
+
}
|
1729
|
+
|
1730
|
+
width -= range.x;
|
1731
|
+
left += range.x;
|
322
1732
|
|
323
1733
|
if (aspectRatio) {
|
324
|
-
|
325
|
-
|
1734
|
+
height = width / aspectRatio;
|
1735
|
+
top += range.Y / 2;
|
326
1736
|
}
|
327
1737
|
|
328
|
-
if (
|
329
|
-
|
330
|
-
|
1738
|
+
if (width < 0) {
|
1739
|
+
action = ACTION_EAST;
|
1740
|
+
width = 0;
|
331
1741
|
}
|
332
1742
|
|
333
1743
|
break;
|
334
1744
|
|
335
|
-
case
|
336
|
-
|
1745
|
+
case ACTION_SOUTH:
|
1746
|
+
if (range.y >= 0 && (bottom >= maxHeight || aspectRatio &&
|
1747
|
+
(left <= minLeft || right >= maxWidth))) {
|
1748
|
+
|
1749
|
+
renderable = false;
|
1750
|
+
break;
|
1751
|
+
}
|
1752
|
+
|
1753
|
+
height += range.y;
|
337
1754
|
|
338
1755
|
if (aspectRatio) {
|
339
|
-
|
340
|
-
|
1756
|
+
width = height * aspectRatio;
|
1757
|
+
left -= range.X / 2;
|
341
1758
|
}
|
342
1759
|
|
343
|
-
if (
|
344
|
-
|
345
|
-
|
1760
|
+
if (height < 0) {
|
1761
|
+
action = ACTION_NORTH;
|
1762
|
+
height = 0;
|
346
1763
|
}
|
347
1764
|
|
348
1765
|
break;
|
349
1766
|
|
350
|
-
case
|
351
|
-
dragger.height -= range.y;
|
352
|
-
dragger.top += range.y;
|
353
|
-
|
1767
|
+
case ACTION_NORTH_EAST:
|
354
1768
|
if (aspectRatio) {
|
355
|
-
|
1769
|
+
if (range.y <= 0 && (top <= minTop || right >= maxWidth)) {
|
1770
|
+
renderable = false;
|
1771
|
+
break;
|
1772
|
+
}
|
1773
|
+
|
1774
|
+
height -= range.y;
|
1775
|
+
top += range.y;
|
1776
|
+
width = height * aspectRatio;
|
356
1777
|
} else {
|
357
|
-
|
1778
|
+
if (range.x >= 0) {
|
1779
|
+
if (right < maxWidth) {
|
1780
|
+
width += range.x;
|
1781
|
+
} else if (range.y <= 0 && top <= minTop) {
|
1782
|
+
renderable = false;
|
1783
|
+
}
|
1784
|
+
} else {
|
1785
|
+
width += range.x;
|
1786
|
+
}
|
1787
|
+
|
1788
|
+
if (range.y <= 0) {
|
1789
|
+
if (top > minTop) {
|
1790
|
+
height -= range.y;
|
1791
|
+
top += range.y;
|
1792
|
+
}
|
1793
|
+
} else {
|
1794
|
+
height -= range.y;
|
1795
|
+
top += range.y;
|
1796
|
+
}
|
358
1797
|
}
|
359
1798
|
|
360
|
-
if (
|
361
|
-
|
362
|
-
|
363
|
-
|
1799
|
+
if (width < 0 && height < 0) {
|
1800
|
+
action = ACTION_SOUTH_WEST;
|
1801
|
+
height = 0;
|
1802
|
+
width = 0;
|
1803
|
+
} else if (width < 0) {
|
1804
|
+
action = ACTION_NORTH_WEST;
|
1805
|
+
width = 0;
|
1806
|
+
} else if (height < 0) {
|
1807
|
+
action = ACTION_SOUTH_EAST;
|
1808
|
+
height = 0;
|
364
1809
|
}
|
365
1810
|
|
366
1811
|
break;
|
367
1812
|
|
368
|
-
case
|
369
|
-
dragger.height -= range.y;
|
370
|
-
dragger.top += range.y;
|
371
|
-
|
1813
|
+
case ACTION_NORTH_WEST:
|
372
1814
|
if (aspectRatio) {
|
373
|
-
|
374
|
-
|
1815
|
+
if (range.y <= 0 && (top <= minTop || left <= minLeft)) {
|
1816
|
+
renderable = false;
|
1817
|
+
break;
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
height -= range.y;
|
1821
|
+
top += range.y;
|
1822
|
+
width = height * aspectRatio;
|
1823
|
+
left += range.X;
|
375
1824
|
} else {
|
376
|
-
|
377
|
-
|
1825
|
+
if (range.x <= 0) {
|
1826
|
+
if (left > minLeft) {
|
1827
|
+
width -= range.x;
|
1828
|
+
left += range.x;
|
1829
|
+
} else if (range.y <= 0 && top <= minTop) {
|
1830
|
+
renderable = false;
|
1831
|
+
}
|
1832
|
+
} else {
|
1833
|
+
width -= range.x;
|
1834
|
+
left += range.x;
|
1835
|
+
}
|
1836
|
+
|
1837
|
+
if (range.y <= 0) {
|
1838
|
+
if (top > minTop) {
|
1839
|
+
height -= range.y;
|
1840
|
+
top += range.y;
|
1841
|
+
}
|
1842
|
+
} else {
|
1843
|
+
height -= range.y;
|
1844
|
+
top += range.y;
|
1845
|
+
}
|
378
1846
|
}
|
379
1847
|
|
380
|
-
if (
|
381
|
-
|
382
|
-
|
383
|
-
|
1848
|
+
if (width < 0 && height < 0) {
|
1849
|
+
action = ACTION_SOUTH_EAST;
|
1850
|
+
height = 0;
|
1851
|
+
width = 0;
|
1852
|
+
} else if (width < 0) {
|
1853
|
+
action = ACTION_NORTH_EAST;
|
1854
|
+
width = 0;
|
1855
|
+
} else if (height < 0) {
|
1856
|
+
action = ACTION_SOUTH_WEST;
|
1857
|
+
height = 0;
|
384
1858
|
}
|
385
1859
|
|
386
1860
|
break;
|
387
1861
|
|
388
|
-
case
|
389
|
-
dragger.width -= range.x;
|
390
|
-
dragger.left += range.x;
|
391
|
-
|
1862
|
+
case ACTION_SOUTH_WEST:
|
392
1863
|
if (aspectRatio) {
|
393
|
-
|
1864
|
+
if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) {
|
1865
|
+
renderable = false;
|
1866
|
+
break;
|
1867
|
+
}
|
1868
|
+
|
1869
|
+
width -= range.x;
|
1870
|
+
left += range.x;
|
1871
|
+
height = width / aspectRatio;
|
394
1872
|
} else {
|
395
|
-
|
1873
|
+
if (range.x <= 0) {
|
1874
|
+
if (left > minLeft) {
|
1875
|
+
width -= range.x;
|
1876
|
+
left += range.x;
|
1877
|
+
} else if (range.y >= 0 && bottom >= maxHeight) {
|
1878
|
+
renderable = false;
|
1879
|
+
}
|
1880
|
+
} else {
|
1881
|
+
width -= range.x;
|
1882
|
+
left += range.x;
|
1883
|
+
}
|
1884
|
+
|
1885
|
+
if (range.y >= 0) {
|
1886
|
+
if (bottom < maxHeight) {
|
1887
|
+
height += range.y;
|
1888
|
+
}
|
1889
|
+
} else {
|
1890
|
+
height += range.y;
|
1891
|
+
}
|
396
1892
|
}
|
397
1893
|
|
398
|
-
if (
|
399
|
-
|
400
|
-
|
401
|
-
|
1894
|
+
if (width < 0 && height < 0) {
|
1895
|
+
action = ACTION_NORTH_EAST;
|
1896
|
+
height = 0;
|
1897
|
+
width = 0;
|
1898
|
+
} else if (width < 0) {
|
1899
|
+
action = ACTION_SOUTH_EAST;
|
1900
|
+
width = 0;
|
1901
|
+
} else if (height < 0) {
|
1902
|
+
action = ACTION_NORTH_WEST;
|
1903
|
+
height = 0;
|
402
1904
|
}
|
403
1905
|
|
404
1906
|
break;
|
405
1907
|
|
406
|
-
case
|
407
|
-
dragger.width += range.x;
|
408
|
-
|
1908
|
+
case ACTION_SOUTH_EAST:
|
409
1909
|
if (aspectRatio) {
|
410
|
-
|
1910
|
+
if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) {
|
1911
|
+
renderable = false;
|
1912
|
+
break;
|
1913
|
+
}
|
1914
|
+
|
1915
|
+
width += range.x;
|
1916
|
+
height = width / aspectRatio;
|
411
1917
|
} else {
|
412
|
-
|
1918
|
+
if (range.x >= 0) {
|
1919
|
+
if (right < maxWidth) {
|
1920
|
+
width += range.x;
|
1921
|
+
} else if (range.y >= 0 && bottom >= maxHeight) {
|
1922
|
+
renderable = false;
|
1923
|
+
}
|
1924
|
+
} else {
|
1925
|
+
width += range.x;
|
1926
|
+
}
|
1927
|
+
|
1928
|
+
if (range.y >= 0) {
|
1929
|
+
if (bottom < maxHeight) {
|
1930
|
+
height += range.y;
|
1931
|
+
}
|
1932
|
+
} else {
|
1933
|
+
height += range.y;
|
1934
|
+
}
|
1935
|
+
}
|
1936
|
+
|
1937
|
+
if (width < 0 && height < 0) {
|
1938
|
+
action = ACTION_NORTH_WEST;
|
1939
|
+
height = 0;
|
1940
|
+
width = 0;
|
1941
|
+
} else if (width < 0) {
|
1942
|
+
action = ACTION_SOUTH_WEST;
|
1943
|
+
width = 0;
|
1944
|
+
} else if (height < 0) {
|
1945
|
+
action = ACTION_NORTH_EAST;
|
1946
|
+
height = 0;
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
break;
|
1950
|
+
|
1951
|
+
// Move canvas
|
1952
|
+
case ACTION_MOVE:
|
1953
|
+
this.move(range.x, range.y);
|
1954
|
+
renderable = false;
|
1955
|
+
break;
|
1956
|
+
|
1957
|
+
// Zoom canvas
|
1958
|
+
case ACTION_ZOOM:
|
1959
|
+
this.zoom((function (x1, y1, x2, y2) {
|
1960
|
+
var z1 = sqrt(x1 * x1 + y1 * y1);
|
1961
|
+
var z2 = sqrt(x2 * x2 + y2 * y2);
|
1962
|
+
|
1963
|
+
return (z2 - z1) / z1;
|
1964
|
+
})(
|
1965
|
+
abs(this.startX - this.startX2),
|
1966
|
+
abs(this.startY - this.startY2),
|
1967
|
+
abs(this.endX - this.endX2),
|
1968
|
+
abs(this.endY - this.endY2)
|
1969
|
+
), event);
|
1970
|
+
this.startX2 = this.endX2;
|
1971
|
+
this.startY2 = this.endY2;
|
1972
|
+
renderable = false;
|
1973
|
+
break;
|
1974
|
+
|
1975
|
+
// Create crop box
|
1976
|
+
case ACTION_CROP:
|
1977
|
+
if (!range.x || !range.y) {
|
1978
|
+
renderable = false;
|
1979
|
+
break;
|
1980
|
+
}
|
1981
|
+
|
1982
|
+
offset = this.$cropper.offset();
|
1983
|
+
left = this.startX - offset.left;
|
1984
|
+
top = this.startY - offset.top;
|
1985
|
+
width = cropBox.minWidth;
|
1986
|
+
height = cropBox.minHeight;
|
1987
|
+
|
1988
|
+
if (range.x > 0) {
|
1989
|
+
action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST;
|
1990
|
+
} else if (range.x < 0) {
|
1991
|
+
left -= width;
|
1992
|
+
action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST;
|
413
1993
|
}
|
414
1994
|
|
415
|
-
if (
|
416
|
-
|
417
|
-
|
418
|
-
|
1995
|
+
if (range.y < 0) {
|
1996
|
+
top -= height;
|
1997
|
+
}
|
1998
|
+
|
1999
|
+
// Show the crop box if is hidden
|
2000
|
+
if (!this.isCropped) {
|
2001
|
+
this.$cropBox.removeClass(CLASS_HIDDEN);
|
2002
|
+
this.isCropped = true;
|
2003
|
+
|
2004
|
+
if (this.limited) {
|
2005
|
+
this.limitCropBox(true, true);
|
2006
|
+
}
|
419
2007
|
}
|
420
2008
|
|
421
2009
|
break;
|
422
2010
|
|
423
|
-
//
|
424
|
-
|
425
|
-
|
426
|
-
|
2011
|
+
// No default
|
2012
|
+
}
|
2013
|
+
|
2014
|
+
if (renderable) {
|
2015
|
+
cropBox.width = width;
|
2016
|
+
cropBox.height = height;
|
2017
|
+
cropBox.left = left;
|
2018
|
+
cropBox.top = top;
|
2019
|
+
this.action = action;
|
2020
|
+
|
2021
|
+
this.renderCropBox();
|
427
2022
|
}
|
428
2023
|
|
429
|
-
|
2024
|
+
// Override
|
430
2025
|
this.startX = this.endX;
|
431
2026
|
this.startY = this.endY;
|
432
2027
|
},
|
433
2028
|
|
434
|
-
|
435
|
-
|
2029
|
+
// Show the crop box manually
|
2030
|
+
crop: function () {
|
2031
|
+
if (!this.isBuilt || this.isDisabled) {
|
2032
|
+
return;
|
2033
|
+
}
|
2034
|
+
|
2035
|
+
if (!this.isCropped) {
|
2036
|
+
this.isCropped = true;
|
2037
|
+
this.limitCropBox(true, true);
|
2038
|
+
|
2039
|
+
if (this.options.modal) {
|
2040
|
+
this.$dragBox.addClass(CLASS_MODAL);
|
2041
|
+
}
|
2042
|
+
|
2043
|
+
this.$cropBox.removeClass(CLASS_HIDDEN);
|
2044
|
+
}
|
2045
|
+
|
2046
|
+
this.setCropBoxData(this.initialCropBox);
|
436
2047
|
},
|
437
2048
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
2049
|
+
// Reset the image and crop box to their initial states
|
2050
|
+
reset: function () {
|
2051
|
+
if (!this.isBuilt || this.isDisabled) {
|
2052
|
+
return;
|
2053
|
+
}
|
2054
|
+
|
2055
|
+
this.image = $.extend({}, this.initialImage);
|
2056
|
+
this.canvas = $.extend({}, this.initialCanvas);
|
2057
|
+
this.cropBox = $.extend({}, this.initialCropBox);
|
442
2058
|
|
443
|
-
this
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
2059
|
+
this.renderCanvas();
|
2060
|
+
|
2061
|
+
if (this.isCropped) {
|
2062
|
+
this.renderCropBox();
|
2063
|
+
}
|
2064
|
+
},
|
2065
|
+
|
2066
|
+
// Clear the crop box
|
2067
|
+
clear: function () {
|
2068
|
+
if (!this.isCropped || this.isDisabled) {
|
2069
|
+
return;
|
2070
|
+
}
|
452
2071
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
2072
|
+
$.extend(this.cropBox, {
|
2073
|
+
left: 0,
|
2074
|
+
top: 0,
|
2075
|
+
width: 0,
|
2076
|
+
height: 0
|
457
2077
|
});
|
2078
|
+
|
2079
|
+
this.isCropped = false;
|
2080
|
+
this.renderCropBox();
|
2081
|
+
|
2082
|
+
this.limitCanvas(true, true);
|
2083
|
+
|
2084
|
+
// Render canvas after crop box rendered
|
2085
|
+
this.renderCanvas();
|
2086
|
+
|
2087
|
+
this.$dragBox.removeClass(CLASS_MODAL);
|
2088
|
+
this.$cropBox.addClass(CLASS_HIDDEN);
|
458
2089
|
},
|
459
2090
|
|
460
|
-
|
2091
|
+
/**
|
2092
|
+
* Replace the image's src and rebuild the cropper
|
2093
|
+
*
|
2094
|
+
* @param {String} url
|
2095
|
+
*/
|
2096
|
+
replace: function (url) {
|
2097
|
+
if (!this.isDisabled && url) {
|
2098
|
+
if (this.isImg) {
|
2099
|
+
this.isReplaced = true;
|
2100
|
+
this.$element.attr('src', url);
|
2101
|
+
}
|
2102
|
+
|
2103
|
+
// Clear previous data
|
2104
|
+
this.options.data = null;
|
2105
|
+
this.load(url);
|
2106
|
+
}
|
2107
|
+
},
|
461
2108
|
|
462
|
-
|
463
|
-
|
2109
|
+
// Enable (unfreeze) the cropper
|
2110
|
+
enable: function () {
|
2111
|
+
if (this.isBuilt) {
|
2112
|
+
this.isDisabled = false;
|
2113
|
+
this.$cropper.removeClass(CLASS_DISABLED);
|
2114
|
+
}
|
464
2115
|
},
|
465
2116
|
|
466
|
-
|
467
|
-
|
2117
|
+
// Disable (freeze) the cropper
|
2118
|
+
disable: function () {
|
2119
|
+
if (this.isBuilt) {
|
2120
|
+
this.isDisabled = true;
|
2121
|
+
this.$cropper.addClass(CLASS_DISABLED);
|
2122
|
+
}
|
468
2123
|
},
|
469
2124
|
|
470
|
-
|
471
|
-
|
472
|
-
|
2125
|
+
// Destroy the cropper and remove the instance from the image
|
2126
|
+
destroy: function () {
|
2127
|
+
var $this = this.$element;
|
2128
|
+
|
2129
|
+
if (this.isLoaded) {
|
2130
|
+
if (this.isImg && this.isReplaced) {
|
2131
|
+
$this.attr('src', this.originalUrl);
|
2132
|
+
}
|
473
2133
|
|
474
|
-
|
475
|
-
|
2134
|
+
this.unbuild();
|
2135
|
+
$this.removeClass(CLASS_HIDDEN);
|
2136
|
+
} else {
|
2137
|
+
if (this.isImg) {
|
2138
|
+
$this.off(EVENT_LOAD, this.start);
|
2139
|
+
} else if (this.$clone) {
|
2140
|
+
this.$clone.remove();
|
476
2141
|
}
|
477
2142
|
}
|
2143
|
+
|
2144
|
+
$this.removeData(NAMESPACE);
|
478
2145
|
},
|
479
2146
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
2147
|
+
/**
|
2148
|
+
* Move the canvas with relative offsets
|
2149
|
+
*
|
2150
|
+
* @param {Number} offsetX
|
2151
|
+
* @param {Number} offsetY (optional)
|
2152
|
+
*/
|
2153
|
+
move: function (offsetX, offsetY) {
|
2154
|
+
var canvas = this.canvas;
|
2155
|
+
|
2156
|
+
this.moveTo(
|
2157
|
+
isUndefined(offsetX) ? offsetX : canvas.left + num(offsetX),
|
2158
|
+
isUndefined(offsetY) ? offsetY : canvas.top + num(offsetY)
|
2159
|
+
);
|
2160
|
+
},
|
487
2161
|
|
488
|
-
|
489
|
-
|
2162
|
+
/**
|
2163
|
+
* Move the canvas to an absolute point
|
2164
|
+
*
|
2165
|
+
* @param {Number} x
|
2166
|
+
* @param {Number} y (optional)
|
2167
|
+
*/
|
2168
|
+
moveTo: function (x, y) {
|
2169
|
+
var canvas = this.canvas;
|
2170
|
+
var isChanged = false;
|
2171
|
+
|
2172
|
+
// If "y" is not present, its default value is "x"
|
2173
|
+
if (isUndefined(y)) {
|
2174
|
+
y = x;
|
490
2175
|
}
|
491
2176
|
|
492
|
-
|
493
|
-
|
2177
|
+
x = num(x);
|
2178
|
+
y = num(y);
|
494
2179
|
|
495
|
-
|
496
|
-
|
2180
|
+
if (this.isBuilt && !this.isDisabled && this.options.movable) {
|
2181
|
+
if (isNumber(x)) {
|
2182
|
+
canvas.left = x;
|
2183
|
+
isChanged = true;
|
497
2184
|
}
|
498
2185
|
|
499
|
-
if (isNumber(
|
500
|
-
|
2186
|
+
if (isNumber(y)) {
|
2187
|
+
canvas.top = y;
|
2188
|
+
isChanged = true;
|
501
2189
|
}
|
502
2190
|
|
503
|
-
if (
|
504
|
-
|
505
|
-
dragger.width = data.width;
|
506
|
-
dragger.height = dragger.width / aspectRatio;
|
507
|
-
} else if (isNumber(data.height) && data.height <= cropper.height) {
|
508
|
-
dragger.height = data.height;
|
509
|
-
dragger.width = dragger.height * aspectRatio;
|
510
|
-
} else if (isNumber(data.x2) && data.x2 <= cropper.width) {
|
511
|
-
dragger.width = data.x2 - dragger.left;
|
512
|
-
dragger.height = dragger.width / aspectRatio;
|
513
|
-
} else if (isNumber(data.y2) && data.y2 <= cropper.height) {
|
514
|
-
dragger.height = data.y2 - dragger.top;
|
515
|
-
dragger.width = dragger.height * aspectRatio;
|
516
|
-
}
|
517
|
-
} else {
|
518
|
-
if (isNumber(data.width) && data.width <= cropper.width) {
|
519
|
-
dragger.width = data.width;
|
520
|
-
} else if (isNumber(data.x2) && data.x2 <= cropper.width) {
|
521
|
-
dragger.width = data.x2 - dragger.left;
|
522
|
-
}
|
523
|
-
|
524
|
-
if (isNumber(data.height) && data.height <= cropper.height) {
|
525
|
-
dragger.height = data.height;
|
526
|
-
} else if (isNumber(data.y2) && data.height <= cropper.height) {
|
527
|
-
dragger.height = data.y2 - dragger.top;
|
528
|
-
}
|
2191
|
+
if (isChanged) {
|
2192
|
+
this.renderCanvas(true);
|
529
2193
|
}
|
530
2194
|
}
|
531
|
-
|
532
|
-
this.dragger = dragger;
|
533
|
-
this.resetDragger();
|
534
2195
|
},
|
535
2196
|
|
536
|
-
|
537
|
-
|
538
|
-
|
2197
|
+
/**
|
2198
|
+
* Zoom the canvas with a relative ratio
|
2199
|
+
*
|
2200
|
+
* @param {Number} ratio
|
2201
|
+
* @param {jQuery Event} _event (private)
|
2202
|
+
*/
|
2203
|
+
zoom: function (ratio, _event) {
|
2204
|
+
var canvas = this.canvas;
|
539
2205
|
|
540
|
-
|
541
|
-
data = {
|
542
|
-
x1: dragger.left,
|
543
|
-
y1: dragger.top,
|
544
|
-
width: dragger.width,
|
545
|
-
height: dragger.height,
|
546
|
-
x2: dragger.left + dragger.width,
|
547
|
-
y2: dragger.top + dragger.height
|
548
|
-
};
|
2206
|
+
ratio = num(ratio);
|
549
2207
|
|
550
|
-
|
2208
|
+
if (ratio < 0) {
|
2209
|
+
ratio = 1 / (1 - ratio);
|
2210
|
+
} else {
|
2211
|
+
ratio = 1 + ratio;
|
551
2212
|
}
|
552
2213
|
|
553
|
-
|
2214
|
+
this.zoomTo(canvas.width * ratio / canvas.naturalWidth, _event);
|
554
2215
|
},
|
555
2216
|
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
2217
|
+
/**
|
2218
|
+
* Zoom the canvas to an absolute ratio
|
2219
|
+
*
|
2220
|
+
* @param {Number} ratio
|
2221
|
+
* @param {jQuery Event} _event (private)
|
2222
|
+
*/
|
2223
|
+
zoomTo: function (ratio, _event) {
|
2224
|
+
var options = this.options;
|
2225
|
+
var canvas = this.canvas;
|
2226
|
+
var width = canvas.width;
|
2227
|
+
var height = canvas.height;
|
2228
|
+
var naturalWidth = canvas.naturalWidth;
|
2229
|
+
var naturalHeight = canvas.naturalHeight;
|
2230
|
+
var originalEvent;
|
2231
|
+
var newWidth;
|
2232
|
+
var newHeight;
|
2233
|
+
var offset;
|
2234
|
+
var center;
|
2235
|
+
|
2236
|
+
ratio = num(ratio);
|
2237
|
+
|
2238
|
+
if (ratio >= 0 && this.isBuilt && !this.isDisabled && options.zoomable) {
|
2239
|
+
newWidth = naturalWidth * ratio;
|
2240
|
+
newHeight = naturalHeight * ratio;
|
2241
|
+
|
2242
|
+
if (_event) {
|
2243
|
+
originalEvent = _event.originalEvent;
|
2244
|
+
}
|
2245
|
+
|
2246
|
+
if (this.trigger(EVENT_ZOOM, {
|
2247
|
+
originalEvent: originalEvent,
|
2248
|
+
oldRatio: width / naturalWidth,
|
2249
|
+
ratio: newWidth / naturalWidth
|
2250
|
+
}).isDefaultPrevented()) {
|
2251
|
+
return;
|
2252
|
+
}
|
2253
|
+
|
2254
|
+
if (originalEvent) {
|
2255
|
+
offset = this.$cropper.offset();
|
2256
|
+
center = originalEvent.touches ? getTouchesCenter(originalEvent.touches) : {
|
2257
|
+
pageX: _event.pageX || originalEvent.pageX || 0,
|
2258
|
+
pageY: _event.pageY || originalEvent.pageY || 0
|
2259
|
+
};
|
2260
|
+
|
2261
|
+
// Zoom from the triggering point of the event
|
2262
|
+
canvas.left -= (newWidth - width) * (
|
2263
|
+
((center.pageX - offset.left) - canvas.left) / width
|
2264
|
+
);
|
2265
|
+
canvas.top -= (newHeight - height) * (
|
2266
|
+
((center.pageY - offset.top) - canvas.top) / height
|
2267
|
+
);
|
2268
|
+
} else {
|
2269
|
+
|
2270
|
+
// Zoom from the center of the canvas
|
2271
|
+
canvas.left -= (newWidth - width) / 2;
|
2272
|
+
canvas.top -= (newHeight - height) / 2;
|
2273
|
+
}
|
2274
|
+
|
2275
|
+
canvas.width = newWidth;
|
2276
|
+
canvas.height = newHeight;
|
2277
|
+
this.renderCanvas(true);
|
560
2278
|
}
|
561
2279
|
},
|
562
2280
|
|
563
|
-
|
564
|
-
|
2281
|
+
/**
|
2282
|
+
* Rotate the canvas with a relative degree
|
2283
|
+
*
|
2284
|
+
* @param {Number} degree
|
2285
|
+
*/
|
2286
|
+
rotate: function (degree) {
|
2287
|
+
this.rotateTo((this.image.rotate || 0) + num(degree));
|
565
2288
|
},
|
566
2289
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
2290
|
+
/**
|
2291
|
+
* Rotate the canvas to an absolute degree
|
2292
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate()
|
2293
|
+
*
|
2294
|
+
* @param {Number} degree
|
2295
|
+
*/
|
2296
|
+
rotateTo: function (degree) {
|
2297
|
+
degree = num(degree);
|
2298
|
+
|
2299
|
+
if (isNumber(degree) && this.isBuilt && !this.isDisabled && this.options.rotatable) {
|
2300
|
+
this.image.rotate = degree % 360;
|
2301
|
+
this.isRotated = true;
|
2302
|
+
this.renderCanvas(true);
|
2303
|
+
}
|
2304
|
+
},
|
574
2305
|
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
2306
|
+
/**
|
2307
|
+
* Scale the image
|
2308
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale()
|
2309
|
+
*
|
2310
|
+
* @param {Number} scaleX
|
2311
|
+
* @param {Number} scaleY (optional)
|
2312
|
+
*/
|
2313
|
+
scale: function (scaleX, scaleY) {
|
2314
|
+
var image = this.image;
|
2315
|
+
var isChanged = false;
|
2316
|
+
|
2317
|
+
// If "scaleY" is not present, its default value is "scaleX"
|
2318
|
+
if (isUndefined(scaleY)) {
|
2319
|
+
scaleY = scaleX;
|
579
2320
|
}
|
580
2321
|
|
581
|
-
|
2322
|
+
scaleX = num(scaleX);
|
2323
|
+
scaleY = num(scaleY);
|
2324
|
+
|
2325
|
+
if (this.isBuilt && !this.isDisabled && this.options.scalable) {
|
2326
|
+
if (isNumber(scaleX)) {
|
2327
|
+
image.scaleX = scaleX;
|
2328
|
+
isChanged = true;
|
2329
|
+
}
|
2330
|
+
|
2331
|
+
if (isNumber(scaleY)) {
|
2332
|
+
image.scaleY = scaleY;
|
2333
|
+
isChanged = true;
|
2334
|
+
}
|
582
2335
|
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
this.direction = direction;
|
587
|
-
this.$image.trigger("dragstart");
|
588
|
-
touching && event.preventDefault();
|
2336
|
+
if (isChanged) {
|
2337
|
+
this.renderImage(true);
|
2338
|
+
}
|
589
2339
|
}
|
590
2340
|
},
|
591
2341
|
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
2342
|
+
/**
|
2343
|
+
* Scale the abscissa of the image
|
2344
|
+
*
|
2345
|
+
* @param {Number} scaleX
|
2346
|
+
*/
|
2347
|
+
scaleX: function (scaleX) {
|
2348
|
+
var scaleY = this.image.scaleY;
|
596
2349
|
|
597
|
-
|
598
|
-
|
599
|
-
touching = true;
|
2350
|
+
this.scale(scaleX, isNumber(scaleY) ? scaleY : 1);
|
2351
|
+
},
|
600
2352
|
|
601
|
-
|
602
|
-
|
603
|
-
|
2353
|
+
/**
|
2354
|
+
* Scale the ordinate of the image
|
2355
|
+
*
|
2356
|
+
* @param {Number} scaleY
|
2357
|
+
*/
|
2358
|
+
scaleY: function (scaleY) {
|
2359
|
+
var scaleX = this.image.scaleX;
|
2360
|
+
|
2361
|
+
this.scale(isNumber(scaleX) ? scaleX : 1, scaleY);
|
2362
|
+
},
|
2363
|
+
|
2364
|
+
/**
|
2365
|
+
* Get the cropped area position and size data (base on the original image)
|
2366
|
+
*
|
2367
|
+
* @param {Boolean} isRounded (optional)
|
2368
|
+
* @return {Object} data
|
2369
|
+
*/
|
2370
|
+
getData: function (isRounded) {
|
2371
|
+
var options = this.options;
|
2372
|
+
var image = this.image;
|
2373
|
+
var canvas = this.canvas;
|
2374
|
+
var cropBox = this.cropBox;
|
2375
|
+
var ratio;
|
2376
|
+
var data;
|
2377
|
+
|
2378
|
+
if (this.isBuilt && this.isCropped) {
|
2379
|
+
data = {
|
2380
|
+
x: cropBox.left - canvas.left,
|
2381
|
+
y: cropBox.top - canvas.top,
|
2382
|
+
width: cropBox.width,
|
2383
|
+
height: cropBox.height
|
2384
|
+
};
|
2385
|
+
|
2386
|
+
ratio = image.width / image.naturalWidth;
|
2387
|
+
|
2388
|
+
$.each(data, function (i, n) {
|
2389
|
+
n = n / ratio;
|
2390
|
+
data[i] = isRounded ? round(n) : n;
|
2391
|
+
});
|
2392
|
+
|
2393
|
+
} else {
|
2394
|
+
data = {
|
2395
|
+
x: 0,
|
2396
|
+
y: 0,
|
2397
|
+
width: 0,
|
2398
|
+
height: 0
|
2399
|
+
};
|
2400
|
+
}
|
2401
|
+
|
2402
|
+
if (options.rotatable) {
|
2403
|
+
data.rotate = image.rotate || 0;
|
604
2404
|
}
|
605
2405
|
|
606
|
-
if (
|
607
|
-
|
608
|
-
|
609
|
-
this.endX = e.pageX;
|
610
|
-
this.endY = e.pageY;
|
611
|
-
this.dragging();
|
2406
|
+
if (options.scalable) {
|
2407
|
+
data.scaleX = image.scaleX || 1;
|
2408
|
+
data.scaleY = image.scaleY || 1;
|
612
2409
|
}
|
2410
|
+
|
2411
|
+
return data;
|
613
2412
|
},
|
614
2413
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
2414
|
+
/**
|
2415
|
+
* Set the cropped area position and size with new data
|
2416
|
+
*
|
2417
|
+
* @param {Object} data
|
2418
|
+
*/
|
2419
|
+
setData: function (data) {
|
2420
|
+
var options = this.options;
|
2421
|
+
var image = this.image;
|
2422
|
+
var canvas = this.canvas;
|
2423
|
+
var cropBoxData = {};
|
2424
|
+
var isRotated;
|
2425
|
+
var isScaled;
|
2426
|
+
var ratio;
|
2427
|
+
|
2428
|
+
if ($.isFunction(data)) {
|
2429
|
+
data = data.call(this.element);
|
2430
|
+
}
|
619
2431
|
|
620
|
-
if (
|
621
|
-
|
622
|
-
|
2432
|
+
if (this.isBuilt && !this.isDisabled && $.isPlainObject(data)) {
|
2433
|
+
if (options.rotatable) {
|
2434
|
+
if (isNumber(data.rotate) && data.rotate !== image.rotate) {
|
2435
|
+
image.rotate = data.rotate;
|
2436
|
+
this.isRotated = isRotated = true;
|
2437
|
+
}
|
2438
|
+
}
|
623
2439
|
|
624
|
-
if (
|
625
|
-
|
2440
|
+
if (options.scalable) {
|
2441
|
+
if (isNumber(data.scaleX) && data.scaleX !== image.scaleX) {
|
2442
|
+
image.scaleX = data.scaleX;
|
2443
|
+
isScaled = true;
|
2444
|
+
}
|
2445
|
+
|
2446
|
+
if (isNumber(data.scaleY) && data.scaleY !== image.scaleY) {
|
2447
|
+
image.scaleY = data.scaleY;
|
2448
|
+
isScaled = true;
|
2449
|
+
}
|
2450
|
+
}
|
2451
|
+
|
2452
|
+
if (isRotated) {
|
2453
|
+
this.renderCanvas();
|
2454
|
+
} else if (isScaled) {
|
2455
|
+
this.renderImage();
|
2456
|
+
}
|
2457
|
+
|
2458
|
+
ratio = image.width / image.naturalWidth;
|
2459
|
+
|
2460
|
+
if (isNumber(data.x)) {
|
2461
|
+
cropBoxData.left = data.x * ratio + canvas.left;
|
626
2462
|
}
|
2463
|
+
|
2464
|
+
if (isNumber(data.y)) {
|
2465
|
+
cropBoxData.top = data.y * ratio + canvas.top;
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
if (isNumber(data.width)) {
|
2469
|
+
cropBoxData.width = data.width * ratio;
|
2470
|
+
}
|
2471
|
+
|
2472
|
+
if (isNumber(data.height)) {
|
2473
|
+
cropBoxData.height = data.height * ratio;
|
2474
|
+
}
|
2475
|
+
|
2476
|
+
this.setCropBoxData(cropBoxData);
|
627
2477
|
}
|
2478
|
+
},
|
628
2479
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
2480
|
+
/**
|
2481
|
+
* Get the container size data
|
2482
|
+
*
|
2483
|
+
* @return {Object} data
|
2484
|
+
*/
|
2485
|
+
getContainerData: function () {
|
2486
|
+
return this.isBuilt ? this.container : {};
|
2487
|
+
},
|
2488
|
+
|
2489
|
+
/**
|
2490
|
+
* Get the image position and size data
|
2491
|
+
*
|
2492
|
+
* @return {Object} data
|
2493
|
+
*/
|
2494
|
+
getImageData: function () {
|
2495
|
+
return this.isLoaded ? this.image : {};
|
2496
|
+
},
|
2497
|
+
|
2498
|
+
/**
|
2499
|
+
* Get the canvas position and size data
|
2500
|
+
*
|
2501
|
+
* @return {Object} data
|
2502
|
+
*/
|
2503
|
+
getCanvasData: function () {
|
2504
|
+
var canvas = this.canvas;
|
2505
|
+
var data = {};
|
2506
|
+
|
2507
|
+
if (this.isBuilt) {
|
2508
|
+
$.each([
|
2509
|
+
'left',
|
2510
|
+
'top',
|
2511
|
+
'width',
|
2512
|
+
'height',
|
2513
|
+
'naturalWidth',
|
2514
|
+
'naturalHeight'
|
2515
|
+
], function (i, n) {
|
2516
|
+
data[n] = canvas[n];
|
2517
|
+
});
|
633
2518
|
}
|
634
|
-
}
|
635
|
-
};
|
636
2519
|
|
637
|
-
|
638
|
-
Cropper.fn = {
|
639
|
-
toggle: function($e) {
|
640
|
-
$e.toggleClass("cropper-hidden");
|
2520
|
+
return data;
|
641
2521
|
},
|
642
2522
|
|
643
|
-
|
644
|
-
|
2523
|
+
/**
|
2524
|
+
* Set the canvas position and size with new data
|
2525
|
+
*
|
2526
|
+
* @param {Object} data
|
2527
|
+
*/
|
2528
|
+
setCanvasData: function (data) {
|
2529
|
+
var canvas = this.canvas;
|
2530
|
+
var aspectRatio = canvas.aspectRatio;
|
2531
|
+
|
2532
|
+
if ($.isFunction(data)) {
|
2533
|
+
data = data.call(this.$element);
|
2534
|
+
}
|
2535
|
+
|
2536
|
+
if (this.isBuilt && !this.isDisabled && $.isPlainObject(data)) {
|
2537
|
+
if (isNumber(data.left)) {
|
2538
|
+
canvas.left = data.left;
|
2539
|
+
}
|
2540
|
+
|
2541
|
+
if (isNumber(data.top)) {
|
2542
|
+
canvas.top = data.top;
|
2543
|
+
}
|
2544
|
+
|
2545
|
+
if (isNumber(data.width)) {
|
2546
|
+
canvas.width = data.width;
|
2547
|
+
canvas.height = data.width / aspectRatio;
|
2548
|
+
} else if (isNumber(data.height)) {
|
2549
|
+
canvas.height = data.height;
|
2550
|
+
canvas.width = data.height * aspectRatio;
|
2551
|
+
}
|
645
2552
|
|
646
|
-
|
647
|
-
$e.css("position", option || "relative");
|
2553
|
+
this.renderCanvas(true);
|
648
2554
|
}
|
649
2555
|
},
|
650
2556
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
2557
|
+
/**
|
2558
|
+
* Get the crop box position and size data
|
2559
|
+
*
|
2560
|
+
* @return {Object} data
|
2561
|
+
*/
|
2562
|
+
getCropBoxData: function () {
|
2563
|
+
var cropBox = this.cropBox;
|
2564
|
+
var data;
|
2565
|
+
|
2566
|
+
if (this.isBuilt && this.isCropped) {
|
2567
|
+
data = {
|
2568
|
+
left: cropBox.left,
|
2569
|
+
top: cropBox.top,
|
2570
|
+
width: cropBox.width,
|
2571
|
+
height: cropBox.height
|
658
2572
|
};
|
659
2573
|
}
|
2574
|
+
|
2575
|
+
return data || {};
|
660
2576
|
},
|
661
2577
|
|
662
|
-
|
663
|
-
|
664
|
-
|
2578
|
+
/**
|
2579
|
+
* Set the crop box position and size with new data
|
2580
|
+
*
|
2581
|
+
* @param {Object} data
|
2582
|
+
*/
|
2583
|
+
setCropBoxData: function (data) {
|
2584
|
+
var cropBox = this.cropBox;
|
2585
|
+
var aspectRatio = this.options.aspectRatio;
|
2586
|
+
var isWidthChanged;
|
2587
|
+
var isHeightChanged;
|
2588
|
+
|
2589
|
+
if ($.isFunction(data)) {
|
2590
|
+
data = data.call(this.$element);
|
2591
|
+
}
|
665
2592
|
|
666
|
-
|
667
|
-
value = data[i];
|
2593
|
+
if (this.isBuilt && this.isCropped && !this.isDisabled && $.isPlainObject(data)) {
|
668
2594
|
|
669
|
-
if (data.
|
670
|
-
|
2595
|
+
if (isNumber(data.left)) {
|
2596
|
+
cropBox.left = data.left;
|
671
2597
|
}
|
672
|
-
}
|
673
2598
|
|
674
|
-
|
675
|
-
|
2599
|
+
if (isNumber(data.top)) {
|
2600
|
+
cropBox.top = data.top;
|
2601
|
+
}
|
676
2602
|
|
677
|
-
|
678
|
-
|
679
|
-
|
2603
|
+
if (isNumber(data.width)) {
|
2604
|
+
isWidthChanged = true;
|
2605
|
+
cropBox.width = data.width;
|
2606
|
+
}
|
680
2607
|
|
681
|
-
|
682
|
-
|
683
|
-
|
2608
|
+
if (isNumber(data.height)) {
|
2609
|
+
isHeightChanged = true;
|
2610
|
+
cropBox.height = data.height;
|
2611
|
+
}
|
2612
|
+
|
2613
|
+
if (aspectRatio) {
|
2614
|
+
if (isWidthChanged) {
|
2615
|
+
cropBox.height = cropBox.width / aspectRatio;
|
2616
|
+
} else if (isHeightChanged) {
|
2617
|
+
cropBox.width = cropBox.height * aspectRatio;
|
2618
|
+
}
|
684
2619
|
}
|
685
|
-
});
|
686
2620
|
|
687
|
-
|
2621
|
+
this.renderCropBox();
|
2622
|
+
}
|
688
2623
|
},
|
689
2624
|
|
690
|
-
|
691
|
-
|
692
|
-
|
2625
|
+
/**
|
2626
|
+
* Get a canvas drawn the cropped image
|
2627
|
+
*
|
2628
|
+
* @param {Object} options (optional)
|
2629
|
+
* @return {HTMLCanvasElement} canvas
|
2630
|
+
*/
|
2631
|
+
getCroppedCanvas: function (options) {
|
2632
|
+
var originalWidth;
|
2633
|
+
var originalHeight;
|
2634
|
+
var canvasWidth;
|
2635
|
+
var canvasHeight;
|
2636
|
+
var scaledWidth;
|
2637
|
+
var scaledHeight;
|
2638
|
+
var scaledRatio;
|
2639
|
+
var aspectRatio;
|
2640
|
+
var canvas;
|
2641
|
+
var context;
|
2642
|
+
var data;
|
2643
|
+
|
2644
|
+
if (!this.isBuilt || !this.isCropped || !SUPPORT_CANVAS) {
|
2645
|
+
return;
|
2646
|
+
}
|
2647
|
+
|
2648
|
+
if (!$.isPlainObject(options)) {
|
2649
|
+
options = {};
|
2650
|
+
}
|
2651
|
+
|
2652
|
+
data = this.getData();
|
2653
|
+
originalWidth = data.width;
|
2654
|
+
originalHeight = data.height;
|
2655
|
+
aspectRatio = originalWidth / originalHeight;
|
2656
|
+
|
2657
|
+
if ($.isPlainObject(options)) {
|
2658
|
+
scaledWidth = options.width;
|
2659
|
+
scaledHeight = options.height;
|
2660
|
+
|
2661
|
+
if (scaledWidth) {
|
2662
|
+
scaledHeight = scaledWidth / aspectRatio;
|
2663
|
+
scaledRatio = scaledWidth / originalWidth;
|
2664
|
+
} else if (scaledHeight) {
|
2665
|
+
scaledWidth = scaledHeight * aspectRatio;
|
2666
|
+
scaledRatio = scaledHeight / originalHeight;
|
2667
|
+
}
|
2668
|
+
}
|
2669
|
+
|
2670
|
+
// The canvas element will use `Math.floor` on a float number, so floor first
|
2671
|
+
canvasWidth = floor(scaledWidth || originalWidth);
|
2672
|
+
canvasHeight = floor(scaledHeight || originalHeight);
|
2673
|
+
|
2674
|
+
canvas = $('<canvas>')[0];
|
2675
|
+
canvas.width = canvasWidth;
|
2676
|
+
canvas.height = canvasHeight;
|
2677
|
+
context = canvas.getContext('2d');
|
2678
|
+
|
2679
|
+
if (options.fillColor) {
|
2680
|
+
context.fillStyle = options.fillColor;
|
2681
|
+
context.fillRect(0, 0, canvasWidth, canvasHeight);
|
693
2682
|
}
|
694
2683
|
|
695
|
-
|
2684
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage
|
2685
|
+
context.drawImage.apply(context, (function () {
|
2686
|
+
var source = getSourceCanvas(this.$clone[0], this.image);
|
2687
|
+
var sourceWidth = source.width;
|
2688
|
+
var sourceHeight = source.height;
|
2689
|
+
var args = [source];
|
2690
|
+
|
2691
|
+
// Source canvas
|
2692
|
+
var srcX = data.x;
|
2693
|
+
var srcY = data.y;
|
2694
|
+
var srcWidth;
|
2695
|
+
var srcHeight;
|
2696
|
+
|
2697
|
+
// Destination canvas
|
2698
|
+
var dstX;
|
2699
|
+
var dstY;
|
2700
|
+
var dstWidth;
|
2701
|
+
var dstHeight;
|
2702
|
+
|
2703
|
+
if (srcX <= -originalWidth || srcX > sourceWidth) {
|
2704
|
+
srcX = srcWidth = dstX = dstWidth = 0;
|
2705
|
+
} else if (srcX <= 0) {
|
2706
|
+
dstX = -srcX;
|
2707
|
+
srcX = 0;
|
2708
|
+
srcWidth = dstWidth = min(sourceWidth, originalWidth + srcX);
|
2709
|
+
} else if (srcX <= sourceWidth) {
|
2710
|
+
dstX = 0;
|
2711
|
+
srcWidth = dstWidth = min(originalWidth, sourceWidth - srcX);
|
2712
|
+
}
|
2713
|
+
|
2714
|
+
if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) {
|
2715
|
+
srcY = srcHeight = dstY = dstHeight = 0;
|
2716
|
+
} else if (srcY <= 0) {
|
2717
|
+
dstY = -srcY;
|
2718
|
+
srcY = 0;
|
2719
|
+
srcHeight = dstHeight = min(sourceHeight, originalHeight + srcY);
|
2720
|
+
} else if (srcY <= sourceHeight) {
|
2721
|
+
dstY = 0;
|
2722
|
+
srcHeight = dstHeight = min(originalHeight, sourceHeight - srcY);
|
2723
|
+
}
|
2724
|
+
|
2725
|
+
// All the numerical parameters should be integer for `drawImage` (#476)
|
2726
|
+
args.push(floor(srcX), floor(srcY), floor(srcWidth), floor(srcHeight));
|
2727
|
+
|
2728
|
+
// Scale destination sizes
|
2729
|
+
if (scaledRatio) {
|
2730
|
+
dstX *= scaledRatio;
|
2731
|
+
dstY *= scaledRatio;
|
2732
|
+
dstWidth *= scaledRatio;
|
2733
|
+
dstHeight *= scaledRatio;
|
2734
|
+
}
|
2735
|
+
|
2736
|
+
// Avoid "IndexSizeError" in IE and Firefox
|
2737
|
+
if (dstWidth > 0 && dstHeight > 0) {
|
2738
|
+
args.push(floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));
|
2739
|
+
}
|
2740
|
+
|
2741
|
+
return args;
|
2742
|
+
}).call(this));
|
2743
|
+
|
2744
|
+
return canvas;
|
696
2745
|
},
|
697
2746
|
|
698
|
-
|
699
|
-
|
2747
|
+
/**
|
2748
|
+
* Change the aspect ratio of the crop box
|
2749
|
+
*
|
2750
|
+
* @param {Number} aspectRatio
|
2751
|
+
*/
|
2752
|
+
setAspectRatio: function (aspectRatio) {
|
2753
|
+
var options = this.options;
|
2754
|
+
|
2755
|
+
if (!this.isDisabled && !isUndefined(aspectRatio)) {
|
2756
|
+
|
2757
|
+
// 0 -> NaN
|
2758
|
+
options.aspectRatio = max(0, aspectRatio) || NaN;
|
2759
|
+
|
2760
|
+
if (this.isBuilt) {
|
2761
|
+
this.initCropBox();
|
2762
|
+
|
2763
|
+
if (this.isCropped) {
|
2764
|
+
this.renderCropBox();
|
2765
|
+
}
|
2766
|
+
}
|
2767
|
+
}
|
700
2768
|
},
|
701
2769
|
|
702
|
-
|
703
|
-
|
2770
|
+
/**
|
2771
|
+
* Change the drag mode
|
2772
|
+
*
|
2773
|
+
* @param {String} mode (optional)
|
2774
|
+
*/
|
2775
|
+
setDragMode: function (mode) {
|
2776
|
+
var options = this.options;
|
2777
|
+
var croppable;
|
2778
|
+
var movable;
|
2779
|
+
|
2780
|
+
if (this.isLoaded && !this.isDisabled) {
|
2781
|
+
croppable = mode === ACTION_CROP;
|
2782
|
+
movable = options.movable && mode === ACTION_MOVE;
|
2783
|
+
mode = (croppable || movable) ? mode : ACTION_NONE;
|
2784
|
+
|
2785
|
+
this.$dragBox.
|
2786
|
+
data(DATA_ACTION, mode).
|
2787
|
+
toggleClass(CLASS_CROP, croppable).
|
2788
|
+
toggleClass(CLASS_MOVE, movable);
|
2789
|
+
|
2790
|
+
if (!options.cropBoxMovable) {
|
2791
|
+
|
2792
|
+
// Sync drag mode to crop box when it is not movable(#300)
|
2793
|
+
this.$face.
|
2794
|
+
data(DATA_ACTION, mode).
|
2795
|
+
toggleClass(CLASS_CROP, croppable).
|
2796
|
+
toggleClass(CLASS_MOVE, movable);
|
2797
|
+
}
|
2798
|
+
}
|
704
2799
|
}
|
705
2800
|
};
|
706
2801
|
|
707
|
-
Cropper.
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
2802
|
+
Cropper.DEFAULTS = {
|
2803
|
+
|
2804
|
+
// Define the view mode of the cropper
|
2805
|
+
viewMode: 0, // 0, 1, 2, 3
|
2806
|
+
|
2807
|
+
// Define the dragging mode of the cropper
|
2808
|
+
dragMode: 'crop', // 'crop', 'move' or 'none'
|
2809
|
+
|
2810
|
+
// Define the aspect ratio of the crop box
|
2811
|
+
aspectRatio: NaN,
|
2812
|
+
|
2813
|
+
// An object with the previous cropping result data
|
2814
|
+
data: null,
|
2815
|
+
|
2816
|
+
// A jQuery selector for adding extra containers to preview
|
2817
|
+
preview: '',
|
2818
|
+
|
2819
|
+
// Re-render the cropper when resize the window
|
2820
|
+
responsive: true,
|
2821
|
+
|
2822
|
+
// Restore the cropped area after resize the window
|
2823
|
+
restore: true,
|
2824
|
+
|
2825
|
+
// Check if the current image is a cross-origin image
|
2826
|
+
checkCrossOrigin: true,
|
2827
|
+
|
2828
|
+
// Check the current image's Exif Orientation information
|
2829
|
+
checkOrientation: true,
|
2830
|
+
|
2831
|
+
// Show the black modal
|
735
2832
|
modal: true,
|
736
|
-
|
2833
|
+
|
2834
|
+
// Show the dashed lines for guiding
|
2835
|
+
guides: true,
|
2836
|
+
|
2837
|
+
// Show the center indicator for guiding
|
2838
|
+
center: true,
|
2839
|
+
|
2840
|
+
// Show the white modal to highlight the crop box
|
2841
|
+
highlight: true,
|
2842
|
+
|
2843
|
+
// Show the grid background
|
2844
|
+
background: true,
|
2845
|
+
|
2846
|
+
// Enable to crop the image automatically when initialize
|
2847
|
+
autoCrop: true,
|
2848
|
+
|
2849
|
+
// Define the percentage of automatic cropping area when initializes
|
2850
|
+
autoCropArea: 0.8,
|
2851
|
+
|
2852
|
+
// Enable to move the image
|
2853
|
+
movable: true,
|
2854
|
+
|
2855
|
+
// Enable to rotate the image
|
2856
|
+
rotatable: true,
|
2857
|
+
|
2858
|
+
// Enable to scale the image
|
2859
|
+
scalable: true,
|
2860
|
+
|
2861
|
+
// Enable to zoom the image
|
2862
|
+
zoomable: true,
|
2863
|
+
|
2864
|
+
// Enable to zoom the image by dragging touch
|
2865
|
+
zoomOnTouch: true,
|
2866
|
+
|
2867
|
+
// Enable to zoom the image by wheeling mouse
|
2868
|
+
zoomOnWheel: true,
|
2869
|
+
|
2870
|
+
// Define zoom ratio when zoom the image by wheeling mouse
|
2871
|
+
wheelZoomRatio: 0.1,
|
2872
|
+
|
2873
|
+
// Enable to move the crop box
|
2874
|
+
cropBoxMovable: true,
|
2875
|
+
|
2876
|
+
// Enable to resize the crop box
|
2877
|
+
cropBoxResizable: true,
|
2878
|
+
|
2879
|
+
// Toggle drag mode between "crop" and "move" when click twice on the cropper
|
2880
|
+
toggleDragModeOnDblclick: true,
|
2881
|
+
|
2882
|
+
// Size limitation
|
2883
|
+
minCanvasWidth: 0,
|
2884
|
+
minCanvasHeight: 0,
|
2885
|
+
minCropBoxWidth: 0,
|
2886
|
+
minCropBoxHeight: 0,
|
2887
|
+
minContainerWidth: 200,
|
2888
|
+
minContainerHeight: 100,
|
2889
|
+
|
2890
|
+
// Shortcuts of events
|
2891
|
+
build: null,
|
2892
|
+
built: null,
|
2893
|
+
cropstart: null,
|
2894
|
+
cropmove: null,
|
2895
|
+
cropend: null,
|
2896
|
+
crop: null,
|
2897
|
+
zoom: null
|
737
2898
|
};
|
738
2899
|
|
739
|
-
Cropper.setDefaults = function(options) {
|
740
|
-
$.extend(Cropper.
|
2900
|
+
Cropper.setDefaults = function (options) {
|
2901
|
+
$.extend(Cropper.DEFAULTS, options);
|
741
2902
|
};
|
742
2903
|
|
2904
|
+
Cropper.TEMPLATE = (
|
2905
|
+
'<div class="cropper-container">' +
|
2906
|
+
'<div class="cropper-wrap-box">' +
|
2907
|
+
'<div class="cropper-canvas"></div>' +
|
2908
|
+
'</div>' +
|
2909
|
+
'<div class="cropper-drag-box"></div>' +
|
2910
|
+
'<div class="cropper-crop-box">' +
|
2911
|
+
'<span class="cropper-view-box"></span>' +
|
2912
|
+
'<span class="cropper-dashed dashed-h"></span>' +
|
2913
|
+
'<span class="cropper-dashed dashed-v"></span>' +
|
2914
|
+
'<span class="cropper-center"></span>' +
|
2915
|
+
'<span class="cropper-face"></span>' +
|
2916
|
+
'<span class="cropper-line line-e" data-action="e"></span>' +
|
2917
|
+
'<span class="cropper-line line-n" data-action="n"></span>' +
|
2918
|
+
'<span class="cropper-line line-w" data-action="w"></span>' +
|
2919
|
+
'<span class="cropper-line line-s" data-action="s"></span>' +
|
2920
|
+
'<span class="cropper-point point-e" data-action="e"></span>' +
|
2921
|
+
'<span class="cropper-point point-n" data-action="n"></span>' +
|
2922
|
+
'<span class="cropper-point point-w" data-action="w"></span>' +
|
2923
|
+
'<span class="cropper-point point-s" data-action="s"></span>' +
|
2924
|
+
'<span class="cropper-point point-ne" data-action="ne"></span>' +
|
2925
|
+
'<span class="cropper-point point-nw" data-action="nw"></span>' +
|
2926
|
+
'<span class="cropper-point point-sw" data-action="sw"></span>' +
|
2927
|
+
'<span class="cropper-point point-se" data-action="se"></span>' +
|
2928
|
+
'</div>' +
|
2929
|
+
'</div>'
|
2930
|
+
);
|
2931
|
+
|
2932
|
+
// Save the other cropper
|
2933
|
+
Cropper.other = $.fn.cropper;
|
2934
|
+
|
743
2935
|
// Register as jQuery plugin
|
744
|
-
$.fn.cropper = function(
|
745
|
-
var
|
2936
|
+
$.fn.cropper = function (option) {
|
2937
|
+
var args = toArray(arguments, 1);
|
2938
|
+
var result;
|
746
2939
|
|
747
|
-
this.each(function() {
|
748
|
-
var $this = $(this)
|
749
|
-
|
2940
|
+
this.each(function () {
|
2941
|
+
var $this = $(this);
|
2942
|
+
var data = $this.data(NAMESPACE);
|
2943
|
+
var options;
|
2944
|
+
var fn;
|
750
2945
|
|
751
2946
|
if (!data) {
|
752
|
-
|
753
|
-
|
2947
|
+
if (/destroy/.test(option)) {
|
2948
|
+
return;
|
2949
|
+
}
|
2950
|
+
|
2951
|
+
options = $.extend({}, $this.data(), $.isPlainObject(option) && option);
|
2952
|
+
$this.data(NAMESPACE, (data = new Cropper(this, options)));
|
754
2953
|
}
|
755
2954
|
|
756
|
-
if (typeof
|
757
|
-
result = data
|
2955
|
+
if (typeof option === 'string' && $.isFunction(fn = data[option])) {
|
2956
|
+
result = fn.apply(data, args);
|
758
2957
|
}
|
759
2958
|
});
|
760
2959
|
|
761
|
-
return (
|
2960
|
+
return isUndefined(result) ? this : result;
|
762
2961
|
};
|
763
2962
|
|
764
2963
|
$.fn.cropper.Constructor = Cropper;
|
765
2964
|
$.fn.cropper.setDefaults = Cropper.setDefaults;
|
766
2965
|
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
2966
|
+
// No conflict
|
2967
|
+
$.fn.cropper.noConflict = function () {
|
2968
|
+
$.fn.cropper = Cropper.other;
|
2969
|
+
return this;
|
2970
|
+
};
|
2971
|
+
|
2972
|
+
});
|