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()) 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 isFirstAssign_ = false; 118 SetValue(endValue); 119 return; 120 } 121 if (NearEqual(value_, endValue)) { 122 return; 123 } 124 ResetController(); 125 if (!animationController_) { 126 animationController_ = CREATE_ANIMATOR(context_); 127 } 128 RefPtr<CurveAnimation<double>> animation = 129 AceType::MakeRefPtr<CurveAnimation<double>>(value_, endValue, animationOption_.GetCurve()); 130 animation->AddListener(std::bind(&AnimatableDouble::OnAnimationCallback, this, std::placeholders::_1)); 131 132 animationController_->AddInterpolator(animation); 133 auto onFinishEvent = animationOption_.GetOnFinishEvent(); 134 if (onFinishEvent) { 135 animationController_->AddStopListener([onFinishEvent, weakContext = context_] { 136 auto context = weakContext.Upgrade(); 137 if (context) { 138 context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatableDoubleFinishEvent"); 139 } else { 140 LOGE("the context is null"); 141 } 142 }); 143 } 144 if (stopCallback_) { 145 animationController_->AddStopListener(stopCallback_); 146 } 147 animationController_->SetDuration(animationOption_.GetDuration()); 148 animationController_->SetStartDelay(animationOption_.GetDelay()); 149 animationController_->SetIteration(animationOption_.GetIteration()); 150 animationController_->SetTempo(animationOption_.GetTempo()); 151 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection()); 152 animationController_->SetFillMode(FillMode::FORWARDS); 153 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously()); 154 animationController_->Play(); 155 } 156 ResetController()157 void ResetController() 158 { 159 if (animationController_) { 160 if (!animationController_->IsStopped()) { 161 animationController_->Stop(); 162 } 163 animationController_->ClearInterpolators(); 164 animationController_->ClearAllListeners(); 165 animationController_.Reset(); 166 } 167 } 168 OnAnimationCallback(const double & value)169 void OnAnimationCallback(const double& value) 170 { 171 SetValue(value); 172 if (animationCallback_) { 173 animationCallback_(); 174 } 175 } 176 ResetAnimatableDouble()177 void ResetAnimatableDouble() 178 { 179 isFirstAssign_ = true; 180 animationOption_ = AnimationOption(); 181 animationController_ = nullptr; 182 context_ = nullptr; 183 animationCallback_ = nullptr; 184 stopCallback_ = nullptr; 185 } 186 187 private: 188 double value_; 189 bool isFirstAssign_ = true; 190 AnimationOption animationOption_; 191 RefPtr<Animator> animationController_; 192 WeakPtr<PipelineContext> context_; 193 RenderNodeAnimationCallback animationCallback_; 194 RenderNodeAnimationCallback stopCallback_; 195 }; 196 197 } // namespace OHOS::Ace 198 199 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_DOUBLE_H 200