1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H 18 19 #include "core/animation/animator.h" 20 #include "core/animation/curve_animation.h" 21 #include "core/components/common/properties/animation_option.h" 22 #include "core/components/common/properties/color.h" 23 #include "core/event/ace_event_helper.h" 24 25 namespace OHOS::Ace { 26 27 using RenderNodeAnimationCallback = std::function<void()>; 28 29 /* 30 * AnimatableColor is a Color with AnimationOption and Animator. 31 */ 32 class AnimatableColor final : public Color { 33 public: 34 AnimatableColor() = default; 35 explicit AnimatableColor(uint32_t value, const AnimationOption& option = AnimationOption()) : Color(value) 36 { 37 animationOption_ = option; 38 } 39 40 explicit AnimatableColor(const Color& color, const AnimationOption& option = AnimationOption()) 41 : Color(color.GetValue()) 42 { 43 animationOption_ = option; 44 } 45 46 ~AnimatableColor() = default; 47 SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)48 void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback) 49 { 50 context_ = context; 51 animationCallback_ = callback; 52 } 53 GetAnimationOption()54 const AnimationOption& GetAnimationOption() const 55 { 56 return animationOption_; 57 } 58 SetAnimationOption(const AnimationOption & option)59 void SetAnimationOption(const AnimationOption& option) 60 { 61 animationOption_ = option; 62 } 63 64 AnimatableColor& operator=(const AnimatableColor& newColor) 65 { 66 SetAnimationOption(newColor.GetAnimationOption()); 67 auto pipelineContext = context_.Upgrade(); 68 if (!pipelineContext || !animationCallback_) { 69 SetValue(newColor.GetValue()); 70 return *this; 71 } 72 AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption(); 73 if (explicitAnim.IsValid()) { 74 SetAnimationOption(explicitAnim); 75 AnimateTo(newColor.GetValue()); 76 } else if (animationOption_.IsValid()) { 77 AnimateTo(newColor.GetValue()); 78 } else { 79 ResetController(); 80 SetValue(newColor.GetValue()); 81 } 82 isFirstAssign_ = false; 83 return *this; 84 } 85 86 private: AnimateTo(uint32_t endValue)87 void AnimateTo(uint32_t endValue) 88 { 89 if (isFirstAssign_) { 90 isFirstAssign_ = false; 91 SetValue(endValue); 92 return; 93 } 94 if (GetValue() == endValue) { 95 return; 96 } 97 ResetController(); 98 if (!animationController_) { 99 animationController_ = CREATE_ANIMATOR(context_); 100 } 101 102 RefPtr<CurveAnimation<Color>> colorAnimation = 103 AceType::MakeRefPtr<CurveAnimation<Color>>(Color(GetValue()), Color(endValue), animationOption_.GetCurve()); 104 colorAnimation->AddListener(std::bind(&AnimatableColor::OnAnimationCallback, this, std::placeholders::_1)); 105 106 animationController_->AddInterpolator(colorAnimation); 107 auto onFinishEvent = animationOption_.GetOnFinishEvent(); 108 if (onFinishEvent) { 109 animationController_->AddStopListener([onFinishEvent, weakContext = context_] { 110 auto context = weakContext.Upgrade(); 111 if (context) { 112 context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatableColorFinishEvent"); 113 } else { 114 LOGE("the context is null"); 115 } 116 }); 117 } 118 animationController_->SetDuration(animationOption_.GetDuration()); 119 animationController_->SetStartDelay(animationOption_.GetDelay()); 120 animationController_->SetIteration(animationOption_.GetIteration()); 121 animationController_->SetTempo(animationOption_.GetTempo()); 122 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection()); 123 animationController_->SetFillMode(FillMode::FORWARDS); 124 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously()); 125 animationController_->Play(); 126 } 127 ResetController()128 void ResetController() 129 { 130 if (animationController_) { 131 if (!animationController_->IsStopped()) { 132 animationController_->Stop(); 133 } 134 animationController_->ClearInterpolators(); 135 animationController_->ClearAllListeners(); 136 animationController_.Reset(); 137 } 138 } 139 OnAnimationCallback(const Color & color)140 void OnAnimationCallback(const Color& color) 141 { 142 SetValue(color.GetValue()); 143 if (animationCallback_) { 144 animationCallback_(); 145 } 146 } 147 148 private: 149 bool isFirstAssign_ = true; 150 AnimationOption animationOption_; 151 RefPtr<Animator> animationController_; 152 WeakPtr<PipelineContext> context_; 153 RenderNodeAnimationCallback animationCallback_; 154 }; 155 156 } // namespace OHOS::Ace 157 158 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H 159