can-animate.mjs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import { isGenerator } from 'motion-dom';
  2. import { warning } from 'motion-utils';
  3. import { isAnimatable } from '../../utils/is-animatable.mjs';
  4. function hasKeyframesChanged(keyframes) {
  5. const current = keyframes[0];
  6. if (keyframes.length === 1)
  7. return true;
  8. for (let i = 0; i < keyframes.length; i++) {
  9. if (keyframes[i] !== current)
  10. return true;
  11. }
  12. }
  13. function canAnimate(keyframes, name, type, velocity) {
  14. /**
  15. * Check if we're able to animate between the start and end keyframes,
  16. * and throw a warning if we're attempting to animate between one that's
  17. * animatable and another that isn't.
  18. */
  19. const originKeyframe = keyframes[0];
  20. if (originKeyframe === null)
  21. return false;
  22. /**
  23. * These aren't traditionally animatable but we do support them.
  24. * In future we could look into making this more generic or replacing
  25. * this function with mix() === mixImmediate
  26. */
  27. if (name === "display" || name === "visibility")
  28. return true;
  29. const targetKeyframe = keyframes[keyframes.length - 1];
  30. const isOriginAnimatable = isAnimatable(originKeyframe, name);
  31. const isTargetAnimatable = isAnimatable(targetKeyframe, name);
  32. warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${name} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
  33. // Always skip if any of these are true
  34. if (!isOriginAnimatable || !isTargetAnimatable) {
  35. return false;
  36. }
  37. return (hasKeyframesChanged(keyframes) ||
  38. ((type === "spring" || isGenerator(type)) && velocity));
  39. }
  40. export { canAnimate };