sugarcube 0.18.12 → 0.18.16
Sign up to get free protection for your applications and to get access to all the features.
data/README.md
CHANGED
@@ -727,9 +727,10 @@ view.fade_out { |completed|
|
|
727
727
|
}
|
728
728
|
|
729
729
|
# fade_out options
|
730
|
-
view.fade_out(0.5,
|
731
|
-
|
732
|
-
|
730
|
+
view.fade_out(duration: 0.5,
|
731
|
+
delay: 0,
|
732
|
+
options: UIViewAnimationOptionCurveLinear,
|
733
|
+
opacity: 0.5) {
|
733
734
|
view.removeFromSuperview
|
734
735
|
}
|
735
736
|
|
@@ -737,6 +738,7 @@ view.move_to([0, 100]) # move to position 0, 100
|
|
737
738
|
view.delta_to([0, 100]) # move over 0, down 100, from current position
|
738
739
|
|
739
740
|
view.rotate_to Math::PI # rotate view upside down
|
741
|
+
view.rotate 45.degrees # rotate *an additional* 45 degrees
|
740
742
|
view.rotate_to(duration: 0.5, angle: 45.degrees) # using options
|
741
743
|
|
742
744
|
view.slide :left # slides the entire view one "page" to the left, right, up, or down
|
@@ -774,43 +776,77 @@ view.slide(:left, 20) {
|
|
774
776
|
}
|
775
777
|
```
|
776
778
|
|
777
|
-
Those be some gnarly callbacks. You can write this as a chain
|
778
|
-
tell the `slide` method to go ahead and run immediately (don't use an
|
779
|
-
animation). When you create an animation chain, the block you pass to each
|
780
|
-
iteration is the block that gets passed to `UIView##animateWithDuration(...)`.
|
781
|
-
If you try and run animations *within* that block they will not get queued up
|
782
|
-
properly.
|
779
|
+
Those be some gnarly callbacks. You can write this as a chain instead!
|
783
780
|
|
784
|
-
|
781
|
+
```ruby
|
782
|
+
UIView.animation_chain {
|
783
|
+
view.slide(:left, 20)
|
784
|
+
}.and_then {
|
785
|
+
view.slide(:up, 20)
|
786
|
+
}.and_then {
|
787
|
+
view.slide(:right, 20)
|
788
|
+
}.and_then {
|
789
|
+
view.slide(:down, 20)
|
790
|
+
}.and_then {
|
791
|
+
view.fade_out
|
792
|
+
}.start
|
793
|
+
```
|
785
794
|
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
in the future), you can use `chain: true`.
|
795
|
+
Behind the scenes, any calls to a SugarCube animate method (`slide`, `fade`,
|
796
|
+
`rotate`) will be setup to run *immediately* instead of in a
|
797
|
+
`UIView#animateWithDuration(...)` block. You can also do multiple animations
|
798
|
+
within that block, as long as no two animations affect the same property:
|
791
799
|
|
792
800
|
```ruby
|
793
801
|
UIView.animation_chain {
|
794
|
-
view.slide(:left,
|
802
|
+
view.slide(:left, 20)
|
803
|
+
view.rotate(90.degrees)
|
795
804
|
}.and_then {
|
796
|
-
view.slide(:up,
|
805
|
+
view.slide(:up, 20)
|
806
|
+
view.rotate(90.degrees)
|
797
807
|
}.and_then {
|
798
|
-
view.
|
799
|
-
|
808
|
+
view.slide(:right, 20)
|
809
|
+
view.rotate(90.degrees)
|
810
|
+
}.and_then {
|
811
|
+
view.slide(:down, 20)
|
812
|
+
view.rotate(90.degrees)
|
813
|
+
}.and_then {
|
814
|
+
view.fade_out
|
815
|
+
view.rotate_to(0.degrees)
|
816
|
+
}.start
|
800
817
|
```
|
801
818
|
|
802
819
|
Chains can also be written like this:
|
803
820
|
|
804
821
|
```ruby
|
805
822
|
chain = UIView.animation_chain
|
806
|
-
chain << proc { view.slide(:left, 20) }
|
807
|
-
chain << proc { view.slide(:up, 20) }
|
808
|
-
chain << proc { view.slide(:right, 20) }
|
809
|
-
chain << proc { view.slide(:down, 20) }
|
823
|
+
chain << proc { view.slide(:left, 20, chain: true) }
|
824
|
+
chain << proc { view.slide(:up, 20, chain: true) }
|
825
|
+
chain << proc { view.slide(:right, 20, chain: true) }
|
826
|
+
chain << proc { view.slide(:down, 20, chain: true) }
|
810
827
|
chain << proc { view.fade_out }
|
811
828
|
chain.start
|
812
829
|
```
|
813
830
|
|
831
|
+
**AND** chains can be looped! Either number of times, or call `stop` on the
|
832
|
+
chain.
|
833
|
+
|
834
|
+
```ruby
|
835
|
+
chain = UIView.animation_chain {
|
836
|
+
view.slide(:left, 20)
|
837
|
+
}.and_then {
|
838
|
+
view.slide(:right, 20)
|
839
|
+
}.loop # loop forever
|
840
|
+
2.seconds.later { chain.stop } # the animation will complete, but not loop again
|
841
|
+
chain.loop(10) # would loop 10 times
|
842
|
+
|
843
|
+
# if you're impatient
|
844
|
+
chain.abort
|
845
|
+
# will stop the animation at the end of whatever block it is in, so it could be
|
846
|
+
# in a strange position, depending on where in the chain it is. better to call
|
847
|
+
# `stop`
|
848
|
+
```
|
849
|
+
|
814
850
|
##### View factories
|
815
851
|
|
816
852
|
###### UIButton
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module SugarCube
|
2
2
|
class AnimationChain
|
3
|
+
|
3
4
|
class << self
|
4
5
|
|
5
6
|
def chains
|
@@ -7,17 +8,17 @@ module SugarCube
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def start_chain(chain)
|
10
|
-
chains << chain
|
11
|
+
chains << chain unless chains.include?(chain)
|
11
12
|
end
|
12
13
|
|
13
14
|
def stop_chain(chain)
|
14
|
-
chains
|
15
|
-
@chains.delete(chain)
|
15
|
+
chains.delete(chain)
|
16
16
|
end
|
17
17
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def initialize
|
21
|
+
raise "animation chains cannot be nested" if Thread.current[:sugarcube_chaining]
|
21
22
|
@blocks = []
|
22
23
|
end
|
23
24
|
|
@@ -44,21 +45,57 @@ module SugarCube
|
|
44
45
|
|
45
46
|
options, block = @blocks[@block_index]
|
46
47
|
@after_block = ->(completed){
|
47
|
-
|
48
|
+
if @abort || ! self.do_next
|
49
|
+
@running = false
|
50
|
+
if @loop
|
51
|
+
start
|
52
|
+
else
|
53
|
+
AnimationChain.stop_chain(self)
|
54
|
+
end
|
55
|
+
end
|
48
56
|
}
|
49
57
|
options[:after] = @after_block
|
50
58
|
|
51
59
|
UIView.animate(options) {
|
60
|
+
Thread.current[:sugarcube_chaining] = true
|
52
61
|
block.call
|
62
|
+
Thread.current[:sugarcube_chaining] = nil
|
53
63
|
@block_index += 1
|
54
64
|
}
|
55
65
|
true
|
56
66
|
end
|
57
67
|
|
58
68
|
def start
|
69
|
+
return if @running
|
59
70
|
AnimationChain.start_chain(self)
|
71
|
+
@running = true
|
72
|
+
@abort = nil
|
60
73
|
@block_index = 0
|
74
|
+
if Fixnum === @loop
|
75
|
+
@loop -= 1
|
76
|
+
@loop = nil if @loop == 0
|
77
|
+
end
|
61
78
|
do_next
|
79
|
+
return self
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param times [Fixnum,nil] number of times to loop, or any other truthy value to loop forever
|
83
|
+
def loop(times=true)
|
84
|
+
@loop = times
|
85
|
+
start
|
86
|
+
end
|
87
|
+
|
88
|
+
# Cancels a loop, but lets the chain finish
|
89
|
+
def stop
|
90
|
+
@loop = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# stops the animation immediately
|
94
|
+
def abort
|
95
|
+
return unless @running
|
96
|
+
@loop = nil
|
97
|
+
@abort = true
|
98
|
+
@running = false
|
62
99
|
end
|
63
100
|
|
64
101
|
end
|
data/lib/sugarcube/uiview.rb
CHANGED
@@ -34,9 +34,10 @@ class UIView
|
|
34
34
|
|
35
35
|
# chain: true is used inside animation_chain blocks to prevent some weird
|
36
36
|
# animation errors (nested animations do not delay/queue as you'd expect)
|
37
|
-
if options[:chain]
|
37
|
+
if options[:chain] || Thread.current[:sugarcube_chaining]
|
38
38
|
duration = 0
|
39
39
|
delay = 0
|
40
|
+
raise "Completion blocks cannot be used within an animation_chain block" if options[:after]
|
40
41
|
end
|
41
42
|
|
42
43
|
after_animations = options[:after]
|
@@ -56,7 +57,7 @@ class UIView
|
|
56
57
|
else
|
57
58
|
UIView.animateWithDuration( duration,
|
58
59
|
delay: delay,
|
59
|
-
options: options[:options] || UIViewAnimationOptionCurveEaseInOut,
|
60
|
+
options: options[:options] || (UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionBeginFromCurrentState),
|
60
61
|
animations: animations,
|
61
62
|
completion: after_adjusted
|
62
63
|
)
|
@@ -225,6 +226,8 @@ class UIView
|
|
225
226
|
self
|
226
227
|
end
|
227
228
|
|
229
|
+
# Changes the current rotation to `new_angle`
|
230
|
+
# (`rotate` rotates relative to the current rotation)
|
228
231
|
def rotate_to(options={}, &after)
|
229
232
|
if options.is_a? Numeric
|
230
233
|
options = { angle: options }
|
@@ -237,6 +240,21 @@ class UIView
|
|
237
240
|
}
|
238
241
|
end
|
239
242
|
|
243
|
+
# Changes the current rotation by `new_angle`
|
244
|
+
# (`rotate` rotates to a specific angle)
|
245
|
+
def rotate(options={}, &after)
|
246
|
+
if options.is_a? Numeric
|
247
|
+
new_angle = options
|
248
|
+
options = {}
|
249
|
+
else
|
250
|
+
new_angle = options[:angle]
|
251
|
+
end
|
252
|
+
|
253
|
+
old_angle = valueForKeyPath('layer.transform.rotation.z')
|
254
|
+
options[:angle] = old_angle + new_angle
|
255
|
+
rotate_to(options, &after)
|
256
|
+
end
|
257
|
+
|
240
258
|
def slide(direction, options={}, more_options=nil, &after)
|
241
259
|
if options.is_a? Numeric
|
242
260
|
size = options
|
@@ -312,7 +330,7 @@ class UIView
|
|
312
330
|
end
|
313
331
|
|
314
332
|
options[:duration] ||= default_duration
|
315
|
-
options[:options] ||= UIViewAnimationOptionCurveEaseIn
|
333
|
+
options[:options] ||= UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionBeginFromCurrentState
|
316
334
|
reset_transform = self.transform
|
317
335
|
reset_after = ->(finished) {
|
318
336
|
self.transform = reset_transform
|
data/lib/sugarcube/version.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
describe "SugarCube::AnimationChain" do
|
2
2
|
tests SugarCube::AnimationChainController
|
3
3
|
|
4
|
-
it "should have a view" do
|
5
|
-
controller.view.should != nil
|
6
|
-
end
|
7
|
-
|
8
4
|
it "should support chains" do
|
9
5
|
SugarCube::AnimationChain.chains.length.should == 0
|
10
6
|
@variable_a = nil
|
@@ -73,4 +69,72 @@ describe "SugarCube::AnimationChain" do
|
|
73
69
|
}
|
74
70
|
end
|
75
71
|
|
72
|
+
it "should support looping" do
|
73
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
74
|
+
@variable_a = 0
|
75
|
+
@num_loops = 2
|
76
|
+
UIView.animation_chain(duration:0.1){
|
77
|
+
@variable_a += 1
|
78
|
+
}.loop(@num_loops)
|
79
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
80
|
+
|
81
|
+
wait 0.3 {
|
82
|
+
@variable_a.should == @num_loops
|
83
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should support stopping" do
|
88
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
89
|
+
@variable_a = 0
|
90
|
+
@num_loops = 0
|
91
|
+
@chain = UIView.animation_chain(duration:0.1){
|
92
|
+
@variable_a += 1
|
93
|
+
f = controller.view.frame
|
94
|
+
f.origin.x -= 20
|
95
|
+
controller.view.frame = f
|
96
|
+
}.loop
|
97
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
98
|
+
|
99
|
+
wait 0.2 {
|
100
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
101
|
+
@variable_a.should > 1
|
102
|
+
@chain.stop
|
103
|
+
}
|
104
|
+
|
105
|
+
wait 0.4 {
|
106
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
107
|
+
@variable_a.should < 4
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should support aborting" do
|
112
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
113
|
+
@variable_a = 0
|
114
|
+
@num_loops = 0
|
115
|
+
@chain = UIView.animation_chain(duration:0.1){
|
116
|
+
@variable_a += 1
|
117
|
+
f = controller.view.frame
|
118
|
+
f.origin.x -= 20
|
119
|
+
controller.view.frame = f
|
120
|
+
}.loop
|
121
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
122
|
+
|
123
|
+
wait 0.21 {
|
124
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
125
|
+
@variable_a.should == 2
|
126
|
+
}
|
127
|
+
|
128
|
+
wait 0.31 {
|
129
|
+
@chain.abort
|
130
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
131
|
+
@variable_a.should > 1
|
132
|
+
@variable_a.should < 4
|
133
|
+
@num_loops = @variable_a
|
134
|
+
}
|
135
|
+
wait 0.51 {
|
136
|
+
@variable_a.should == @num_loops
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
76
140
|
end
|
@@ -8,12 +8,20 @@ describe "UIView animation methods" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should rotate 45 degrees' do
|
11
|
-
angle = 45
|
11
|
+
angle = 45.degrees
|
12
12
|
@view.rotate_to(angle)
|
13
13
|
current_angle = Math.atan2(@view.transform.b, @view.transform.a)
|
14
14
|
current_angle.should == angle
|
15
15
|
end
|
16
16
|
|
17
|
+
it 'should rotate 45 degrees and then 45 degrees again' do
|
18
|
+
angle = 45.degrees
|
19
|
+
@view.rotate_to(angle)
|
20
|
+
@view.rotate(angle)
|
21
|
+
current_angle = Math.atan2(@view.transform.b, @view.transform.a)
|
22
|
+
current_angle.should == 90.degrees
|
23
|
+
end
|
24
|
+
|
17
25
|
it 'should animate anything' do
|
18
26
|
UIView.animate {
|
19
27
|
@view.frame = [[0, 0], [0, 0]]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sugarcube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.16
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-02-
|
16
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
17
17
|
dependencies: []
|
18
18
|
description: ! '== Description
|
19
19
|
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- runtests
|
124
124
|
- spec/568_spec.rb
|
125
125
|
- spec/activesupport_spec.rb
|
126
|
+
- spec/animation_chain_spec.rb
|
126
127
|
- spec/calayer_spec.rb
|
127
128
|
- spec/core_graphics_spec.rb
|
128
129
|
- spec/core_location_spec.rb
|
@@ -147,7 +148,6 @@ files:
|
|
147
148
|
- spec/uicolor_spec.rb
|
148
149
|
- spec/uiimage_color_at_spec.rb
|
149
150
|
- spec/uiimage_scale_spec.rb
|
150
|
-
- spec/uiview_animation_chain_spec.rb
|
151
151
|
- spec/uiview_animation_spec.rb
|
152
152
|
- spec/uiview_attr_updates_spec.rb
|
153
153
|
- spec/uiview_spec.rb
|
@@ -181,6 +181,7 @@ summary: Extensions for Ruby to make Rubymotion development more enjoyable, and
|
|
181
181
|
test_files:
|
182
182
|
- spec/568_spec.rb
|
183
183
|
- spec/activesupport_spec.rb
|
184
|
+
- spec/animation_chain_spec.rb
|
184
185
|
- spec/calayer_spec.rb
|
185
186
|
- spec/core_graphics_spec.rb
|
186
187
|
- spec/core_location_spec.rb
|
@@ -205,9 +206,7 @@ test_files:
|
|
205
206
|
- spec/uicolor_spec.rb
|
206
207
|
- spec/uiimage_color_at_spec.rb
|
207
208
|
- spec/uiimage_scale_spec.rb
|
208
|
-
- spec/uiview_animation_chain_spec.rb
|
209
209
|
- spec/uiview_animation_spec.rb
|
210
210
|
- spec/uiview_attr_updates_spec.rb
|
211
211
|
- spec/uiview_spec.rb
|
212
212
|
- spec/unholy_spec.rb
|
213
|
-
has_rdoc:
|