UNPKG

@egjs/view3d

Version:

Fast & Customizable glTF 3D model viewer, packed with full of features!

199 lines (161 loc) 5.36 kB
/* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ import View3D from "../../View3D"; import { EVENTS } from "../../const/external"; import * as BROWSER from "../../const/browser"; import ControlBar from "./ControlBar"; import ControlBarItem from "./ControlBarItem"; /** * @param {string} [position="top"] Position inside the control bar * @param {number} [order=9999] Order within the current position, items will be sorted in ascending order */ export interface AnimationSelectorOptions { position: ControlBarItem["position"]; order: ControlBarItem["order"]; } /** * Show animation selector, use with ControlBar */ class AnimationSelector implements ControlBarItem { public position: AnimationSelectorOptions["position"]; public order: AnimationSelectorOptions["order"]; public get element() { return this._rootEl; } public get enabled() { return this._enabled; } private _view3D: View3D; private _controlBar: ControlBar; private _rootEl: HTMLElement; private _nameEl: HTMLElement; private _itemListEl: HTMLElement; private _enabled: boolean; /** */ public constructor(view3D: View3D, controlBar: ControlBar, { position = ControlBar.POSITION.LEFT, order = 9999 }: Partial<AnimationSelectorOptions> = {}) { this.position = position; this.order = order; this._view3D = view3D; this._controlBar = controlBar; this._createElements(); this._enabled = false; } /** * Enable control item */ public enable() { if (this._enabled) return; if (this._view3D.initialized) { this._updateAnimations(); } this._view3D.on(EVENTS.MODEL_CHANGE, this._updateAnimations); this._nameEl.addEventListener(BROWSER.EVENTS.CLICK, this._toggleList); this._enabled = true; } /** * Disable control item */ public disable() { if (!this._enabled) return; this._view3D.off(EVENTS.MODEL_CHANGE, this._updateAnimations); this._view3D.rootEl.removeEventListener(BROWSER.EVENTS.CLICK, this._hideList); this._nameEl.removeEventListener(BROWSER.EVENTS.CLICK, this._toggleList); this._enabled = false; } private _createElements() { const controlBar = this._controlBar; const root = document.createElement(BROWSER.EL_DIV); const name = document.createElement(BROWSER.EL_DIV); const itemList = document.createElement(BROWSER.EL_DIV); const className = { ...controlBar.className, ...ControlBar.DEFAULT_CLASS }; root.classList.add(className.CONTROLS_ITEM); root.classList.add(className.DISABLED); name.classList.add(className.ANIMATION_NAME); itemList.classList.add(className.ANIMATION_LIST); root.appendChild(name); root.appendChild(itemList); this._rootEl = root; this._nameEl = name; this._itemListEl = itemList; } private _updateAnimations = () => { const view3D = this._view3D; const controlBar = this._controlBar; const animator = view3D.animator; const root = this._rootEl; const name = this._nameEl; const itemList = this._itemListEl; const animations = animator.clips; const className = { ...controlBar.className, ...ControlBar.DEFAULT_CLASS }; while (itemList.firstChild) { itemList.removeChild(itemList.firstChild); } if (animations.length <= 0) { root.classList.add(className.DISABLED); return; } root.classList.remove(className.DISABLED); const elements = animations.map(animation => { const el = document.createElement(BROWSER.EL_DIV); el.classList.add(className.ANIMATION_ITEM); el.innerHTML = animation.name; return el; }); const selectAnimation = (animation: THREE.AnimationClip, idx: number) => { elements[idx].classList.add(className.ANIMATION_SELECTED); name.innerHTML = animation.name; }; animations.forEach((animation, idx) => { const el = elements[idx]; if (idx === animator.activeAnimationIndex) { selectAnimation(animation, idx); } el.addEventListener(BROWSER.EVENTS.CLICK, evt => { const wasPaused = animator.paused; animator.play(idx); if (wasPaused) { animator.pause(); } elements.forEach(element => { element.classList.remove(className.ANIMATION_SELECTED); }); selectAnimation(animation, idx); this._hideList(); evt.stopPropagation(); }); itemList.appendChild(el); }); }; private _toggleList = (evt: MouseEvent) => { const controlBar = this._controlBar; const itemList = this._itemListEl; const className = { ...controlBar.className, ...ControlBar.DEFAULT_CLASS }; itemList.classList.toggle(className.VISIBLE); if (itemList.classList.contains(className.VISIBLE)) { this._view3D.rootEl.addEventListener(BROWSER.EVENTS.CLICK, this._hideList); } evt.stopPropagation(); }; private _hideList = () => { const controlBar = this._controlBar; const itemList = this._itemListEl; const className = { ...controlBar.className, ...ControlBar.DEFAULT_CLASS }; if (itemList.classList.contains(className.VISIBLE)) { itemList.classList.remove(className.VISIBLE); } }; } export default AnimationSelector;