1 August 2019
Angular (47) -- Angular Animations
by Jerry Zhang
LeetCode Day 27: P189. Rotate Array (Easy)
题目:
给一个整数数组和一个正整数k,把这个数组向右平移k步。
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
思路:
方法应该很多,我想的办法是每个数找到正确的位置后,挤掉另一个,然后被挤掉的那个数再去找它的正确位置,去挤另一个。这样不会产生新的 空间,而且n步就可以完成。至少也需要n步。
这个算法是错误的,第一次试验成功是因为数组长度是7,恰好能轮换到所有的数,如果数组长度是6,右移两步,就会重复了。
看了下答案,最省事的是新开一个数组,当然这个我早也想到了,新开空间就没意思了。。。
public class E_189_RotateArray {
public static void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
int[] clone = nums.clone();
for (int i = 0; i < n; i++) {
nums[i] = clone[(i + n - k) % n];
}
}
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6};
rotate(nums, 2);
System.out.println(Arrays.toString(nums));
}
}
大多in-place的解法是反转。先把整个数组反转,再根据k的值切成两部分,把第一部分反转,再把第二部分反转。
最优解:
public class E_189_RotateArray {
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length-1); // reverse the whole array
reverse(nums, 0, k-1); // reverse the first part
reverse(nums, k, nums.length-1); // reverse the second part
}
public void reverse(int[] nums, int l, int r) {
while (l < r) {
int tmp = nums[l];
nums[l++] = nums[r];
nums[r--] = tmp;
}
}
}
Angular: Animations
The “void” State
Sometimes we do not have an element in the dom and add it later. To represent the “no element” state, we can use void
.
trigger('list1', [
state('in', style({
opacity: 1,
transform: 'translateX(0)'
})),
transition('void => *', [
style({
opacity: 0,
transform: 'translateX(-100px)'
}),
animate(300)
]),
transition('* => void', [
animate(300, style({
transform: 'translateX(100px)',
opacity: 0
}))
])
])
We define a state in
as the final state when we add an item. Then we define a transition from void to *
, which
includes two steps. The first step is a state with a 0 opacity. The second step is just an animate of 0.3 second for
transiting from the void
state to the in
state.
For the animation of deleting an item, we define another transition from any thing to void. In this transition, only a final animation is defined.
Using Keyframes for Animation
During the transition, we can set time points in a keyframes to explicitly separate the time pieces for each state.
- Use the keyframes function.
transition('void => *', [
animate(1000, keyframes([
style({
transform: 'translateX(-100px)',
opacity: 0,
offset: 0
}),
style({
transform: 'translateX(-50px)',
opacity: 0.5,
offset: 0.3
}),
style({
transform: 'translateX(-20px)',
opacity: 1,
offset: 0.8
}),
style({
transform: 'translateX(0px)',
opacity: 1,
offset: 1
})
]))
Grouping Transitions
If you want two different style at the same time but with different timings, so that you do not wait for one
animation to finish before starting the next. We can use the group
method. In the method, all the animations happen
at the same time.
transition('* => void', [
group([
animate(300, style({
color: 'red'
})),
animate(800, style({
transform: 'translateX(100px)',
opacity: 0
}))
])
])
Animation Callbacks
There are some callback functions we can use, so that after an animation finished, we can execute some other code.
<div
style="width: 100px; height: 100px;"
[@divState]="state"
(@divState.start)="animationStarted($event)"
(@divState.done)="animationEnded($event)"
>
animationStarted($event) {
console.log($event);
}
animationEnded($event) {
console.log($event);
}