static void InsertVisibilityVisualIntoTransformChain( TranslationContext context, float inProgress, float outProgress, ref ContainerVisual root) { // Implement the Visibility for the layer. Only needed if the layer becomes visible after // the LottieComposition's in point, or it becomes invisible before the LottieComposition's out point. if (inProgress > 0 || outProgress < 1) { // Insert a new node to control visibility at the top of the chain. var visibilityNode = context.ObjectFactory.CreateContainerVisual(); visibilityNode.Children.Add(root); root = visibilityNode; var visibilityAnimation = context.ObjectFactory.CreateBooleanKeyFrameAnimation(); if (inProgress > 0) { // Set initial value to be non-visible. visibilityNode.IsVisible = false; visibilityAnimation.InsertKeyFrame(inProgress, true); } if (outProgress < 1) { visibilityAnimation.InsertKeyFrame(outProgress, false); } visibilityAnimation.Duration = context.LottieComposition.Duration; Animate.WithKeyFrame(context, visibilityNode, "IsVisible", visibilityAnimation); } }
public static bool TryCreateContainerShapeTransformChain( LayerContext context, out CompositionContainerShape rootNode, out CompositionContainerShape contentsNode) { // Create containers for the contents in the layer. // The rootNode is the root for the layer. It may be the same object // as the contentsNode if there are no inherited transforms and no visibility animation. // // +---------------+ // | ... | // +---------------+ // ^ // | // +-----------------+ // | visiblityNode |-- Optional visiblity node (only used if the visiblity is animated) // +-----------------+ // ^ // | // +-------------------+ // | rootTransformNode |--Transform (values are inherited from root ancestor of the transform tree) // +-------------------+ // ^ // | // + - - - - - - - - - - - - + // | other transforms nodes |--Transform (values inherited from the transform tree) // + - - - - - - - - - - - - + // ^ // | // +-------------------+ // | leafTransformNode |--Transform defined on the layer // +-------------------+ // ^ ^ // | | // +---------+ +---------+ // | content | | content | ... // +---------+ +---------+ // // Get the opacity of the layer. var layerOpacity = Optimizer.TrimAnimatable(context, context.Layer.Transform.Opacity); // Convert the layer's in point and out point into absolute progress (0..1) values. var inProgress = context.InPointAsProgress; var outProgress = context.OutPointAsProgress; if (inProgress > 1 || outProgress <= 0 || inProgress >= outProgress || layerOpacity.IsAlways(LottieData.Opacity.Transparent)) { // The layer is never visible. Don't create anything. rootNode = null; contentsNode = null; return(false); } // Create the transforms chain. TranslateTransformOnContainerShapeForLayer(context, context.Layer, out var transformsRoot, out contentsNode); // Implement the Visibility for the layer. Only needed if the layer becomes visible after // the LottieComposition's in point, or it becomes invisible before the LottieComposition's out point. if (inProgress > 0 || outProgress < 1) { // Create a node to control visibility. var visibilityNode = context.ObjectFactory.CreateContainerShape(); visibilityNode.Shapes.Add(transformsRoot); rootNode = visibilityNode; visibilityNode.SetDescription(context, () => $"Layer: {context.Layer.Name}"); // Animate between Scale(0,0) and Scale(1,1). var visibilityAnimation = context.ObjectFactory.CreateVector2KeyFrameAnimation(); visibilityAnimation.SetName("ShapeVisibilityAnimation"); if (inProgress > 0) { // Set initial value to be non-visible (default is visible). visibilityNode.Scale = Sn.Vector2.Zero; visibilityAnimation.InsertKeyFrame(inProgress, Sn.Vector2.One, context.ObjectFactory.CreateHoldThenStepEasingFunction()); } if (outProgress < 1) { visibilityAnimation.InsertKeyFrame(outProgress, Sn.Vector2.Zero, context.ObjectFactory.CreateHoldThenStepEasingFunction()); } visibilityAnimation.Duration = context.Translation.LottieComposition.Duration; Animate.WithKeyFrame(context, visibilityNode, nameof(visibilityNode.Scale), visibilityAnimation); } else { rootNode = transformsRoot; } return(true); }