Skip to content

Commit 500a4f8

Browse files
committed
fixes #51. animate differences in fill/stroke color properties
1 parent 0dabb5f commit 500a4f8

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-23
lines changed

src/app/scripts/animation/AvdTarget.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
/**
22
* The names of the currently supported animatable properties.
33
*/
4-
export type PropertyName = 'pathData' | 'rotation';
4+
export type PropertyName =
5+
'pathData'
6+
| 'rotation'
7+
| 'fillColor'
8+
| 'strokeColor'
9+
| 'fillAlpha'
10+
| 'strokeAlpha'
11+
| 'strokeWidth';
512

613
/**
714
* The currently supported animatable value types.
815
*/
9-
export type ValueType = 'pathType' | 'floatType';
16+
export type ValueType = 'pathType' | 'floatType' | 'colorType';
1017

1118
/**
1219
* An AvdTarget assigns a group of animations to a particular layer in the vector.
1320
*/
1421
export class AvdTarget {
1522
constructor(
1623
public readonly layerId: string,
17-
public readonly animation: AvdAnimation) { }
24+
public readonly animations: AvdAnimation[]) { }
1825
}
1926

2027
/**

src/app/scripts/parsers/AvdSerializer.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,29 @@ export function vectorLayerAnimationToAvdXmlString(
4747
animationNode.setAttribute('name', 'android:animation');
4848
targetNode.appendChild(animationNode);
4949

50-
const animation = target.animation;
51-
const animatorNode = xmlDoc.createElement('objectAnimator');
52-
animatorNode.setAttributeNS(XMLNS_NS, 'xmlns:android', ANDROID_NS);
53-
animatorNode.setAttributeNS(ANDROID_NS, 'android:name', layerId);
54-
animatorNode.setAttributeNS(ANDROID_NS, 'android:propertyName', animation.propertyName);
55-
conditionalAttr(animatorNode, 'android:duration', animation.duration);
56-
conditionalAttr(animatorNode, 'android:valueFrom', animation.valueFrom);
57-
conditionalAttr(animatorNode, 'android:valueTo', animation.valueTo);
58-
conditionalAttr(animatorNode, 'android:valueType', animation.valueType);
59-
conditionalAttr(animatorNode, 'android:interpolator', animation.interpolator);
60-
animationNode.appendChild(animatorNode);
50+
const animations = target.animations;
51+
let animationContainerNode = animationNode;
52+
if (animations.length > 1) {
53+
// <set> for multiple property animations on a single layer
54+
animationContainerNode = xmlDoc.createElement('set');
55+
animationContainerNode.setAttributeNS(XMLNS_NS, 'xmlns:android', ANDROID_NS);
56+
animationNode.appendChild(animationContainerNode);
57+
}
58+
59+
for (const animation of animations) {
60+
const animatorNode = xmlDoc.createElement('objectAnimator');
61+
if (animations.length === 1) {
62+
animatorNode.setAttributeNS(XMLNS_NS, 'xmlns:android', ANDROID_NS);
63+
}
64+
animatorNode.setAttributeNS(XMLNS_NS, 'xmlns:android', ANDROID_NS);
65+
animatorNode.setAttributeNS(ANDROID_NS, 'android:propertyName', animation.propertyName);
66+
conditionalAttr(animatorNode, 'android:duration', animation.duration);
67+
conditionalAttr(animatorNode, 'android:valueFrom', animation.valueFrom);
68+
conditionalAttr(animatorNode, 'android:valueTo', animation.valueTo);
69+
conditionalAttr(animatorNode, 'android:valueType', animation.valueType);
70+
conditionalAttr(animatorNode, 'android:interpolator', animation.interpolator);
71+
animationContainerNode.appendChild(animatorNode);
72+
}
6173
}
6274

6375
return serializeXmlNode(rootNode);

src/app/toolbar/toolbar.component.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Component, OnInit, ViewContainerRef } from '@angular/core';
44
import { LayerStateService, MorphabilityStatus } from '../services';
55
import { CanvasType } from '../CanvasType';
66
import { AvdSerializer, SvgSerializer } from '../scripts/parsers';
7-
import { AvdTarget, AvdAnimation } from '../scripts/animation';
7+
import { AvdTarget, AvdAnimation, ValueType, PropertyName } from '../scripts/animation';
88
import { DialogService } from '../dialogs';
99
import { AutoAwesome } from '../scripts/commands';
1010
import { AnimatorService } from '../services/animator.service';
@@ -142,13 +142,13 @@ export class ToolbarComponent implements OnInit {
142142
const duration = this.animatorService.getDuration();
143143
const interpolator = this.animatorService.getInterpolator();
144144
return new AvdTarget(startLayer.id,
145-
new AvdAnimation(
145+
[new AvdAnimation(
146146
fromValue.toString(),
147147
toValue.toString(),
148148
duration,
149149
interpolator.androidRef,
150150
'rotation',
151-
'floatType'));
151+
'floatType')]);
152152
}
153153

154154
private createPathAvdTarget() {
@@ -158,14 +158,40 @@ export class ToolbarComponent implements OnInit {
158158
const toValue = endLayer.pathData.getPathString();
159159
const duration = this.animatorService.getDuration();
160160
const interpolator = this.animatorService.getInterpolator();
161-
return new AvdTarget(startLayer.id,
162-
new AvdAnimation(
163-
fromValue,
164-
toValue,
165-
duration,
166-
interpolator.androidRef,
161+
const createAvdAnimation = (from: string, to: string, propertyName: PropertyName, valueType: ValueType) => {
162+
return new AvdAnimation(from, to, duration, interpolator.androidRef, propertyName, valueType);
163+
};
164+
const avdAnimations: AvdAnimation[] = [];
165+
avdAnimations.push(
166+
createAvdAnimation(
167+
startLayer.pathData.getPathString(),
168+
endLayer.pathData.getPathString(),
167169
'pathData',
168170
'pathType'));
171+
if (startLayer.fillColor && endLayer.fillColor && startLayer.fillColor !== endLayer.fillColor) {
172+
avdAnimations.push(
173+
createAvdAnimation(startLayer.fillColor, endLayer.fillColor, 'fillColor', 'colorType'));
174+
}
175+
if (startLayer.strokeColor && endLayer.strokeColor && startLayer.strokeColor !== endLayer.strokeColor) {
176+
avdAnimations.push(
177+
createAvdAnimation(startLayer.strokeColor, endLayer.strokeColor, 'strokeColor', 'colorType'));
178+
}
179+
if (startLayer.fillAlpha !== endLayer.fillAlpha) {
180+
avdAnimations.push(
181+
createAvdAnimation(
182+
startLayer.fillAlpha.toString(), endLayer.fillAlpha.toString(), 'fillAlpha', 'floatType'));
183+
}
184+
if (startLayer.strokeAlpha !== endLayer.strokeAlpha) {
185+
avdAnimations.push(
186+
createAvdAnimation(
187+
startLayer.strokeAlpha.toString(), endLayer.strokeAlpha.toString(), 'strokeAlpha', 'floatType'));
188+
}
189+
if (startLayer.strokeWidth !== endLayer.strokeWidth) {
190+
avdAnimations.push(
191+
createAvdAnimation(
192+
startLayer.strokeWidth.toString(), endLayer.strokeWidth.toString(), 'strokeWidth', 'floatType'));
193+
}
194+
return new AvdTarget(startLayer.id, avdAnimations);
169195
}
170196

171197
onDemoClick() {

0 commit comments

Comments
 (0)