Animatable.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /*
  2. * Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/Animations/Animatable.h>
  7. #include <LibWeb/Animations/Animation.h>
  8. #include <LibWeb/Animations/DocumentTimeline.h>
  9. #include <LibWeb/DOM/Document.h>
  10. #include <LibWeb/DOM/Element.h>
  11. namespace Web::Animations {
  12. // https://www.w3.org/TR/web-animations-1/#dom-animatable-animate
  13. WebIDL::ExceptionOr<JS::NonnullGCPtr<Animation>> Animatable::animate(Optional<JS::Handle<JS::Object>> keyframes, Variant<Empty, double, KeyframeAnimationOptions> options)
  14. {
  15. // 1. Let target be the object on which this method was called.
  16. JS::NonnullGCPtr target { *static_cast<DOM::Element*>(this) };
  17. auto& realm = target->realm();
  18. // 2. Construct a new KeyframeEffect object, effect, in the relevant Realm of target by using the same procedure as
  19. // the KeyframeEffect(target, keyframes, options) constructor, passing target as the target argument, and the
  20. // keyframes and options arguments as supplied.
  21. //
  22. // If the above procedure causes an exception to be thrown, propagate the exception and abort this procedure.
  23. auto effect = TRY(options.visit(
  24. [&](Empty) { return KeyframeEffect::construct_impl(realm, target, keyframes); },
  25. [&](auto const& value) { return KeyframeEffect::construct_impl(realm, target, keyframes, value); }));
  26. // 3. If options is a KeyframeAnimationOptions object, let timeline be the timeline member of options or, if
  27. // timeline member of options is missing, be the default document timeline of the node document of the element
  28. // on which this method was called.
  29. JS::GCPtr<AnimationTimeline> timeline;
  30. if (options.has<KeyframeAnimationOptions>())
  31. timeline = options.get<KeyframeAnimationOptions>().timeline;
  32. if (!timeline)
  33. timeline = target->document().timeline();
  34. // 4. Construct a new Animation object, animation, in the relevant Realm of target by using the same procedure as
  35. // the Animation() constructor, passing effect and timeline as arguments of the same name.
  36. auto animation = TRY(Animation::construct_impl(realm, effect, timeline));
  37. // 5. If options is a KeyframeAnimationOptions object, assign the value of the id member of options to animation’s
  38. // id attribute.
  39. if (options.has<KeyframeAnimationOptions>())
  40. animation->set_id(options.get<KeyframeAnimationOptions>().id);
  41. // 6. Run the procedure to play an animation for animation with the auto-rewind flag set to true.
  42. TRY(animation->play_an_animation(Animation::AutoRewind::Yes));
  43. // 7. Return animation.
  44. return animation;
  45. }
  46. // https://www.w3.org/TR/web-animations-1/#dom-animatable-getanimations
  47. Vector<JS::NonnullGCPtr<Animation>> Animatable::get_animations(Web::Animations::GetAnimationsOptions options)
  48. {
  49. // FIXME: Implement this
  50. (void)options;
  51. return {};
  52. }
  53. void Animatable::associate_with_effect(JS::NonnullGCPtr<AnimationEffect> effect)
  54. {
  55. m_associated_effects.append(effect);
  56. }
  57. void Animatable::disassociate_with_effect(JS::NonnullGCPtr<AnimationEffect> effect)
  58. {
  59. m_associated_effects.remove_first_matching([&](auto element) { return effect == element; });
  60. }
  61. }