首页 > 代码库 > AnimationTask分析

AnimationTask分析

class ComponentAnimator::AnimationTask
{
public:
    AnimationTask (Componentcnoexcept  : component (c) {}
    void reset (const Rectangle<int>& finalBounds,
                float finalAlpha,
                int   millisecondsToSpendMoving,
                bool  useProxyComponent,
                double startSpddouble endSpd)
    {
        msElapsed = 0;
        msTotal = jmax (1, millisecondsToSpendMoving);
        lastProgress = 0;
        destination = finalBounds;
        destAlpha = finalAlpha;
        isMoving = (finalBounds != component->getBounds());
        isChangingAlpha = (finalAlpha != component->getAlpha());
        left    = component->getX();
        top     = component->getY();
        right   = component->getRight();
        bottom  = component->getBottom();
        alpha   = component->getAlpha();
        const double invTotalDistance = 4.0 / (startSpd + endSpd + 2.0);
        startSpeed = jmax (0.0, startSpd * invTotalDistance);
        midSpeed = invTotalDistance;
        endSpeed = jmax (0.0, endSpd * invTotalDistance);
        if (useProxyComponent)
            proxy = new ProxyComponent (*component);
        else
            proxy = nullptr;
        component->setVisible (! useProxyComponent);
    }

    //这个函数就是进行位置和透明度的变化
    bool useTimeslice (const int elapsed)
    {
        if (Componentconst c = proxy != nullptr ? static_cast<Component*> (proxy)static_cast<Component*> (component))
        {
            msElapsed += elapsed;
            double newProgress = msElapsed / (double) msTotal;
            if (newProgress >= 0 && newProgress < 1.0)
            {
                newProgress = timeToDistance (newProgress);
                const double delta = (newProgress - lastProgress) / (1.0 - lastProgress);
                jassert (newProgress >= lastProgress);
                lastProgress = newProgress;
                if (delta < 1.0)
                {
                    bool stillBusy = false;
                    if (isMoving)
                    {
                              //偏移位置
                        left   += (destination.getX()      - left)   * delta;
                        top    += (destination.getY()      - top)    * delta;
                        right  += (destination.getRight()  - right)  * delta;
                        bottom += (destination.getBottom() - bottom) * delta;
                        const Rectangle<int> newBounds (roundToInt (left),
                                                        roundToInt (top),
                                                        roundToInt (right - left),
                                                        roundToInt (bottom - top));
                        if (newBounds != destination)
                        {
                            c->setBounds (newBounds);
                            stillBusy = true;
                        }
                    }
                         //偏移透明度
                    if (isChangingAlpha)
                    {
                        alpha += (destAlpha - alpha) * delta;
                        c->setAlpha ((floatalpha);
                        stillBusy = true;
                    }
                
                    if (stillBusy)
                        return true;
                }
            }
        }
        moveToFinalDestination();
        return false;
    }
   //移动到结束位置
    void moveToFinalDestination()
    {
        if (component != nullptr)
        {
            component->setAlpha ((floatdestAlpha);
            component->setBounds (destination);
            if (proxy != nullptr)
                component->setVisible (destAlpha > 0);
        }
    }
    //==============================================================================
    class ProxyComponent  : public Component
    {
    public:
        ProxyComponent (Componentc)
        {
            setWantsKeyboardFocus (false);
            setBounds (c.getBounds());
            setTransform (c.getTransform());
            setAlpha (c.getAlpha());
            setInterceptsMouseClicks (falsefalse);
            if (Componentconst parent = c.getParentComponent())
                parent->addAndMakeVisible (this);
            else if (c.isOnDesktop() && c.getPeer() != nullptr)
                addToDesktop (c.getPeer()->getStyleFlags() | ComponentPeer::windowIgnoresKeyPresses);
            else
                jassertfalse// seem to be trying to animate a component that‘s not visible..
            const float scale = (floatDesktop::getInstance().getDisplays()
                                            .getDisplayContaining (getScreenBounds().getCentre()).scale;
            image = c.createComponentSnapshot (c.getLocalBounds(), false, scale);
            setVisible (true);
            toBehind (&c);
        }
        void paint (Graphicsgoverride
        {
            g.setOpacity (1.0f);
            g.drawImageTransformed (imageAffineTransform::scale (getWidth()  / (floatimage.getWidth(),
                                                                   getHeight() / (floatimage.getHeight()), false);
        }
    private:
        Image image;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent)
    };

    WeakReference<Component> component;//移动的控件
    ScopedPointer<Component> proxy; //代理,也就是用一张图来显示控件内容
    Rectangle<int> destination; //目标位置
    double destAlpha; //透明度
    int msElapsed, msTotal; //使用了多少时间
    double startSpeed, midSpeed, endSpeed, lastProgress; //计算得到的几个速度
    double left, top, right, bottom, alpha; 
    bool isMoving, isChangingAlpha;

private:
    //这里的时间是限制在0到1之间?
    double timeToDistance (const double timeconst noexcept
    {
        return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed))
                            : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed))
                                + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed));
    }
};


来自为知笔记(Wiz)


AnimationTask分析