Source: animation/PathMotion.js

  1. import {Animate} from './Animate';
  2. import {Utils} from '../utils/Utils';
  3. import {Tween} from '../utils/Tween';
  4. import {Curve} from '../math/Curve';
  5. import {Point} from '../math/Point';
  6. /**
  7. * PathMotion类型动画对象
  8. *
  9. * @class
  10. * @memberof JC
  11. * @param {object} [options] 动画所具备的特性
  12. */
  13. function PathMotion(options) {
  14. Animate.call(this, options);
  15. if (!options.path || !(options.path instanceof Curve)) {
  16. console.warn('path is not instanceof Curve');
  17. }
  18. this.path = options.path;
  19. this.ease = options.ease || Tween.Ease.InOut;
  20. this.lengthMode = Utils.isBoolean(options.lengthMode)?
  21. options.lengthMode:
  22. false;
  23. this.attachTangent = Utils.isBoolean(options.attachTangent)?
  24. options.attachTangent:
  25. false;
  26. this._cacheRotate = this.element.rotation;
  27. const radian = this._cacheRotate;
  28. this._cacheVector = new Point(10 * Math.cos(radian), 10 * Math.sin(radian));
  29. }
  30. PathMotion.prototype = Object.create(Animate.prototype);
  31. /**
  32. * 计算下一帧状态
  33. * @private
  34. * @return {object}
  35. */
  36. PathMotion.prototype.nextPose = function() {
  37. let _rotate = 0;
  38. const t = this.ease(this.progress / this.duration);
  39. const pos = this.lengthMode ?
  40. this.path.getPointAt(t) :
  41. this.path.getPoint(t);
  42. const pose = pos.clone();
  43. if (this.attachTangent) {
  44. _rotate = this.decomposeRotate(t);
  45. pose.rotation = _rotate === false ? this.preDegree : _rotate;
  46. pose.rotation += this._cacheRotate;
  47. if (_rotate !== false) this.preDegree = _rotate;
  48. }
  49. this.element.setProps(pose);
  50. return pose;
  51. };
  52. /**
  53. * 解算旋转角度
  54. * @private
  55. * @param {number} t 当前进度, 区间[0, 1]
  56. * @return {number}
  57. */
  58. PathMotion.prototype.decomposeRotate = function(t) {
  59. const vector = this.lengthMode ?
  60. this.path.getTangentAt(t) :
  61. this.path.getTangent(t);
  62. const nor = this._cacheVector.x * vector.y - vector.x * this._cacheVector.y;
  63. const pi = nor > 0 ? 1 : -1;
  64. const cos = (vector.x * this._cacheVector.x + vector.y * this._cacheVector.y)/
  65. ( Math.sqrt(vector.x * vector.x + vector.y * vector.y) *
  66. Math.sqrt(
  67. this._cacheVector.x * this._cacheVector.x +
  68. this._cacheVector.y * this._cacheVector.y
  69. )
  70. );
  71. if (isNaN(cos)) return false;
  72. return pi * Math.acos(cos) * Utils.RTD;
  73. };
  74. export {PathMotion};