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_ANIMATION_KEYFRAME_ANIMATION_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_KEYFRAME_ANIMATION_H 18 19 #include <list> 20 21 #include "base/utils/utils.h" 22 #include "core/animation/animation.h" 23 #include "core/animation/curve.h" 24 #include "core/animation/curves.h" 25 #include "core/animation/evaluator.h" 26 #include "core/animation/keyframe.h" 27 28 namespace OHOS::Ace { 29 30 template<typename T> 31 class KeyframeAnimation : public Animation<T> { 32 DECLARE_ACE_TYPE(KeyframeAnimation, Animation<T>); 33 public: 34 KeyframeAnimation() = default; 35 36 ~KeyframeAnimation() override = default; 37 AddKeyframe(const std::list<RefPtr<Keyframe<T>>> & keyframes)38 void AddKeyframe(const std::list<RefPtr<Keyframe<T>>>& keyframes) 39 { 40 for (const auto& keyframe : keyframes) { 41 AddKeyframe(keyframe); 42 } 43 // in order by time; 44 keyframes_.sort([](const RefPtr<Keyframe<T>>& a, const RefPtr<Keyframe<T>>& b) { 45 return a->GetKeyTime() < b->GetKeyTime(); 46 }); 47 } 48 AddKeyframe(const RefPtr<Keyframe<T>> & keyframe)49 void AddKeyframe(const RefPtr<Keyframe<T>>& keyframe) 50 { 51 if (!keyframe) { 52 LOGE("add key frame failed. empty keyframe."); 53 return; 54 } 55 if (!keyframe->IsValid()) { 56 LOGE("add key frame failed. invalid keyframe."); 57 return; 58 } 59 60 keyframes_.emplace_back(keyframe); 61 ++keyframeNum_; 62 } 63 ReplaceKeyframe(const RefPtr<Keyframe<T>> & keyframeReplace)64 void ReplaceKeyframe(const RefPtr<Keyframe<T>>& keyframeReplace) 65 { 66 if (!keyframeReplace) { 67 LOGE("add key frame failed. empty keyframe."); 68 return; 69 } 70 if (!keyframeReplace->IsValid()) { 71 LOGE("add key frame failed. invalid keyframe."); 72 return; 73 } 74 for (auto& keyframe : keyframes_) { 75 if (NearEqual(keyframe->GetKeyTime(), keyframeReplace->GetKeyTime())) { 76 keyframe = keyframeReplace; 77 } 78 } 79 } 80 GetValue()81 const T& GetValue() const override 82 { 83 return currentValue_; 84 } 85 GetKeyframes()86 const std::list<RefPtr<Keyframe<T>>>& GetKeyframes() const 87 { 88 return keyframes_; 89 } 90 SetCurve(const RefPtr<Curve> & curve)91 void SetCurve(const RefPtr<Curve>& curve) override 92 { 93 if (!curve) { 94 LOGE("set curve failed. curve is null."); 95 return; 96 } 97 for (auto& keyframe : keyframes_) { 98 keyframe->SetCurve(curve); 99 } 100 } 101 RunAsync(const WeakPtr<Scheduler> & weakScheduler,const AnimationOption & option,const std::function<void ()> prepareCallback,const std::function<void ()> finishCallback)102 bool RunAsync(const WeakPtr<Scheduler>& weakScheduler, const AnimationOption& option, 103 const std::function<void()> prepareCallback, const std::function<void()> finishCallback) override 104 { 105 auto scheduler = weakScheduler.Upgrade(); 106 if (scheduler == nullptr) { 107 LOGE("run async failed, scheduler is null!"); 108 return false; 109 } 110 111 scheduler->OpenImplicitAnimation(option, Curves::EASE, finishCallback); 112 113 for (const auto& keyframe : keyframes_) { 114 if (keyframe == nullptr) { 115 continue; 116 } 117 118 float fraction = keyframe->GetKeyTime(); 119 auto curve = keyframe->GetCurve() ? keyframe->GetCurve() : AceType::DynamicCast<Curve>(Curves::EASE); 120 scheduler->AddKeyFrame( 121 fraction, curve, [weak = AceType::WeakClaim(this), callback = prepareCallback, fraction]() { 122 auto animation = weak.Upgrade(); 123 if (animation == nullptr) { 124 LOGE("propetry change failed, animation is null!"); 125 return; 126 } 127 128 if (callback != nullptr) { 129 callback(); 130 } 131 132 animation->OnNormalizedTimestampChanged(fraction, false); 133 }); 134 } 135 136 return scheduler->CloseImplicitAnimation(); 137 } 138 139 private: Calculate(float keyTime)140 void Calculate(float keyTime) 141 { 142 if (keyframes_.empty()) { 143 return; 144 } 145 auto begin = keyframes_.front()->GetKeyValue(); 146 auto end = keyframes_.back()->GetKeyValue(); 147 // The initial state is maintained when keyTime < 0. 148 if (keyTime < 0.0f) { 149 currentValue_ = begin; 150 return; 151 } else if (keyTime > 1.0f || keyframeNum_ == 1) { 152 // The final state is maintained when keyTime > 1 or keyframeNum_ = 1. 153 currentValue_ = end; 154 return; 155 } 156 auto preKeyframe = keyframes_.front(); 157 // Iteratively calculate the value between each keyframe. 158 for (const auto& keyframe : keyframes_) { 159 if (keyTime < keyframe->GetKeyTime()) { 160 float preKeyTime = preKeyframe->GetKeyTime(); 161 if (NearEqual(keyframe->GetKeyTime(), preKeyTime)) { 162 return; 163 } 164 float intervalKeyTime = (keyTime - preKeyTime) / (keyframe->GetKeyTime() - preKeyTime); 165 auto& curve = keyframe->GetCurve(); 166 begin = preKeyframe->GetKeyValue(); 167 end = keyframe->GetKeyValue(); 168 if (curve) { 169 currentValue_ = evaluator_->Evaluate(begin, end, curve->Move(intervalKeyTime)); 170 return; 171 } else { 172 currentValue_ = evaluator_->Evaluate(begin, end, Curves::EASE->Move(intervalKeyTime)); 173 return; 174 } 175 } 176 preKeyframe = keyframe; 177 } 178 currentValue_ = end; 179 } 180 OnNormalizedTimestampChanged(float normalized,bool reverse)181 void OnNormalizedTimestampChanged(float normalized, bool reverse) override 182 { 183 if (normalized < NORMALIZED_DURATION_MIN || normalized > NORMALIZED_DURATION_MAX) { 184 LOGE("normalized time check failed. normalized: %{public}f", normalized); 185 return; 186 } 187 Calculate(normalized); 188 ValueListenable<T>::NotifyListener(currentValue_); 189 } 190 191 T currentValue_ {}; 192 int32_t keyframeNum_ = 0; 193 std::list<RefPtr<Keyframe<T>>> keyframes_; 194 RefPtr<Evaluator<T>> evaluator_ = AceType::MakeRefPtr<LinearEvaluator<T>>(); 195 }; 196 197 } // namespace OHOS::Ace 198 199 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_KEYFRAME_ANIMATION_H 200