/* * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.litho.animation; import com.facebook.litho.dataflow.ConstantNode; import com.facebook.litho.dataflow.SpringNode; import com.facebook.litho.dataflow.ValueNode; import com.facebook.litho.internal.ArraySet; /** * Animation for the transition of the position of a mount item on a quadratic Bezier curve. */ public class BezierTransition extends TransitionAnimationBinding { private final ComponentProperty mXProperty; private final ComponentProperty mYProperty; private final float mControlX; private final float mControlY; /** * Creates a quadratic Bezier transition. The control x/y are used to configure the curve: see * {@link Animated.BezierBuilder#controlPoint} for more information on the units of controlX/Y. */ public BezierTransition( ComponentProperty xProperty, ComponentProperty yProperty, float controlX, float controlY) { mXProperty = xProperty; mYProperty = yProperty; mControlX = controlX; mControlY = controlY; } @Override public void collectTransitioningProperties(ArraySet<ComponentProperty> outSet) { outSet.add(mXProperty); outSet.add(mYProperty); } @Override protected void setupBinding(Resolver resolver) { final float startX = resolver.getCurrentState(mXProperty); final float endX = resolver.getEndState(mXProperty); final float startY = resolver.getCurrentState(mYProperty); final float endY = resolver.getEndState(mYProperty); final float controlX = (endX - startX) * mControlX + startX; final float controlY = (endY - startY) * mControlY + startY; SpringNode springNode = new SpringNode(); BezierNode xBezierNode = new BezierNode(startX, endX, controlX); BezierNode yBezierNode = new BezierNode(startY, endY, controlY); addBinding(new ConstantNode(0f), springNode, SpringNode.INITIAL_INPUT); addBinding(new ConstantNode(1f), springNode, SpringNode.END_INPUT); addBinding(springNode, xBezierNode); addBinding(springNode, yBezierNode); addBinding(xBezierNode, resolver.getAnimatedPropertyNode(mXProperty)); addBinding(yBezierNode, resolver.getAnimatedPropertyNode(mYProperty)); } private static class BezierNode extends ValueNode { private final float mInitial; private final float mEnd; private final float mControlPoint; public BezierNode(float initial, float end, float controlPoint) { mInitial = initial; mEnd = end; mControlPoint = controlPoint; } @Override protected float calculateValue(long frameTimeNanos) { float t = getInput().getValue(); // Bezier math from Wikipedia: https://goo.gl/MvrMei return (1 - t) * (1 - t) * mInitial + 2 * t * (1 - t) * mControlPoint + t * t * mEnd; } } }