rails_cropit 0.1.0
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.
- data/.gitignore +9 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/rails_cropit/version.rb +3 -0
- data/lib/rails_cropit.rb +6 -0
- data/rails_cropit.gemspec +25 -0
- data/vendor/assets/javascripts/jquery.cropit.js +637 -0
- data/vendor/assets/javascripts/jquery.cropit.min.js +10 -0
- data/vendor/assets/stylesheets/cropit.coffee +415 -0
- data/vendor/assets/stylesheets/plugin.coffee +83 -0
- data/vendor/assets/stylesheets/zoomer.coffee +31 -0
- metadata +112 -0
@@ -0,0 +1,415 @@
|
|
1
|
+
class Cropit
|
2
|
+
|
3
|
+
@_DEFAULTS:
|
4
|
+
exportZoom: 1
|
5
|
+
imageBackground: false
|
6
|
+
imageBackgroundBorderWidth: 0
|
7
|
+
imageState: null
|
8
|
+
allowCrossOrigin: false
|
9
|
+
allowDragNDrop: true
|
10
|
+
freeMove: false
|
11
|
+
minZoom: 'fill'
|
12
|
+
|
13
|
+
@PREVIEW_EVENTS: do ->
|
14
|
+
[
|
15
|
+
'mousedown', 'mouseup', 'mouseleave'
|
16
|
+
'touchstart', 'touchend', 'touchcancel', 'touchleave'
|
17
|
+
]
|
18
|
+
.map (type) -> "#{type}.cropit"
|
19
|
+
.join ' '
|
20
|
+
@PREVIEW_MOVE_EVENTS: 'mousemove.cropit touchmove.cropit'
|
21
|
+
@ZOOM_INPUT_EVENTS: do ->
|
22
|
+
[
|
23
|
+
'mousemove', 'touchmove', 'change'
|
24
|
+
]
|
25
|
+
.map (type) -> "#{type}.cropit"
|
26
|
+
.join ' '
|
27
|
+
|
28
|
+
constructor: (@element, options) ->
|
29
|
+
@$el = $ @element
|
30
|
+
|
31
|
+
dynamicDefaults =
|
32
|
+
$fileInput: @$ 'input.cropit-image-input'
|
33
|
+
$preview: @$ '.cropit-image-preview'
|
34
|
+
$zoomSlider: @$ 'input.cropit-image-zoom-input'
|
35
|
+
$previewContainer: @$ '.cropit-image-preview-container'
|
36
|
+
|
37
|
+
@options = $.extend {}, Cropit._DEFAULTS, dynamicDefaults, options
|
38
|
+
@init()
|
39
|
+
|
40
|
+
init: ->
|
41
|
+
@image = new Image
|
42
|
+
@image.crossOrigin = 'Anonymous' if @options.allowCrossOrigin
|
43
|
+
|
44
|
+
@$fileInput = @options.$fileInput
|
45
|
+
.attr
|
46
|
+
accept: 'image/*'
|
47
|
+
@$preview = @options.$preview
|
48
|
+
.css
|
49
|
+
backgroundRepeat: 'no-repeat'
|
50
|
+
@$zoomSlider = @options.$zoomSlider
|
51
|
+
.attr
|
52
|
+
min: 0
|
53
|
+
max: 1
|
54
|
+
step: .01
|
55
|
+
|
56
|
+
@previewSize =
|
57
|
+
w: @options.width or @$preview.width()
|
58
|
+
h: @options.height or @$preview.height()
|
59
|
+
@$preview.width @previewSize.w if @options.width
|
60
|
+
@$preview.height @previewSize.h if @options.height
|
61
|
+
|
62
|
+
if @options.imageBackground
|
63
|
+
if $.isArray @options.imageBackgroundBorderWidth
|
64
|
+
@imageBgBorderWidthArray = @options.imageBackgroundBorderWidth
|
65
|
+
else
|
66
|
+
@imageBgBorderWidthArray = []
|
67
|
+
[0..3].forEach (i) =>
|
68
|
+
@imageBgBorderWidthArray[i] = @options.imageBackgroundBorderWidth
|
69
|
+
|
70
|
+
$previewContainer = @options.$previewContainer
|
71
|
+
@$imageBg = $ '<img />'
|
72
|
+
.addClass 'cropit-image-background'
|
73
|
+
.attr 'alt', ''
|
74
|
+
.css 'position', 'absolute'
|
75
|
+
@$imageBgContainer = $ '<div />'
|
76
|
+
.addClass 'cropit-image-background-container'
|
77
|
+
.css
|
78
|
+
position: 'absolute'
|
79
|
+
zIndex: 0
|
80
|
+
left: -@imageBgBorderWidthArray[3] + window.parseInt @$preview.css 'border-left-width'
|
81
|
+
top: -@imageBgBorderWidthArray[0] + window.parseInt @$preview.css 'border-top-width'
|
82
|
+
width: @previewSize.w + @imageBgBorderWidthArray[1] + @imageBgBorderWidthArray[3]
|
83
|
+
height: @previewSize.h + @imageBgBorderWidthArray[0] + @imageBgBorderWidthArray[2]
|
84
|
+
.append @$imageBg
|
85
|
+
@$imageBgContainer.css overflow: 'hidden' if @imageBgBorderWidthArray[0] > 0
|
86
|
+
$previewContainer
|
87
|
+
.css 'position', 'relative'
|
88
|
+
.prepend @$imageBgContainer
|
89
|
+
@$preview.css 'position', 'relative'
|
90
|
+
|
91
|
+
@$preview.hover =>
|
92
|
+
@$imageBg.addClass 'cropit-preview-hovered'
|
93
|
+
, =>
|
94
|
+
@$imageBg.removeClass 'cropit-preview-hovered'
|
95
|
+
|
96
|
+
@initialOffset = x: 0, y: 0
|
97
|
+
@initialZoom = 0
|
98
|
+
@initialZoomSliderPos = 0
|
99
|
+
@imageLoaded = false
|
100
|
+
|
101
|
+
@moveContinue = false
|
102
|
+
|
103
|
+
@zoomer = new Zoomer
|
104
|
+
|
105
|
+
jQuery.event.props.push 'dataTransfer' if @options.allowDragNDrop
|
106
|
+
@bindListeners()
|
107
|
+
|
108
|
+
@$zoomSlider.val @initialZoomSliderPos
|
109
|
+
@setOffset @options.imageState?.offset or @initialOffset
|
110
|
+
@zoom = @options.imageState?.zoom or @initialZoom
|
111
|
+
@loadImage @options.imageState?.src or null
|
112
|
+
|
113
|
+
bindListeners: ->
|
114
|
+
@$fileInput.on 'change.cropit', @onFileChange.bind @
|
115
|
+
@$preview.on Cropit.PREVIEW_EVENTS, @onPreviewEvent.bind @
|
116
|
+
@$zoomSlider.on Cropit.ZOOM_INPUT_EVENTS, @onZoomSliderChange.bind @
|
117
|
+
|
118
|
+
if @options.allowDragNDrop
|
119
|
+
@$preview.on 'dragover.cropit dragleave.cropit', @onDragOver.bind @
|
120
|
+
@$preview.on 'drop.cropit', @onDrop.bind @
|
121
|
+
|
122
|
+
unbindListeners: ->
|
123
|
+
@$fileInput.off 'change.cropit'
|
124
|
+
@$preview.off Cropit.PREVIEW_EVENTS
|
125
|
+
@$preview.off 'dragover.cropit dragleave.cropit drop.cropit'
|
126
|
+
@$zoomSlider.off Cropit.ZOOM_INPUT_EVENTS
|
127
|
+
|
128
|
+
reset: ->
|
129
|
+
@zoom = @initialZoom
|
130
|
+
@offset = @initialOffset
|
131
|
+
|
132
|
+
onFileChange: ->
|
133
|
+
@options.onFileChange?()
|
134
|
+
|
135
|
+
@loadFileReader @$fileInput.get(0).files[0]
|
136
|
+
|
137
|
+
loadFileReader: (file) ->
|
138
|
+
fileReader = new FileReader()
|
139
|
+
if file?.type.match 'image'
|
140
|
+
@setImageLoadingClass()
|
141
|
+
|
142
|
+
fileReader.readAsDataURL file
|
143
|
+
fileReader.onload = @onFileReaderLoaded.bind @
|
144
|
+
fileReader.onerror = @onFileReaderError.bind @
|
145
|
+
else if file?
|
146
|
+
@onFileReaderError()
|
147
|
+
|
148
|
+
onFileReaderLoaded: (e) ->
|
149
|
+
@reset()
|
150
|
+
@loadImage e.target.result
|
151
|
+
|
152
|
+
onFileReaderError: ->
|
153
|
+
@options.onFileReaderError?()
|
154
|
+
|
155
|
+
onDragOver: (e) ->
|
156
|
+
e.preventDefault()
|
157
|
+
e.dataTransfer.dropEffect = 'copy'
|
158
|
+
@$preview.toggleClass 'cropit-drag-hovered', e.type is 'dragover'
|
159
|
+
|
160
|
+
onDrop: (e) ->
|
161
|
+
e.preventDefault()
|
162
|
+
e.stopPropagation()
|
163
|
+
|
164
|
+
files = Array.prototype.slice.call e.dataTransfer.files, 0
|
165
|
+
files.some (file) =>
|
166
|
+
if file.type.match 'image'
|
167
|
+
@loadFileReader file
|
168
|
+
return true
|
169
|
+
|
170
|
+
@$preview.removeClass 'cropit-drag-hovered'
|
171
|
+
|
172
|
+
loadImage: (imageSrc) ->
|
173
|
+
@imageSrc = imageSrc
|
174
|
+
return unless @imageSrc
|
175
|
+
|
176
|
+
@options.onImageLoading?()
|
177
|
+
@setImageLoadingClass()
|
178
|
+
|
179
|
+
@image.onload = @onImageLoaded.bind @
|
180
|
+
@image.onerror = @onImageError.bind @
|
181
|
+
|
182
|
+
@image.src = @imageSrc
|
183
|
+
|
184
|
+
onImageLoaded: ->
|
185
|
+
@setImageLoadedClass()
|
186
|
+
|
187
|
+
@setOffset @offset
|
188
|
+
@$preview.css 'background-image', "url(#{@imageSrc})"
|
189
|
+
@$imageBg.attr 'src', @imageSrc if @options.imageBackground
|
190
|
+
|
191
|
+
@imageSize =
|
192
|
+
w: @image.width
|
193
|
+
h: @image.height
|
194
|
+
|
195
|
+
@setupZoomer()
|
196
|
+
|
197
|
+
@imageLoaded = true
|
198
|
+
|
199
|
+
@options.onImageLoaded?()
|
200
|
+
|
201
|
+
onImageError: ->
|
202
|
+
@options.onImageError?()
|
203
|
+
|
204
|
+
setImageLoadingClass: ->
|
205
|
+
@$preview
|
206
|
+
.removeClass 'cropit-image-loaded'
|
207
|
+
.addClass 'cropit-image-loading'
|
208
|
+
|
209
|
+
setImageLoadedClass: ->
|
210
|
+
@$preview
|
211
|
+
.removeClass 'cropit-image-loading'
|
212
|
+
.addClass 'cropit-image-loaded'
|
213
|
+
|
214
|
+
getEventPosition: (e) ->
|
215
|
+
e = e.originalEvent?.touches?[0] if e.originalEvent?.touches?[0]
|
216
|
+
return x: e.clientX, y: e.clientY if e.clientX and e.clientY
|
217
|
+
|
218
|
+
onPreviewEvent: (e) ->
|
219
|
+
return unless @imageLoaded
|
220
|
+
@moveContinue = false
|
221
|
+
@$preview.off Cropit.PREVIEW_MOVE_EVENTS
|
222
|
+
|
223
|
+
if e.type is 'mousedown' or e.type is 'touchstart'
|
224
|
+
@origin = @getEventPosition e
|
225
|
+
@moveContinue = true
|
226
|
+
@$preview.on Cropit.PREVIEW_MOVE_EVENTS, @onMove.bind @
|
227
|
+
else
|
228
|
+
$(document.body).focus()
|
229
|
+
e.stopPropagation()
|
230
|
+
false
|
231
|
+
|
232
|
+
onMove: (e) ->
|
233
|
+
eventPosition = @getEventPosition e
|
234
|
+
|
235
|
+
if @moveContinue and eventPosition
|
236
|
+
@setOffset
|
237
|
+
x: @offset.x + eventPosition.x - @origin.x
|
238
|
+
y: @offset.y + eventPosition.y - @origin.y
|
239
|
+
|
240
|
+
@origin = eventPosition
|
241
|
+
|
242
|
+
e.stopPropagation()
|
243
|
+
false
|
244
|
+
|
245
|
+
setOffset: (position) ->
|
246
|
+
@offset = @fixOffset position
|
247
|
+
@$preview.css 'background-position', "#{@offset.x}px #{@offset.y}px"
|
248
|
+
if @options.imageBackground
|
249
|
+
@$imageBg.css
|
250
|
+
left: @offset.x + @imageBgBorderWidthArray[3]
|
251
|
+
top: @offset.y + @imageBgBorderWidthArray[0]
|
252
|
+
|
253
|
+
fixOffset: (offset) ->
|
254
|
+
return offset unless @imageLoaded
|
255
|
+
|
256
|
+
ret = x: offset.x, y: offset.y
|
257
|
+
|
258
|
+
unless @options.freeMove
|
259
|
+
if @imageSize.w * @zoom >= @previewSize.w
|
260
|
+
ret.x = Math.min 0, Math.max ret.x, @previewSize.w - @imageSize.w * @zoom
|
261
|
+
else
|
262
|
+
ret.x = Math.max 0, Math.min ret.x, @previewSize.w - @imageSize.w * @zoom
|
263
|
+
|
264
|
+
if @imageSize.h * @zoom >= @previewSize.h
|
265
|
+
ret.y = Math.min 0, Math.max ret.y, @previewSize.h - @imageSize.h * @zoom
|
266
|
+
else
|
267
|
+
ret.y = Math.max 0, Math.min ret.y, @previewSize.h - @imageSize.h * @zoom
|
268
|
+
|
269
|
+
ret.x = @round ret.x
|
270
|
+
ret.y = @round ret.y
|
271
|
+
|
272
|
+
ret
|
273
|
+
|
274
|
+
onZoomSliderChange: ->
|
275
|
+
return unless @imageLoaded
|
276
|
+
|
277
|
+
@zoomSliderPos = Number @$zoomSlider.val()
|
278
|
+
newZoom = @zoomer.getZoom @zoomSliderPos
|
279
|
+
@setZoom newZoom
|
280
|
+
|
281
|
+
enableZoomSlider: ->
|
282
|
+
@$zoomSlider.removeAttr 'disabled'
|
283
|
+
@options.onZoomEnabled?()
|
284
|
+
|
285
|
+
disableZoomSlider: ->
|
286
|
+
@$zoomSlider.attr 'disabled', true
|
287
|
+
@options.onZoomDisabled?()
|
288
|
+
|
289
|
+
setupZoomer: ->
|
290
|
+
@zoomer.setup @imageSize, @previewSize, @options.exportZoom, @options
|
291
|
+
@zoom = @fixZoom @zoom
|
292
|
+
@setZoom @zoom
|
293
|
+
|
294
|
+
if @isZoomable() then @enableZoomSlider() else @disableZoomSlider()
|
295
|
+
|
296
|
+
setZoom: (newZoom) ->
|
297
|
+
newZoom = @fixZoom newZoom
|
298
|
+
|
299
|
+
updatedWidth = @round @imageSize.w * newZoom
|
300
|
+
updatedHeight = @round @imageSize.h * newZoom
|
301
|
+
|
302
|
+
oldZoom = @zoom
|
303
|
+
|
304
|
+
newX = @previewSize.w / 2 - (@previewSize.w / 2 - @offset.x) * newZoom / oldZoom
|
305
|
+
newY = @previewSize.h / 2 - (@previewSize.h / 2 - @offset.y) * newZoom / oldZoom
|
306
|
+
|
307
|
+
@zoom = newZoom
|
308
|
+
@setOffset x: newX, y: newY
|
309
|
+
|
310
|
+
@zoomSliderPos = @zoomer.getSliderPos @zoom
|
311
|
+
@$zoomSlider.val @zoomSliderPos
|
312
|
+
|
313
|
+
@$preview.css 'background-size', "#{updatedWidth}px #{updatedHeight}px"
|
314
|
+
if @options.imageBackground
|
315
|
+
@$imageBg.css
|
316
|
+
width: updatedWidth
|
317
|
+
height: updatedHeight
|
318
|
+
|
319
|
+
fixZoom: (zoom) ->
|
320
|
+
@zoomer.fixZoom zoom
|
321
|
+
|
322
|
+
isZoomable: ->
|
323
|
+
@zoomer.isZoomable()
|
324
|
+
|
325
|
+
getCroppedImageData: (exportOptions) ->
|
326
|
+
return null unless @imageSrc
|
327
|
+
|
328
|
+
exportDefaults =
|
329
|
+
type: 'image/png'
|
330
|
+
quality: .75
|
331
|
+
originalSize: false
|
332
|
+
fillBg: '#fff'
|
333
|
+
exportOptions = $.extend {}, exportDefaults, exportOptions
|
334
|
+
|
335
|
+
croppedSize =
|
336
|
+
w: @previewSize.w
|
337
|
+
h: @previewSize.h
|
338
|
+
|
339
|
+
exportZoom = if exportOptions.originalSize then 1 / @zoom else @options.exportZoom
|
340
|
+
|
341
|
+
canvas = $ '<canvas />'
|
342
|
+
.attr
|
343
|
+
width: croppedSize.w * exportZoom
|
344
|
+
height: croppedSize.h * exportZoom
|
345
|
+
.get 0
|
346
|
+
canvasContext = canvas.getContext '2d'
|
347
|
+
|
348
|
+
if exportOptions.type is 'image/jpeg'
|
349
|
+
canvasContext.fillStyle = exportOptions.fillBg
|
350
|
+
canvasContext.fillRect 0, 0, canvas.width, canvas.height
|
351
|
+
|
352
|
+
canvasContext.drawImage @image,
|
353
|
+
@offset.x * exportZoom,
|
354
|
+
@offset.y * exportZoom,
|
355
|
+
@zoom * exportZoom * @imageSize.w,
|
356
|
+
@zoom * exportZoom * @imageSize.h
|
357
|
+
|
358
|
+
canvas.toDataURL exportOptions.type, exportOptions.quality
|
359
|
+
|
360
|
+
getImageState: ->
|
361
|
+
src: @imageSrc
|
362
|
+
offset: @offset
|
363
|
+
zoom: @zoom
|
364
|
+
|
365
|
+
getImageSrc: ->
|
366
|
+
@imageSrc
|
367
|
+
|
368
|
+
getOffset: ->
|
369
|
+
@offset
|
370
|
+
|
371
|
+
getZoom: ->
|
372
|
+
@zoom
|
373
|
+
|
374
|
+
getImageSize: ->
|
375
|
+
return null unless @imageSize
|
376
|
+
width: @imageSize.w
|
377
|
+
height: @imageSize.h
|
378
|
+
|
379
|
+
getPreviewSize: ->
|
380
|
+
width: @previewSize.w
|
381
|
+
height: @previewSize.h
|
382
|
+
|
383
|
+
setPreviewSize: (size) ->
|
384
|
+
return unless size?.width > 0 and size?.height > 0
|
385
|
+
|
386
|
+
@previewSize =
|
387
|
+
w: size.width
|
388
|
+
h: size.height
|
389
|
+
@$preview.css
|
390
|
+
width: @previewSize.w
|
391
|
+
height: @previewSize.h
|
392
|
+
|
393
|
+
if @options.imageBackground
|
394
|
+
@$imageBgContainer.css
|
395
|
+
width: @previewSize.w + @imageBgBorderWidthArray[1] + @imageBgBorderWidthArray[3]
|
396
|
+
height: @previewSize.h + @imageBgBorderWidthArray[0] + @imageBgBorderWidthArray[2]
|
397
|
+
|
398
|
+
if @imageLoaded
|
399
|
+
@setupZoomer()
|
400
|
+
|
401
|
+
disable: ->
|
402
|
+
@unbindListeners()
|
403
|
+
@disableZoomSlider()
|
404
|
+
@$el.addClass 'cropit-disabled'
|
405
|
+
|
406
|
+
reenable: ->
|
407
|
+
@bindListeners()
|
408
|
+
@enableZoomSlider()
|
409
|
+
@$el.removeClass 'cropit-disabled'
|
410
|
+
|
411
|
+
round: (x) -> +(Math.round(x * 1e2) + 'e-2')
|
412
|
+
|
413
|
+
$: (selector) ->
|
414
|
+
return null unless @$el
|
415
|
+
@$el.find selector
|
@@ -0,0 +1,83 @@
|
|
1
|
+
dataKey = 'cropit'
|
2
|
+
|
3
|
+
methods =
|
4
|
+
|
5
|
+
init: (options) ->
|
6
|
+
@each ->
|
7
|
+
# Only instantiate once per element
|
8
|
+
unless $.data @, dataKey
|
9
|
+
cropit = new Cropit @, options
|
10
|
+
$.data @, dataKey, cropit
|
11
|
+
|
12
|
+
destroy: ->
|
13
|
+
@each ->
|
14
|
+
$.removeData @, dataKey
|
15
|
+
|
16
|
+
isZoomable: ->
|
17
|
+
cropit = @first().data dataKey
|
18
|
+
cropit?.isZoomable()
|
19
|
+
|
20
|
+
export: (options) ->
|
21
|
+
cropit = @first().data dataKey
|
22
|
+
cropit?.getCroppedImageData options
|
23
|
+
|
24
|
+
imageState: ->
|
25
|
+
cropit = @first().data dataKey
|
26
|
+
cropit?.getImageState()
|
27
|
+
|
28
|
+
imageSrc: (newImageSrc) ->
|
29
|
+
if newImageSrc?
|
30
|
+
@each ->
|
31
|
+
cropit = $.data @, dataKey
|
32
|
+
cropit?.reset()
|
33
|
+
cropit?.loadImage newImageSrc
|
34
|
+
else
|
35
|
+
cropit = @first().data dataKey
|
36
|
+
cropit?.getImageSrc()
|
37
|
+
|
38
|
+
offset: (newOffset) ->
|
39
|
+
if newOffset? and newOffset.x? and newOffset.y?
|
40
|
+
@each ->
|
41
|
+
cropit = $.data @, dataKey
|
42
|
+
cropit?.setOffset newOffset
|
43
|
+
else
|
44
|
+
cropit = @first().data dataKey
|
45
|
+
cropit?.getOffset()
|
46
|
+
|
47
|
+
zoom: (newZoom) ->
|
48
|
+
if newZoom?
|
49
|
+
@each ->
|
50
|
+
cropit = $.data @, dataKey
|
51
|
+
cropit?.setZoom newZoom
|
52
|
+
else
|
53
|
+
cropit = @first().data dataKey
|
54
|
+
cropit?.getZoom()
|
55
|
+
|
56
|
+
imageSize: ->
|
57
|
+
cropit = @first().data dataKey
|
58
|
+
cropit?.getImageSize()
|
59
|
+
|
60
|
+
previewSize: (newSize) ->
|
61
|
+
if newSize?
|
62
|
+
@each ->
|
63
|
+
cropit = $.data @, dataKey
|
64
|
+
cropit?.setPreviewSize newSize
|
65
|
+
else
|
66
|
+
cropit = @first().data dataKey
|
67
|
+
cropit?.getPreviewSize()
|
68
|
+
|
69
|
+
disable: ->
|
70
|
+
@each ->
|
71
|
+
cropit = $.data @, dataKey
|
72
|
+
cropit.disable()
|
73
|
+
|
74
|
+
reenable: ->
|
75
|
+
@each ->
|
76
|
+
cropit = $.data @, dataKey
|
77
|
+
cropit.reenable()
|
78
|
+
|
79
|
+
$.fn.cropit = (method) ->
|
80
|
+
if methods[method]
|
81
|
+
methods[method].apply @, [].slice.call arguments, 1
|
82
|
+
else
|
83
|
+
methods.init.apply @, arguments
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Zoomer
|
2
|
+
setup: (imageSize, previewSize, exportZoom = 1, options) ->
|
3
|
+
widthRatio = previewSize.w / imageSize.w
|
4
|
+
heightRatio = previewSize.h / imageSize.h
|
5
|
+
|
6
|
+
if options?.minZoom is 'fit'
|
7
|
+
@minZoom = if widthRatio < heightRatio then widthRatio else heightRatio
|
8
|
+
else
|
9
|
+
@minZoom = if widthRatio < heightRatio then heightRatio else widthRatio
|
10
|
+
|
11
|
+
@maxZoom = if @minZoom < 1 / exportZoom then 1 / exportZoom else @minZoom
|
12
|
+
|
13
|
+
getZoom: (sliderPos) ->
|
14
|
+
return null unless @minZoom and @maxZoom
|
15
|
+
sliderPos * (@maxZoom - @minZoom) + @minZoom
|
16
|
+
|
17
|
+
getSliderPos: (zoom) ->
|
18
|
+
return null unless @minZoom and @maxZoom
|
19
|
+
if @minZoom is @maxZoom
|
20
|
+
0
|
21
|
+
else
|
22
|
+
(zoom - @minZoom) / (@maxZoom - @minZoom)
|
23
|
+
|
24
|
+
isZoomable: ->
|
25
|
+
return null unless @minZoom and @maxZoom
|
26
|
+
@minZoom isnt @maxZoom
|
27
|
+
|
28
|
+
fixZoom: (zoom) ->
|
29
|
+
return @minZoom if zoom < @minZoom
|
30
|
+
return @maxZoom if zoom > @maxZoom
|
31
|
+
zoom
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_cropit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Kaushal Kishor
|
14
|
+
autorequire:
|
15
|
+
bindir: exe
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2015-09-27 00:00:00 +05:30
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 31
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 8
|
31
|
+
version: "1.8"
|
32
|
+
prerelease: false
|
33
|
+
requirement: *id001
|
34
|
+
type: :development
|
35
|
+
name: bundler
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 35
|
43
|
+
segments:
|
44
|
+
- 10
|
45
|
+
- 0
|
46
|
+
version: "10.0"
|
47
|
+
prerelease: false
|
48
|
+
requirement: *id002
|
49
|
+
type: :development
|
50
|
+
name: rake
|
51
|
+
description: It is jQuery gem for "customizable crop and zoom" on rails application platform
|
52
|
+
email:
|
53
|
+
- kaushalk16@gmail.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- .gitignore
|
62
|
+
- CODE_OF_CONDUCT.md
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- bin/console
|
68
|
+
- bin/setup
|
69
|
+
- lib/rails_cropit.rb
|
70
|
+
- lib/rails_cropit/version.rb
|
71
|
+
- rails_cropit.gemspec
|
72
|
+
- vendor/assets/javascripts/jquery.cropit.js
|
73
|
+
- vendor/assets/javascripts/jquery.cropit.min.js
|
74
|
+
- vendor/assets/stylesheets/cropit.coffee
|
75
|
+
- vendor/assets/stylesheets/plugin.coffee
|
76
|
+
- vendor/assets/stylesheets/zoomer.coffee
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: https://github.com/kaushal-xx/rails_cropit
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.4.2
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Crop image run time
|
111
|
+
test_files: []
|
112
|
+
|