Source: src/SpinViewer/SpinViewer.ts

  1. import Component, { ComponentEvent } from "@egjs/component";
  2. import Axes, { PanInput } from "@egjs/axes";
  3. import { VERSION } from "../version";
  4. import { AnimationEndEvent, ChangeEvent, ImageErrorEvent, LoadEvent } from "../types/event";
  5. import SpriteImage from "./SpriteImage";
  6. const DEFAULT_PAN_SCALE = 0.21;
  7. export interface SpinViewerEvent {
  8. load: LoadEvent;
  9. imageError: ImageErrorEvent;
  10. change: ChangeEvent;
  11. animationEnd: AnimationEndEvent<SpinViewer>;
  12. }
  13. export interface SpinViewerOptions {
  14. imageUrl: string;
  15. rowCount: number;
  16. colCount: number;
  17. width: number | string;
  18. height: number | string;
  19. autoHeight: boolean;
  20. colRow: number[];
  21. scale: number;
  22. frameIndex: number;
  23. wrapperClass: string;
  24. imageClass: string;
  25. }
  26. /**
  27. * @memberof eg.view360
  28. * @extends eg.Component
  29. * SpinViewer
  30. */
  31. class SpinViewer extends Component<SpinViewerEvent> {
  32. /**
  33. * Version info string
  34. * @ko 버전정보 문자열
  35. * @static
  36. * @example
  37. * eg.view360.SpinViewer.VERSION; // ex) 3.0.1
  38. * @memberof eg.view360.SpinViewer
  39. */
  40. public static VERSION = VERSION;
  41. private _el: HTMLElement;
  42. private _sprites: SpriteImage;
  43. private _axes: Axes;
  44. private _panInput: PanInput;
  45. private _scale: number;
  46. private _panScale: number;
  47. private _frameCount: number;
  48. /**
  49. * @classdesc A module used to displays each image sequentially according to the direction of the user's touch movement (left / right) of the sprite image that is collected by rotating the object.
  50. * @ko 물체 주위를 회전하여 촬영한 이미지들을 모은 스프라이트 이미지를 사용자의 터치 이동 방향(좌 / 우) 에 따라 각 이미지들을 순차적으로 보여주는 컴포넌트입니다.
  51. *
  52. * @param {HTMLElement} element The element to show the image <ko>이미지를 보여줄 대상 요소</ko>
  53. * @param {Object} options The option object<ko>파라미터 객체</ko>
  54. * @param {String} options.imageUrl The url of the sprite image <ko>스프라이트 이미지의 url</ko>
  55. * @param {Number} [options.rowCount=1] Number of horizontal frames in the sprite image <ko>스프라이트 이미지의 가로 프레임 갯수</ko>
  56. * @param {Number} [options.colCount=1] Number of vertical frames in the sprite image <ko>스프라이트 이미지의 세로 프레임 갯수</ko>
  57. * @param {Number|String} [options.width="auto"] The width of the target element to show the image <ko>이미지를 보여줄 대상 요소의 너비</ko>
  58. * @param {Number|String} [options.height="auto"] The height of the target element to show the image <ko>이미지를 보여줄 대상 요소의 높이</ko>
  59. * @param {Boolean} [options.autoHeight=true] Whether to automatically set the height of the image area to match the original image's proportion <ko>원본 이미지 비율에 맞게 이미지 영역의 높이를 자동으로 설정할지 여부</ko>
  60. * @param {Number[]} [options.colRow=[0, 0]] The column, row coordinates of the first frame of the sprite image (based on 0 index) <ko> 스프라이트 이미지 중 처음 보여줄 프레임의 (column, row) 좌표 (0 index 기반)</ko>
  61. * @param {Number} [options.scale=1] Spin scale (The larger the spin, the more).<ko>Spin 배율 (클 수록 더 많이 움직임)</ko>
  62. * @param {Number} [options.frameIndex] The frameIndex of the frame to be shown in the sprite image<ko>스프라이트 이미지 중 보여질 프레임의 frameIndex 값</ko>
  63. * @param {String} [options.wrapperClass="view360-wrapper"] A class name for the parent element of the image element inside the container element. SpinViewer will use the element that has this class instead of creating one if it exists<ko>이미지 엘리먼트의 부모 엘리먼트의 클래스 이름. SpinViewer는 해당 클래스를 갖는 엘리먼트가 콘테이너 엘리먼트 내부에 존재할 경우, 새로 생성하는 대신 그 엘리먼트를 사용할 것입니다</ko>
  64. * @param {String} [options.imageClass="view360-image"] A class name for the image element inside the container element. SpinViewer will use the image element that has this class instead of creating one if it exists<ko>콘테이너 엘리먼트 내부의 이미지 엘리먼트의 클래스 이름. SpinViewer는 해당 클래스를 갖는 이미지 엘리먼트가 콘테이너 엘리먼트 내부에 존재할 경우, 새로 생성하는 대신 그 엘리먼트를 사용할 것입니다</ko>
  65. * @support {"ie": "9+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
  66. * @example
  67. * ```
  68. * // Initialize SpinViewer
  69. * var el = document.getElementById("product-360");
  70. * var viewer = new eg.view360.SpinViewer(el, {
  71. * imageUrl: "/img/bag360.jpg", // required
  72. * rowCount: 24 //required
  73. * });
  74. * ```
  75. */
  76. public constructor(element: HTMLElement, options: Partial<SpinViewerOptions> = {}) {
  77. super();
  78. this._el = element;
  79. const opt = {...options};
  80. const colCount = opt.colCount || 1;
  81. const rowCount = opt.rowCount || 1;
  82. this._scale = (opt.scale || 1);
  83. this._panScale = this._scale * DEFAULT_PAN_SCALE;
  84. this._frameCount = colCount * rowCount;
  85. // Init SpriteImage
  86. this._sprites = new SpriteImage(element, opt).on({
  87. "load": evt => {
  88. this.trigger(new ComponentEvent("load", evt));
  89. },
  90. "imageError": evt => {
  91. this.trigger(new ComponentEvent("imageError", {
  92. imageUrl: evt.imageUrl
  93. }));
  94. }
  95. });
  96. // Init Axes
  97. this._panInput = new PanInput(this._el, {
  98. scale: [this._panScale, this._panScale]
  99. });
  100. this._axes = new Axes({
  101. angle: {
  102. range: [0, 359],
  103. circular: true
  104. }
  105. }).on({
  106. "change": evt => {
  107. const curr = Math.floor(evt.pos.angle / (360 / this._frameCount));
  108. const frameIndex = this._frameCount - curr - 1;
  109. this._sprites.setFrameIndex(frameIndex);
  110. this.trigger(new ComponentEvent("change", {
  111. frameIndex,
  112. colRow: this._sprites.getColRow(),
  113. angle: evt.pos.angle
  114. }));
  115. },
  116. "animationEnd": evt => {
  117. this.trigger(new ComponentEvent("animationEnd", {
  118. isTrusted: evt.isTrusted
  119. }));
  120. }
  121. });
  122. this._axes.connect("angle", this._panInput);
  123. }
  124. /**
  125. * Set spin scale
  126. * @ko scale 을 조정할 수 있는 함수
  127. * @param {Number} scale Rotation multiples at spin, the larger the rotation<ko>Spin 시 회전 배수값, 커질 수록 더 많이 회전</ko>
  128. *
  129. * @return {Object} Instance of SpinViewer <ko>SpinViewer 인스턴스</ko>
  130. *
  131. * @example
  132. * viewer.setScale(2);// It moves twice as much.
  133. */
  134. public setScale(scale: number) {
  135. if (isNaN(scale) || scale < 0) {
  136. return this;
  137. }
  138. this._scale = scale;
  139. this._panScale = scale * DEFAULT_PAN_SCALE;
  140. this._panInput.options.scale = [this._panScale, this._panScale];
  141. return this;
  142. }
  143. /**
  144. * Get spin scale
  145. * @ko scale 값을 반환한다.
  146. *
  147. * @return {Number} Rotation multiples at spin, the larger the rotation<ko>Spin 시 회전 배수값, 커질 수록 더 많이 회전</ko>
  148. *
  149. * @example
  150. * viewer.getScale();// It returns number
  151. */
  152. public getScale() {
  153. return this._scale;
  154. }
  155. /**
  156. * It gives the effect of rotating for a certain duration by the specified angle based on the current rotation angle.
  157. * @ko 현재 회전 각도를 기준으로 지정된 각도(angle)만큼 일정 시간동안(duration) 회전하는 효과를 준다.
  158. * @param {Number} [angle = 0] angle<ko>상대적 회전 각도</ko>
  159. * @param {Object} param The parameter object<ko>파라미터 객체</ko>
  160. * @param {Number} [param.duration = 0] duration<ko>회전할 시간 - 밀리세컨드 단위</ko>
  161. *
  162. * @return {Object} Instance of SpinViewer <ko>SpinViewer 인스턴스</ko>
  163. *
  164. * @example
  165. * viewer.spinBy(720, {duration: 500});
  166. */
  167. public spinBy(angle = 0, param = {duration: 0}) {
  168. this._axes.setBy({angle}, param.duration);
  169. return this;
  170. }
  171. /**
  172. * It gives the effect of rotating for a certain duration (duration) by the specified angle (angle).
  173. * @ko 지정된 각도(angle)만큼 일정 시간동안(duration) 회전하는 효과를 준다.
  174. * @param {Number} [angle = 0] angle<ko>회전 각도</ko>
  175. * @param {Object} param The parameter object<ko>파라미터 객체</ko>
  176. * @param {Number} [param.duration = 0] duration<ko>회전할 시간 - 밀리세컨드 단위</ko>
  177. *
  178. * @return {Object} Instance of SpinViewer <ko>SpinViewer 인스턴스</ko>
  179. *
  180. * @example
  181. * viewer.spinTo(30, {duration:100});
  182. */
  183. public spinTo(angle = 0, param = {duration: 0}) {
  184. this._axes.setTo({angle}, param.duration);
  185. return this;
  186. }
  187. /**
  188. * Returns current angles
  189. * @ko 현재 각도를 반환한다.
  190. *
  191. * @return {Number} Current angle <ko>현재 각도</ko>
  192. */
  193. public getAngle() {
  194. return this._axes.get().angle || 0;
  195. }
  196. }
  197. export default SpinViewer;
comments powered by Disqus