Skip to content

Commit

Permalink
+
Browse files Browse the repository at this point in the history
  • Loading branch information
xvrh committed Nov 21, 2023
1 parent c7edba4 commit d206b39
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.0.0-alpha.2
- Implement auto-orient
- Require Flutter 3.16

## 3.0.0-alpha.1
- Add `enableRenderCache` parameter.

Expand Down
1 change: 1 addition & 0 deletions example/assets/Tests/AutoOrient.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"5.12.1","fr":29.9700012207031,"ip":0,"op":284.000011567557,"w":400,"h":400,"nm":"ao","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"shape","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.641,"y":0.641},"o":{"x":0.167,"y":0.167},"t":0,"s":[68.5,44.5,0],"to":[2.395,1.173,0],"ti":[-52,-114,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.438,"y":0.438},"t":83.533,"s":[304.5,148.5,0],"to":[-8,108,0],"ti":[-2.164,-1.328,0]},{"i":{"x":0.575,"y":0.575},"o":{"x":0.167,"y":0.167},"t":114,"s":[340.035,204.247,0],"to":[60.399,77.002,0],"ti":[118,-2,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.407,"y":0.407},"t":189.251,"s":[240.5,270.5,0],"to":[-118,2,0],"ti":[52.68,50.729,0]},{"t":283.000011526826,"s":[14.5,222.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":1,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-172.23,-7.099],[-161.73,29.401],[-73.23,-21.099]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[54.125,22.142],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":284.000011567557,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}}
28 changes: 28 additions & 0 deletions lib/src/animation/keyframe/transform_keyframe_animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TransformKeyframeAnimation {
_position = animatableTransform.position?.createAnimation(),
_scale = animatableTransform.scale?.createAnimation(),
_rotation = animatableTransform.rotation?.createAnimation(),
_autoOrient = animatableTransform.isAutoOrient(),
_skew = animatableTransform.skew?.createAnimation(),
_skewAngle = animatableTransform.skewAngle?.createAnimation(),
_opacity = animatableTransform.opacity?.createAnimation(),
Expand Down Expand Up @@ -50,6 +51,8 @@ class TransformKeyframeAnimation {
BaseKeyframeAnimation<double, double>? _endOpacity;
BaseKeyframeAnimation<double, double>? get endOpacity => _endOpacity;

final bool _autoOrient;

void addAnimationsToLayer(BaseLayer layer) {
layer.addAnimation(_opacity);
layer.addAnimation(_startOpacity);
Expand Down Expand Up @@ -103,6 +106,31 @@ class TransformKeyframeAnimation {
_matrix.rotateZ(rotation * pi / 180.0);
}
}
// If autoOrient is true, the rotation should follow the derivative of the position rather
// than the rotation property.
if (_autoOrient) {
if (_position case var position?) {
var currentProgress = position.progress;
var startPosition = position.value;
// Store the start X and Y values because the pointF will be overwritten by the next getValue call.
var startX = startPosition.dx;
var startY = startPosition.dy;
// 1) Find the next position value.
// 2) Create a vector from the current position to the next position.
// 3) Find the angle of that vector to the X axis (0 degrees).
position.setProgress(currentProgress + 0.0001);
var nextPosition = position.value;
position.setProgress(currentProgress);
var rotationValue = degrees(
atan2(nextPosition.dy - startY, nextPosition.dx - startX));
_matrix.rotateZ(rotationValue);
}
} else {
final rotation = _rotation!.value;
if (rotation != 0) {
_matrix.rotateZ(rotation * pi / 180.0);
}
}

if (_skew != null) {
final mCos =
Expand Down
2 changes: 2 additions & 0 deletions lib/src/model/animatable/animatable_transform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class AnimatableTransform implements ModifierContent, ContentModel {

final AnimatableDoubleValue? endOpacity;

bool isAutoOrient = false;

AnimatableTransform(
{this.anchorPoint,
this.position,
Expand Down
56 changes: 56 additions & 0 deletions lib/src/model/content/layer_blend.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@


import 'dart:ui';

enum LBlendMode {
normal,
multiply,
screen,
overlay,
darken,
lighten,
colorDodge,
colorBurn,
hardlight,
softLight,
difference,
exclusion,
hue,
saturation,
color,
luminosity,
add,
hardMix,
;

BlendMode? toNativeBlendMode() {
return switch (this) {
normal => null,
screen => BlendMode.screen,
return BlendModeCompat.SCREEN;
case OVERLAY:
return BlendModeCompat.OVERLAY;
case DARKEN:
return BlendModeCompat.DARKEN;
case LIGHTEN:
return BlendModeCompat.LIGHTEN;
case ADD:
return BlendModeCompat.PLUS;
case MULTIPLY:
case COLOR_DODGE:
case COLOR_BURN:
case HARD_LIGHT:
case SOFT_LIGHT:
case DIFFERENCE:
case EXCLUSION:
case HUE:
case SATURATION:
case COLOR:
case LUMINOSITY:
case HARD_MIX:
default:
return null;
}
}

}
59 changes: 40 additions & 19 deletions lib/src/parser/layer_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,34 @@ class LayerParser {
'op', // 19
'tm', // 20
'cl', // 21
'hd' // 22
'hd', // 22
'ao', // 23
'bm', // 24
]);

static Layer parse(LottieComposition composition) {
var bounds = composition.bounds;
return Layer(
shapes: <ContentModel>[],
composition: composition,
name: '__container',
id: -1,
layerType: LayerType.preComp,
parentId: -1,
masks: <Mask>[],
transform: AnimatableTransform(),
solidWidth: 0,
solidHeight: 0,
solidColor: const Color(0x00000000),
timeStretch: 0,
startFrame: 0,
preCompWidth: bounds.width,
preCompHeight: bounds.height,
inOutKeyframes: <Keyframe<double>>[],
matteType: MatteType.none,
isHidden: false);
shapes: <ContentModel>[],
composition: composition,
name: '__container',
id: -1,
layerType: LayerType.preComp,
parentId: -1,
masks: <Mask>[],
transform: AnimatableTransform(),
solidWidth: 0,
solidHeight: 0,
solidColor: const Color(0x00000000),
timeStretch: 0,
startFrame: 0,
preCompWidth: bounds.width,
preCompHeight: bounds.height,
inOutKeyframes: <Keyframe<double>>[],
matteType: MatteType.none,
isHidden: false,
blendMode: LayerBlend.normal,
);
}

static final JsonReaderOptions _textNames = JsonReaderOptions.of(['d', 'a']);
Expand Down Expand Up @@ -98,8 +102,10 @@ class LayerParser {
var hidden = false;
BlurEffect? blurEffect;
DropShadowEffect? dropShadowEffect;
var autoOrient = false;

var matteType = MatteType.none;
LayerBlend blendMode = LayerBlend.normal;
AnimatableTransform? transform;
AnimatableTextFrame? text;
AnimatableTextProperties? textProperties;
Expand Down Expand Up @@ -235,6 +241,16 @@ class LayerParser {
cl = reader.nextString();
case 22:
hidden = reader.nextBoolean();
case 23:
autoOrient = reader.nextInt() == 1;
case 24:
int blendModeIndex = reader.nextInt();
if (blendModeIndex >= LayerBlend.values.length) {
composition.addWarning('Unsupported Blend Mode: $blendModeIndex');
blendMode = LayerBlend.normal;
break;
}
blendMode = LayerBlend.values[blendModeIndex];
default:
reader.skipName();
reader.skipValue();
Expand Down Expand Up @@ -269,6 +285,10 @@ class LayerParser {
composition
.addWarning('Convert your Illustrator layers to shape layers.');
}
if (autoOrient) {
transform ??= AnimatableTransform();
transform.isAutoOrient = autoOrient;
}

return Layer(
shapes: shapes,
Expand All @@ -295,6 +315,7 @@ class LayerParser {
isHidden: hidden,
blurEffect: blurEffect,
dropShadowEffect: dropShadowEffect,
blendMode: blendMode,
);
}
}

0 comments on commit d206b39

Please sign in to comment.