motion-image-editor 0.0.1 → 0.0.3
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 +4 -4
- data/lib/project/controllers/image_editor_controller.rb +162 -86
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 226472c295b2d57d3bd62e85792534346b931730
|
4
|
+
data.tar.gz: 08016d9fb24343fbac4d2247ba543756f957617e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3721b52b59c18805e7b4d7ca69807fc854536ecf340da76670d9c1dfc6405600e04ac6874a7acada985310c99e15e27241981f21d0ca19eba8c762fa91c5cc5
|
7
|
+
data.tar.gz: f2bfa5a4e7a5226cbc930b3172d40e04821269d6b200a7472bdcad2ae9b4cf5e9bb4fcc04b10fecf1fa515bab63c169a0dbb31d5c2775b71021a2d9183612678
|
@@ -3,12 +3,15 @@ class Motion; class ImageEditorController < UIViewController
|
|
3
3
|
MINIMUM_SCALE = 1
|
4
4
|
MAXIMUM_SCALE = 3
|
5
5
|
|
6
|
-
attr_reader :
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
attr_reader :source_image, :crop_rect, :output_width
|
7
|
+
attr_writer :rotation_enabled, :enforce_bounds
|
8
|
+
|
9
|
+
def initWithNibName(nib, bundle: bundle)
|
10
|
+
super.tap do |controller|
|
11
|
+
controller.rotation_enabled = true
|
12
|
+
controller.enforce_bounds = false
|
13
|
+
end
|
14
|
+
end
|
12
15
|
|
13
16
|
def viewDidLoad
|
14
17
|
super
|
@@ -20,6 +23,14 @@ class Motion; class ImageEditorController < UIViewController
|
|
20
23
|
setup_constraints
|
21
24
|
end
|
22
25
|
|
26
|
+
def viewDidAppear(animated)
|
27
|
+
super
|
28
|
+
|
29
|
+
image_view.image = preview_image
|
30
|
+
|
31
|
+
reset
|
32
|
+
end
|
33
|
+
|
23
34
|
def add_subviews
|
24
35
|
view.addSubview(crop_view)
|
25
36
|
view.insertSubview(image_view, belowSubview: crop_view)
|
@@ -46,6 +57,53 @@ class Motion; class ImageEditorController < UIViewController
|
|
46
57
|
views: { 'crop' => crop_view }))
|
47
58
|
end
|
48
59
|
|
60
|
+
def source_image=(image)
|
61
|
+
if image != source_image
|
62
|
+
@source_image = image
|
63
|
+
@preview_image = nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def crop_rect=(rect)
|
68
|
+
@crop_rect = rect
|
69
|
+
|
70
|
+
crop_view.crop_rect = rect
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_gesture_state?(state)
|
74
|
+
case state
|
75
|
+
when UIGestureRecognizerStateEnded || UIGestureRecognizerStateCancelled
|
76
|
+
new_scale = bounded_scale(scale)
|
77
|
+
|
78
|
+
delta_x = scale_center.x - image_view.bounds.size.width / 2.0
|
79
|
+
delta_y = scale_center.y - image_view.bounds.size.height / 2.0
|
80
|
+
|
81
|
+
transform = CGAffineTransformTranslate(image_view.transform, delta_x, delta_y)
|
82
|
+
|
83
|
+
transform = CGAffineTransformScale(transform, new_scale / scale , new_scale / scale)
|
84
|
+
|
85
|
+
transform = CGAffineTransformTranslate(transform, -delta_x, -delta_y)
|
86
|
+
|
87
|
+
view.userInteractionEnabled = false
|
88
|
+
|
89
|
+
UIView.animateWithDuration(
|
90
|
+
ANIMATION_DURATION,
|
91
|
+
delay: 0,
|
92
|
+
options: UIViewAnimationOptionCurveEaseOut,
|
93
|
+
animations: -> { image_view.transform = transform },
|
94
|
+
completion: -> (finished) {
|
95
|
+
view.userInteractionEnabled = true
|
96
|
+
@scale = new_scale
|
97
|
+
})
|
98
|
+
|
99
|
+
check_bounds if enforce_bounds?
|
100
|
+
|
101
|
+
false
|
102
|
+
else
|
103
|
+
true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
49
107
|
def process(&block)
|
50
108
|
view.userInteractionEnabled = false
|
51
109
|
|
@@ -74,19 +132,6 @@ class Motion; class ImageEditorController < UIViewController
|
|
74
132
|
end
|
75
133
|
end
|
76
134
|
|
77
|
-
def crop_rect=(rect)
|
78
|
-
@crop_rect = rect
|
79
|
-
|
80
|
-
crop_view.crop_rect = rect
|
81
|
-
end
|
82
|
-
|
83
|
-
def scale_reset_orientations
|
84
|
-
[ UIImageOrientationUpMirrored,
|
85
|
-
UIImageOrientationDownMirrored,
|
86
|
-
UIImageOrientationLeftMirrored,
|
87
|
-
UIImageOrientationRightMirrored ]
|
88
|
-
end
|
89
|
-
|
90
135
|
def transform_image(transform, source_image: source_image, source_size: source_size, source_orientation: source_orientation, output_width: output_width, crop_rect: crop_rect, image_view_size: image_view_size)
|
91
136
|
aspect = crop_rect.size.height / crop_rect.size.width
|
92
137
|
output_size = CGSizeMake(output_width, output_width * aspect)
|
@@ -145,14 +190,6 @@ class Motion; class ImageEditorController < UIViewController
|
|
145
190
|
CGBitmapContextCreateImage(context)
|
146
191
|
end
|
147
192
|
|
148
|
-
def viewDidAppear(animated)
|
149
|
-
super
|
150
|
-
|
151
|
-
image_view.image = preview_image
|
152
|
-
|
153
|
-
reset
|
154
|
-
end
|
155
|
-
|
156
193
|
def reset(options = {})
|
157
194
|
animated = options.fetch(:animated, false)
|
158
195
|
|
@@ -163,8 +200,8 @@ class Motion; class ImageEditorController < UIViewController
|
|
163
200
|
crop_aspect = crop_rect.size.height / crop_rect.size.width
|
164
201
|
|
165
202
|
if source_aspect > crop_aspect
|
166
|
-
|
167
|
-
|
203
|
+
w = crop_rect.size.width
|
204
|
+
h = source_aspect * w
|
168
205
|
else
|
169
206
|
h = crop_rect.size.height
|
170
207
|
w = h / source_aspect
|
@@ -189,7 +226,53 @@ class Motion; class ImageEditorController < UIViewController
|
|
189
226
|
end
|
190
227
|
end
|
191
228
|
|
192
|
-
|
229
|
+
def check_bounds
|
230
|
+
y_offset = 0
|
231
|
+
x_offset = 0
|
232
|
+
|
233
|
+
if image_view.frame.origin.x > crop_rect.origin.x
|
234
|
+
x_offset = -(image_view.frame.origin.x - crop_rect.origin.x)
|
235
|
+
new_right_x = CGRectGetMaxX(image_view.frame) + x_offset
|
236
|
+
|
237
|
+
if new_right_x < CGRectGetMaxX(crop_rect)
|
238
|
+
x_offset = CGRectGetMaxX(crop_rect) - CGRectGetMaxX(image_view.frame)
|
239
|
+
end
|
240
|
+
elsif CGRectGetMaxX(image_view.frame) < CGRectGetMaxX(crop_rect)
|
241
|
+
x_offset = CGRectGetMaxX(crop_rect) - CGRectGetMaxX(image_view.frame)
|
242
|
+
new_left_x = image_view.frame.origin.x + x_offset
|
243
|
+
|
244
|
+
if new_left_x > crop_rect.origin.x
|
245
|
+
x_offset = crop_rect.origin.x - image_view.frame.origin.x
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
if image_view.frame.origin.y > crop_rect.origin.y
|
250
|
+
y_offset = -(image_view.frame.origin.y - crop_rect.origin.y)
|
251
|
+
new_bottom_y = CGRectGetMaxY(image_view.frame) + y_offset
|
252
|
+
|
253
|
+
if new_bottom_y < CGRectGetMaxY(crop_rect)
|
254
|
+
y_offset = CGRectGetMaxY(crop_rect) - CGRectGetMaxY(image_view.frame)
|
255
|
+
end
|
256
|
+
elsif CGRectGetMaxY(image_view.frame) < CGRectGetMaxY(crop_rect)
|
257
|
+
y_offset = CGRectGetMaxY(crop_rect) - CGRectGetMaxY(image_view.frame)
|
258
|
+
new_top_y = image_view.frame.origin.y + y_offset
|
259
|
+
|
260
|
+
if new_top_y > crop_rect.origin.y
|
261
|
+
y_offset = crop_rect.origin.y - image_view.frame.origin.y
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
if x_offset || y_offset
|
266
|
+
view.userInteractionEnabled = false
|
267
|
+
transform = CGAffineTransformTranslate(image_view.transform, x_offset / scale, y_offset / scale)
|
268
|
+
UIView.animateWithDuration(
|
269
|
+
ANIMATION_DURATION,
|
270
|
+
delay: 0,
|
271
|
+
options: UIViewAnimationOptionCurveEaseOut,
|
272
|
+
animations: -> { image_view.transform = transform },
|
273
|
+
completion: -> (finished) { view.userInteractionEnabled = true })
|
274
|
+
end
|
275
|
+
end
|
193
276
|
|
194
277
|
def touchesBegan(touches, withEvent: event)
|
195
278
|
handle_touches(event.allTouches)
|
@@ -221,48 +304,19 @@ class Motion; class ImageEditorController < UIViewController
|
|
221
304
|
end
|
222
305
|
end
|
223
306
|
|
224
|
-
def handle_state?(state)
|
225
|
-
if state == UIGestureRecognizerStateEnded
|
226
|
-
new_scale = bounded_scale(scale)
|
227
|
-
|
228
|
-
delta_x = scale_center.x - image_view.bounds.size.width / 2.0
|
229
|
-
delta_y = scale_center.y - image_view.bounds.size.height / 2.0
|
230
|
-
|
231
|
-
transform = CGAffineTransformTranslate(image_view.transform, delta_x, delta_y)
|
232
|
-
|
233
|
-
transform = CGAffineTransformScale(transform, new_scale / scale , new_scale / scale)
|
234
|
-
|
235
|
-
transform = CGAffineTransformTranslate(transform, -delta_x, -delta_y)
|
236
|
-
|
237
|
-
view.userInteractionEnabled = false
|
238
|
-
|
239
|
-
UIView.animateWithDuration(
|
240
|
-
ANIMATION_DURATION,
|
241
|
-
delay: 0,
|
242
|
-
options: UIViewAnimationOptionCurveEaseOut,
|
243
|
-
animations: -> { image_view.transform = transform },
|
244
|
-
completion: -> (finished) {
|
245
|
-
view.userInteractionEnabled = true
|
246
|
-
@scale = new_scale
|
247
|
-
})
|
248
|
-
|
249
|
-
false
|
250
|
-
else
|
251
|
-
true
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
307
|
def handle_pan(recognizer)
|
256
|
-
|
257
|
-
|
308
|
+
if handle_gesture_state? recognizer.state
|
309
|
+
translation = recognizer.translationInView(image_view)
|
310
|
+
transform = CGAffineTransformTranslate(image_view.transform, translation.x, translation.y)
|
258
311
|
|
259
|
-
|
312
|
+
image_view.transform = transform
|
260
313
|
|
261
|
-
|
314
|
+
recognizer.setTranslation(CGPointZero, inView: crop_view)
|
315
|
+
end
|
262
316
|
end
|
263
317
|
|
264
318
|
def handle_pinch(recognizer)
|
265
|
-
if
|
319
|
+
if handle_gesture_state? recognizer.state
|
266
320
|
if recognizer.state == UIGestureRecognizerStateBegan
|
267
321
|
@scale_center = @touch_center
|
268
322
|
end
|
@@ -283,22 +337,37 @@ class Motion; class ImageEditorController < UIViewController
|
|
283
337
|
end
|
284
338
|
|
285
339
|
def handle_rotation(recognizer)
|
286
|
-
|
287
|
-
|
340
|
+
if rotation_enabled? && handle_gesture_state?(recognizer.state)
|
341
|
+
delta_x = touch_center.x - image_view.bounds.size.width / 2
|
342
|
+
delta_y = touch_center.y - image_view.bounds.size.height / 2
|
288
343
|
|
289
|
-
|
290
|
-
|
291
|
-
|
344
|
+
transform = CGAffineTransformTranslate(image_view.transform, delta_x, delta_y)
|
345
|
+
transform = CGAffineTransformRotate(transform, recognizer.rotation)
|
346
|
+
transform = CGAffineTransformTranslate(transform, -delta_x, -delta_y)
|
292
347
|
|
293
|
-
|
348
|
+
image_view.transform = transform
|
294
349
|
|
295
|
-
|
350
|
+
recognizer.rotation = 0
|
351
|
+
end
|
296
352
|
end
|
297
353
|
|
298
354
|
def handle_tap(recognizer)
|
299
355
|
reset(animated: true)
|
300
356
|
end
|
301
357
|
|
358
|
+
def bounded_scale(scale)
|
359
|
+
return scale if (MINIMUM_SCALE..MAXIMUM_SCALE).include? scale
|
360
|
+
|
361
|
+
scale < MINIMUM_SCALE ? MINIMUM_SCALE : MAXIMUM_SCALE
|
362
|
+
end
|
363
|
+
|
364
|
+
def scale_reset_orientations
|
365
|
+
[ UIImageOrientationUpMirrored,
|
366
|
+
UIImageOrientationDownMirrored,
|
367
|
+
UIImageOrientationLeftMirrored,
|
368
|
+
UIImageOrientationRightMirrored ]
|
369
|
+
end
|
370
|
+
|
302
371
|
def pan_recognizer
|
303
372
|
@pan_recognizer ||= UIPanGestureRecognizer.alloc.initWithTarget(self, action: 'handle_pan:').tap do |recognizer|
|
304
373
|
recognizer.cancelsTouchesInView = false
|
@@ -326,19 +395,6 @@ class Motion; class ImageEditorController < UIViewController
|
|
326
395
|
end
|
327
396
|
end
|
328
397
|
|
329
|
-
def source_image=(image)
|
330
|
-
if image != source_image
|
331
|
-
@source_image = image
|
332
|
-
@preview_image = nil
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
def bounded_scale(scale)
|
337
|
-
return scale if (MINIMUM_SCALE..MAXIMUM_SCALE).include? scale
|
338
|
-
|
339
|
-
scale < MINIMUM_SCALE ? MINIMUM_SCALE : MAXIMUM_SCALE
|
340
|
-
end
|
341
|
-
|
342
398
|
def preview_image
|
343
399
|
@preview_image ||= source_image.resizedImageToFitInSize(view.bounds.size, scaleIfSmaller: false)
|
344
400
|
end
|
@@ -355,7 +411,27 @@ class Motion; class ImageEditorController < UIViewController
|
|
355
411
|
end
|
356
412
|
end
|
357
413
|
|
414
|
+
def scale
|
415
|
+
@scale ||= 1
|
416
|
+
end
|
417
|
+
|
418
|
+
def touch_center
|
419
|
+
@touch_center ||= CGPointZero
|
420
|
+
end
|
421
|
+
|
422
|
+
def scale_center
|
423
|
+
@scale_center ||= CGPointZero
|
424
|
+
end
|
425
|
+
|
358
426
|
def prefersStatusBarHidden
|
359
427
|
true
|
360
428
|
end
|
429
|
+
|
430
|
+
def rotation_enabled?
|
431
|
+
!!@rotation_enabled
|
432
|
+
end
|
433
|
+
|
434
|
+
def enforce_bounds?
|
435
|
+
!!@enforce_bounds
|
436
|
+
end
|
361
437
|
end; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-image-editor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Devon Blandin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: motion-cocoapods
|