/**
* @module CanvasMenu
* @description My [dropdown menu]{@link https://github.com/anhr/commonNodeJS/tree/master/DropdownMenu} for canvas in my [three.js]{@link https://threejs.org/} projects.
*
* @author [Andrej Hristoliubov]{@link https://anhr.github.io/AboutMe/}
*
* @copyright 2011 Data Arts Team, Google Creative Lab
*
* @license under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
import three from '../three.js'
//import { lang } from '../controllerPlay/index.js';
//import { create as dropdownMenuCreate } from '../DropdownMenu/index.js';
import DropdownMenu from '../DropdownMenu/dropdownMenu.js';
//import StereoEffect from 'https://raw.githack.com/anhr/commonNodeJS/master/StereoEffect/StereoEffect.js';
import StereoEffect from '../StereoEffect/StereoEffect.js';
import CreateFullScreenSettings from '../createFullScreenSettings.js';
import Options from '../Options.js'
/**
* @callback onFullScreenToggle
* @param {boolean} fullScreen true - full screen mode of the canvas.
*/
class CanvasMenu {
/**
* @class Create [dropdown menu]{@link https://github.com/anhr/commonNodeJS/tree/master/DropdownMenu} for canvas in my [three.js]{@link https://threejs.org/} projects.
* @param {THREE.WebGLRenderer} renderer [WebGLRenderer]{@link https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer}
* @param {Object} [settings={}] the following settings are available
* @param {Array} [settings.menu] menu array. See <b>arrayMenu</b> of the [DropdownMenu.create]{@link https://raw.githack.com/anhr/commonNodeJS/master/DropdownMenu/jsdoc/module-DropdownMenu.html#~create}
* @param {Function} [settings.onOver] The event is fired at an Element when a pointing device (such as a mouse or trackpad) is used to move the cursor onto the element or one of its child elements.
* <pre>
* true - mouseenter event.
* false - mouseleave event.
* </pre>
*
* @param {Object} [settings.fullScreen] Add a "Full Screen" button
* <p>
* Full screen of the canvas see <b>settings.options.canvas.fullScreen</b>.
* </p>
* @param {onFullScreen} settings.fullScreen.camera [THREE.PerspectiveCamera]{@link https://threejs.org/docs/index.html#api/en/cameras/PerspectiveCamera}.
* @param {onFullScreenToggle} [settings.fullScreen.onFullScreenToggle] user toggled fullscreen mode of the canvas.
*
* @param {Options} [settings.options=new Options()] <a href="../../jsdoc/Options/Options.html" target="_blank">Options</a> instance. The following options are available.
* See <b>options</b> parameter of <a href="../../myThree/jsdoc/module-MyThree-MyThree.html" target="_blank">MyThree</a> class.
* @param {Player} [settings.options.player] <a href="../../Player/jsdoc/index.html" target="_blank">Player</a> instance. Playing of 3D ojbects in my projects.
* @param {StereoEffect} [settings.options.stereoEffect] <a href="../../StereoEffect/jsdoc/index.html" target="_blank">StereoEffect</a> instance.
* @param {boolean} [settings.options.canvas.fullScreen] Default canvas is full screen. false - no full screen
* @param {Function} [settings.options.getLanguageCode=language code of your browser] returns the "primary language" subtag of the version of the browser.
*/
constructor( renderer, settings = {} ) {
if ( !three.isThree() ) {
console.warn( 'CanvasMenu: Set THREE first.' )
return;
}
const THREE = three.THREE;
settings.options = settings.options || new Options();
const options = settings.options;
if ( !options.boOptions ) {
console.error( 'CanvasMenu: call options = new Options( options ) first' );
return;
}
if ( options.canvasMenu === false ) return;
options.canvasMenu = this;
//Localization
const lang = {
fullScreen: 'Full Screen',
nonFullScreen: 'Non Full Screen',
}
const getLanguageCode = options.getLanguageCode;
switch ( getLanguageCode() ) {
case 'ru'://Russian language
lang.prevSymbolTitle = 'Кадр назад';//'Go to previous animation scene',
lang.playTitle = 'Проиграть';//'Play'
lang.nextSymbolTitle = 'Кадр вперед';//'Go to next animation scene';
lang.pauseTitle = 'Пауза';//'Pause',
lang.repeatOn = 'Повторять проигрывание';
lang.repeatOff = 'Остановить повтор проигрывания';
lang.controllerTitle = 'Текущее время.';
lang.stereoEffects = 'Стерео эффекты';
lang.mono = 'Моно';
lang.sideBySide = 'Слева направо';
lang.topAndBottom = 'Сверху вниз';
break;
}
if ( THREE && ( renderer instanceof THREE.WebGLRenderer !== true ) ) {
console.error( 'CanvasMenu: renderer is not THREE.WebGLRenderer' );
return;
}
const elCanvas = renderer.domElement, elContainer = elCanvas.parentElement;
if ( elContainer.tagName !== "DIV" ) {
console.error( 'CanvasMenu: elContainer.tagName = ' + elContainer.tagName );
return;
}
const container = "container";
if ( !elContainer.classList.contains( "container" ) ) elContainer.classList.add( "container" );
settings.menu = settings.menu || [];
/**
* Menu array
* @array canvasMenu.
* menu
* @see <b>arrayMenu</b> of the [DropdownMenu.create]{@link https://raw.githack.com/anhr/commonNodeJS/master/DropdownMenu/jsdoc/module-DropdownMenu.html#~create}
*/
this.menu = settings.menu;
if ( settings.options.stereoEffect && settings.options.stereoEffect.createCanvasMenuItem )
settings.options.stereoEffect.createCanvasMenuItem( this, { getLanguageCode: options.getLanguageCode } );
if ( options.player ) { options.player.createCanvasMenuItem( this, getLanguageCode ); }
CreateFullScreenSettings.RendererSetSize( renderer, this );
//Full Screen button
var fullScreenSettings;
if ( settings.fullScreen !== undefined ) {
if ( !settings.fullScreen.camera ) {
console.error( 'CanvasMenu: settings.fullScreen.camera = ' + settings.fullScreen.camera );
return;
}
fullScreenSettings = new CreateFullScreenSettings( THREE, renderer, settings.fullScreen.camera,
{
canvasMenu: this,
fullScreen: settings.fullScreen,
} );
if ( options.canvas.fullScreen !== false )
fullScreenSettings.setFullScreen( false, true );
/**
* @param {StereoEffect} stereoEffect <a href="../../StereoEffect/jsdoc/index.html" target="_blank">StereoEffect</a>.
* @returns Set <b>stereoEffect</b> to <b>fullScreenSettings</b> and returns <a href="../../jsdoc/CreateFullScreenSettings/index.html" target="_blank">fullScreenSettings</a>.
*/
this.getFullScreenSettings = function ( stereoEffect ) {
fullScreenSettings.setStereoEffect( stereoEffect );
return fullScreenSettings;
}
/**
* @returns <b>true</b> if <b>canvas</b> is full screen.
*/
this.isFullScreen = function () { return fullScreenSettings.isFullScreen(); }
/**
* Sets the full screen of the canvas.
* @param {boolean} fullScreen false - full screen of the canvas.
*/
this.setFullScreen = function ( fullScreen ) { return fullScreenSettings.setFullScreen( fullScreen ); }
settings.menu.push( {
style: 'float: right;',
id: "menuButtonFullScreen",
onclick: function ( event ) { fullScreenSettings.onclick(); }
} );
}
//Play slider
if ( options.player ) options.player.addSlider();
const elMenu = DropdownMenu.create( settings.menu, {
elParent: typeof elContainer === "string" ? document.getElementById( elContainer ) : elContainer,
canvas: typeof elCanvas === "string" ? document.getElementById( elCanvas ) : elCanvas,
decorations: 'Transparent',
} );
/**
* @param {string} selectors See CSS selectors in [HTML DOM querySelector() Method]{@link https://www.w3schools.com/jsref/met_document_queryselector.asp} for details.
* @returns First element that matches a specified CSS selector(s) in the <b>canvasMenu</b>.
*/
this.querySelector = function ( selectors ) { return elMenu.querySelector( selectors ); }
elMenu.addEventListener( 'mouseenter', function ( event ) {
if ( settings.options.dat ) settings.options.dat.mouseenter = true;
if ( settings.onOver ) settings.onOver( true );
} );
elMenu.addEventListener( 'mouseleave', function ( event ) {
if ( settings.options.dat ) settings.options.dat.mouseenter = false;
if ( settings.onOver ) settings.onOver( false );
} );
if ( options.player ) options.player.addSliderEvents();// options.THREE );
if ( settings.fullScreen ) {
/**
* Sets the "Full Screen" button. Available only if <b>settings.fullScreen</b> is defined.
* @param {boolean} fullScreen true - non full screen.
* <p>false - full screen of the canvas.</p>
*/
this.setFullScreenButton = function ( fullScreen ) {
if ( fullScreen === undefined ) {
if ( options.canvas.fullScreen === false )
fullScreen = false;
else fullScreen = true;
}
const elMenuButtonFullScreen = elContainer.querySelector( '#menuButtonFullScreen' );//document.getElementById( 'menuButtonFullScreen' );
if ( elMenuButtonFullScreen === null )
return true;
if ( fullScreen ) {
elMenuButtonFullScreen.innerHTML = '⤦';
elMenuButtonFullScreen.title = lang.nonFullScreen;
} else {
elMenuButtonFullScreen.innerHTML = '⤢';
elMenuButtonFullScreen.title = lang.fullScreen;
}
return true;
}
this.setFullScreenButton();
if (
settings.options.stereoEffect &&
settings.options.stereoEffect.settings &&
( settings.options.stereoEffect.settings.spatialMultiplex !== StereoEffect.spatialMultiplexsIndexs.Mono )
)
this.setFullScreen( false );
}
/**
* Sets the size of the slider element of the player's menu.
* @param {Number} width width of the canvas
*/
this.setSize = function ( width ) {
if ( elMenu === undefined )
return;
var itemWidth = 0, elSlider;
for ( var i = 0; i < elMenu.childNodes.length; i++ ) {
var menuItem = elMenu.childNodes[i];
var computedStyle = window.getComputedStyle( menuItem ),
styleWidth =
parseInt( computedStyle["margin-left"] ) +
parseInt( computedStyle["margin-right"] ) +
parseInt( computedStyle["padding-left"] ) +
parseInt( computedStyle["padding-right"] )
;
var elSliderCur = menuItem.querySelector( '.slider' );
if ( elSliderCur === null )
itemWidth += menuItem.offsetWidth + styleWidth;
else {
elSlider = elSliderCur;
itemWidth += styleWidth;
}
}
if ( !elSlider )
return;//no controllerPlay
var sliderWidth = width - itemWidth;
if ( sliderWidth > 0 ) {
elSlider.parentElement.style.width = sliderWidth + 'px';
}
}
const size = { set: function ( width, height ) { this.x = width; this.y = height } };
renderer.getSize( size );
this.setSize( size.x, size.y );
if ( this.menu.length === 0 ) console.warn( 'CanvasMenu: menu is empty.' );
}
}
export default CanvasMenu;