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_DOUBLE_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_DOUBLE_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/event/ace_event_helper.h" 23 24 namespace OHOS::Ace { 25 26 using RenderNodeAnimationCallback = std::function<void()>; 27 28 /* 29 * AnimatableDouble is a double with AnimationOption and Animator. 30 */ 31 class AnimatableDouble final { 32 public: 33 AnimatableDouble() = default; 34 explicit AnimatableDouble(double value, const AnimationOption& option = AnimationOption()) value_(value)35 : value_(value), animationOption_(option) 36 {} 37 ~AnimatableDouble() = default; 38 SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)39 void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback) 40 { 41 context_ = context; 42 animationCallback_ = callback; 43 } 44 SetAnimationStopCallback(const RenderNodeAnimationCallback & callback)45 void SetAnimationStopCallback(const RenderNodeAnimationCallback& callback) 46 { 47 stopCallback_ = callback; 48 } 49 GetValue()50 double GetValue() const 51 { 52 return value_; 53 } 54 SetValue(double value)55 void SetValue(double value) 56 { 57 value_ = value; 58 } 59 GetAnimationOption()60 const AnimationOption& GetAnimationOption() const 61 { 62 return animationOption_; 63 } 64 SetAnimationOption(const AnimationOption & option)65 void SetAnimationOption(const AnimationOption& option) 66 { 67 animationOption_ = option; 68 } 69 70 AnimatableDouble& operator=(double newValue) 71 { 72 ResetAnimatableDouble(); 73 value_ = newValue; 74 return *this; 75 } 76 77 AnimatableDouble& operator=(const AnimatableDouble& newValue) 78 { 79 SetAnimationOption(newValue.GetAnimationOption()); 80 auto context = context_.Upgrade(); 81 if (!context || !animationCallback_) { 82 SetValue(newValue.GetValue()); 83 return *this; 84 } 85 AnimationOption explicitAnim = context->GetExplicitAnimationOption(); 86 if (explicitAnim.IsValid()) { 87 SetAnimationOption(explicitAnim); 88 AnimateTo(newValue.GetValue()); 89 } else if (animationOption_.IsValid()) { 90 AnimateTo(newValue.GetValue()); 91 } else { 92 ResetController(); 93 SetValue(newValue.GetValue()); 94 } 95 isFirstAssign_ = false; 96 return *this; 97 } 98 MoveTo(double target)99 void MoveTo(double target) 100 { 101 SetValue(target); 102 isFirstAssign_ = false; 103 } 104 GetAnimationStatus()105 Animator::Status GetAnimationStatus() const 106 { 107 if (!animationController_) { 108 return Animator::Status::IDLE; 109 } 110 return animationController_->GetStatus(); 111 } 112 113 private: AnimateTo(double endValue)114 void AnimateTo(double endValue) 115 { 116 if (isFirstAssign_) { 117 LOGD("AnimateTo with first assign. endValue: %{public}.2f", endValue); 118 isFirstAssign_ = false; 119 SetValue(endValue); 120 return; 121 } 122 if (NearEqual(value_, endValue)) { 123 LOGD("AnimateTo with same value. endValue: %{public}.2f", endValue); 124 return; 125 } 126 ResetController(); 127 if (!animationController_) { 128 animationController_ = AceType::MakeRefPtr<Animator>(context_); 129 } 130 RefPtr<CurveAnimation<double>> animation = 131 AceType::MakeRefPtr<CurveAnimation<double>>(value_, endValue, animationOption_.GetCurve()); 132 animation->AddListener(std::bind(&AnimatableDouble::OnAnimationCallback, this, std::placeholders::_1)); 133 134 animationController_->AddInterpolator(animation); 135 auto onFinishEvent = animationOption_.GetOnFinishEvent(); 136 if (onFinishEvent) { 137 animationController_->AddStopListener([onFinishEvent, weakContext = context_] { 138 auto context = weakContext.Upgrade(); 139 if (context) { 140 context->PostAsyncEvent(onFinishEvent); 141 } else { 142 LOGE("the context is null"); 143 } 144 }); 145 } 146 if (stopCallback_) { 147 animationController_->AddStopListener(stopCallback_); 148 } 149 animationController_->SetDuration(animationOption_.GetDuration()); 150 animationController_->SetStartDelay(animationOption_.GetDelay()); 151 animationController_->SetIteration(animationOption_.GetIteration()); 152 animationController_->SetTempo(animationOption_.GetTempo()); 153 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection()); 154 animationController_->SetFillMode(FillMode::FORWARDS); 155 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously()); 156 animationController_->Play(); 157 } 158 ResetController()159 void ResetController() 160 { 161 if (animationController_) { 162 if (!animationController_->IsStopped()) { 163 animationController_->Stop(); 164 } 165 animationController_->ClearInterpolators(); 166 animationController_->ClearAllListeners(); 167 animationController_.Reset(); 168 } 169 } 170 OnAnimationCallback(const double & value)171 void OnAnimationCallback(const double& value) 172 { 173 SetValue(value); 174 if (animationCallback_) { 175 animationCallback_(); 176 } 177 } 178 ResetAnimatableDouble()179 void ResetAnimatableDouble() 180 { 181 isFirstAssign_ = true; 182 animationOption_ = AnimationOption(); 183 animationController_ = nullptr; 184 context_ = nullptr; 185 animationCallback_ = nullptr; 186 stopCallback_ = nullptr; 187 } 188 189 private: 190 double value_; 191 bool isFirstAssign_ = true; 192 AnimationOption animationOption_; 193 RefPtr<Animator> animationController_; 194 WeakPtr<PipelineContext> context_; 195 RenderNodeAnimationCallback animationCallback_; 196 RenderNodeAnimationCallback stopCallback_; 197 }; 198 199 } // namespace OHOS::Ace 200 201 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_DOUBLE_H