@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
128 lines (118 loc) • 4.18 kB
text/typescript
// import {Camera} from 'three';
import {isBooleanTrue} from '../../../core/Type';
import {RootManagerNode} from '../../nodes/manager/Root';
import {BaseViewerType} from '../_Base';
const ICON = {
ON: `<svg xmlns="http://www.w3.org/2000/svg" class="soundOn h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
</svg>`,
OFF: `<svg xmlns="http://www.w3.org/2000/svg" class="soundOff h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" clip-rule="evenodd" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
</svg>`,
};
export class ViewerAudioController {
private __iconContainer: HTMLElement | undefined;
private _onIcon: HTMLElement | undefined;
private _offIcon: HTMLElement | undefined;
constructor(private _viewer: BaseViewerType) {}
update() {
const root = this._viewer.scene().root();
if (isBooleanTrue(root.pv.displayAudioIcon)) {
this._showIcon();
this._updateIcon(root);
} else {
this._hideIcon();
}
}
unmount() {
if (this.__iconContainer) {
this.__iconContainer.parentElement?.removeChild(this.__iconContainer);
this.__iconContainer = undefined;
}
this._onIcon = undefined;
this._offIcon = undefined;
}
private _showIcon() {
const element = this._iconContainer();
if (element) {
element.style.display = 'block';
}
}
private _hideIcon() {
if (this.__iconContainer) {
this.__iconContainer.style.display = 'none';
}
}
private _iconContainer() {
const createIconContainer = () => {
const element = this._createIconContainer();
const domElement = this._viewer.domElement();
if (!domElement) {
return;
}
domElement.append(element);
return element;
};
return (this.__iconContainer = this.__iconContainer || createIconContainer());
}
private _createIconContainer() {
const element = document.createElement('div');
element.addEventListener('pointerdown', (event) => {
this._toggleSound();
event.preventDefault();
event.stopPropagation();
return false;
});
return element;
}
private _setIconContainerStyle(element: HTMLElement, root: RootManagerNode) {
// const style = 'position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; cursor: pointer'
const style = root.pv.audioIconStyle;
element.setAttribute('style', style);
element.style.color = root.pv.audioIconColor.getStyle();
// element.style.position = 'absolute';
// element.style.top = '10px';
// element.style.right = '10px';
// element.style.width = '24px';
// element.style.height = '24px';
// element.style.cursor = 'pointer';
}
private offIcon() {
function createIcon() {
const icon = document.createElement('div');
icon.innerHTML = ICON.OFF;
return icon.children[0] as HTMLElement;
}
return (this._offIcon = this._offIcon || createIcon());
}
private onIcon() {
function createIcon() {
const icon = document.createElement('div');
icon.innerHTML = ICON.ON;
return icon.children[0] as HTMLElement;
}
return (this._onIcon = this._onIcon || createIcon());
}
private _toggleSound() {
const root = this._viewer.scene().root();
root.audioController.toggleSound();
this._updateIcon(root);
}
private _updateIcon(root: RootManagerNode) {
const container = this._iconContainer();
if (!container) {
return;
}
this._setIconContainerStyle(container, root);
const onIcon = this.onIcon();
const offIcon = this.offIcon();
if (this._viewer.scene().root().audioController.soundOn()) {
container.appendChild(onIcon);
offIcon.parentElement?.removeChild(offIcon);
} else {
container.appendChild(offIcon);
onIcon.parentElement?.removeChild(onIcon);
}
}
}