utils.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { animationType } from './types';
  2. import { maxTouchTime, defaultAnimationConfig } from './variables';
  3. /**
  4. * 获取图片合适的大小
  5. * @param naturalWidth 图片真实宽度
  6. * @param naturalHeight 图片真实高度
  7. * @return 图片合适的大小
  8. */
  9. export const getSuitableImageSize = (
  10. naturalWidth: number,
  11. naturalHeight: number,
  12. ): {
  13. width: number;
  14. height: number;
  15. } => {
  16. let width = 0;
  17. let height = 0;
  18. const { innerWidth, innerHeight } = window;
  19. if (naturalWidth < innerWidth && naturalHeight < innerHeight) {
  20. width = naturalWidth;
  21. height = naturalHeight;
  22. } else if (naturalWidth < innerWidth && naturalHeight >= innerHeight) {
  23. width = (naturalWidth / naturalHeight) * innerHeight;
  24. height = innerHeight;
  25. } else if (naturalWidth >= innerWidth && naturalHeight < innerHeight) {
  26. width = innerWidth;
  27. height = (naturalHeight / naturalWidth) * innerWidth;
  28. } else if (
  29. naturalWidth >= innerWidth &&
  30. naturalHeight >= innerHeight &&
  31. naturalWidth / naturalHeight > innerWidth / innerHeight
  32. ) {
  33. width = innerWidth;
  34. height = (naturalHeight / naturalWidth) * innerWidth;
  35. } else {
  36. width = (naturalWidth / naturalHeight) * innerHeight;
  37. height = innerHeight;
  38. }
  39. return {
  40. width: Math.floor(width),
  41. height: Math.floor(height),
  42. };
  43. };
  44. export const getPositionOnScale = ({
  45. x,
  46. y,
  47. pageX,
  48. pageY,
  49. toScale,
  50. }: {
  51. x: number;
  52. y: number;
  53. pageX: number;
  54. pageY: number;
  55. toScale: number;
  56. }): {
  57. distanceX: number;
  58. distanceY: number;
  59. } => {
  60. const { innerWidth, innerHeight } = window;
  61. const scale = toScale - 1;
  62. const distanceX = (innerWidth / 2 - x - pageX) * scale;
  63. const distanceY = (innerHeight / 2 - y - pageY) * scale;
  64. return {
  65. distanceX: Math.floor(distanceX),
  66. distanceY: Math.floor(distanceY),
  67. };
  68. };
  69. export const slideToPosition = ({
  70. x,
  71. y,
  72. offsetX,
  73. offsetY,
  74. touchedTime,
  75. }: {
  76. x: number;
  77. y: number;
  78. offsetX: number;
  79. offsetY: number;
  80. touchedTime: number;
  81. }): {
  82. endX: number;
  83. endY: number;
  84. } & animationType => {
  85. const moveTime = Date.now() - touchedTime;
  86. const speedX = (x - offsetX) / moveTime;
  87. const speedY = (y - offsetY) / moveTime;
  88. const maxSpeed = Math.max(speedX, speedY);
  89. const slideTime = moveTime < maxTouchTime ? Math.abs(maxSpeed) * 10 + 400 : 0;
  90. return {
  91. endX: Math.floor(x + speedX * slideTime),
  92. endY: Math.floor(y + speedY * slideTime),
  93. animation: {
  94. stiffness: 170,
  95. damping: 32,
  96. },
  97. };
  98. };
  99. /**
  100. * 跳转到合适的图片偏移量
  101. */
  102. export const jumpToSuitableOffset = ({
  103. x,
  104. y,
  105. offsetX,
  106. offsetY,
  107. width,
  108. height,
  109. scale,
  110. touchedTime,
  111. hasMove,
  112. }: {
  113. x: number;
  114. y: number;
  115. offsetX: number;
  116. offsetY: number;
  117. width: number;
  118. height: number;
  119. scale: number;
  120. touchedTime: number;
  121. hasMove: boolean;
  122. }): {
  123. x: number;
  124. y: number;
  125. } & animationType => {
  126. // 没有移动图片
  127. if (!hasMove) {
  128. return {
  129. x,
  130. y,
  131. animation: defaultAnimationConfig,
  132. };
  133. }
  134. const { innerWidth, innerHeight } = window;
  135. // 图片超出的长度
  136. const outOffsetX = (width * scale - innerWidth) / 2;
  137. const outOffsetY = (height * scale - innerHeight) / 2;
  138. // 滑动到结果的位置
  139. const { endX, endY, animation } = slideToPosition({ x, y, offsetX, offsetY, touchedTime });
  140. let currentX = endX;
  141. let currentY = endY;
  142. if (width * scale <= innerWidth) {
  143. currentX = 0;
  144. } else if (endX > 0 && outOffsetX - endX <= 0) {
  145. currentX = outOffsetX;
  146. } else if (endX < 0 && outOffsetX + endX <= 0) {
  147. currentX = -outOffsetX;
  148. }
  149. if (height * scale <= innerHeight) {
  150. currentY = 0;
  151. } else if (endY > 0 && outOffsetY - endY <= 0) {
  152. currentY = outOffsetY;
  153. } else if (endY < 0 && outOffsetY + endY <= 0) {
  154. currentY = -outOffsetY;
  155. }
  156. const isSlide = currentX === endX || currentY === endY;
  157. return {
  158. x: currentX,
  159. y: currentY,
  160. animation: isSlide ? defaultAnimationConfig : animation,
  161. };
  162. };