modern/js/interface.js
2021-01-17 17:17:19 +01:00

589 lines
18 KiB
JavaScript
Executable File

const interfaceWrapper = document.getElementById("interface-wrapper");
const moduleWrapper = document.createElement("div");
moduleWrapper.setAttribute("id", "module-wrapper");
interfaceWrapper.appendChild(moduleWrapper);
const isMobile = new RegExp(/Android|webOS|iPhone|iPad|BlackBerry|Windows Phone|Opera Mini|IEMobile|Mobile/).test(navigator.userAgent);
const styles = ["light", "medium", "heavy"];
let currentStyle = styles[0];
if (localStorage.style) {
currentStyle = styles[localStorage.style];
} else {
localStorage.style = "0";
}
const modules = [];
//GENERAL FUNCTIONS
function loadSVG(path, callback) {
let xhr = new XMLHttpRequest();
xhr.open("GET", path, true);
// Following line is just to be on the safe side;
// not needed if your server delivers SVG with correct MIME type
xhr.overrideMimeType("image/svg+xml");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status === 200) {
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
callback(xhr.responseXML.documentElement);
}
};
xhr.send();
}
function createModule(titleText) {
let div = document.createElement("div");
div.classList = ["module module-out"];
let title = document.createElement("h2");
title.innerHTML = titleText;
div.appendChild(title);
modules.push(div);
moduleWrapper.appendChild(div);
return div;
}
//STYLE SPECIFICS GENERATION
function createToggleCheckbox(scope, parent, config) {
let wrapper = document.createElement("div");
wrapper.classList = "module-row";
let header = document.createElement("h4");
header.style = "width: fit-content;position: absolute;right: 50%;";
header.innerHTML = config.name;
let container = document.createElement("label");
container.classList = "checkbox-container";
let checkBox = document.createElement("input");
if (config.default) {
checkBox.checked = "checked";
}
checkBox.type = "checkbox";
let span = document.createElement("span");
span.classList = "checkmark";
checkBox.addEventListener("input", function () {
config.callback(checkBox.checked);
}, false);
container.appendChild(checkBox);
container.appendChild(span);
wrapper.appendChild(header);
wrapper.appendChild(container);
parent.appendChild(wrapper);
}
function createToggleSwitch(scope, parent, config) {
let wrapper = document.createElement("div");
wrapper.classList = "module-row";
let header = document.createElement("h4");
header.innerHTML = config.name;
let switchContainer = document.createElement("label");
switchContainer.classList = "switch-container";
let checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.addEventListener("input", function () {
config.callback(checkbox.checked);
});
checkbox.checked = true //_default;
let span = document.createElement("span");
span.classList = "slider";
wrapper.appendChild(header);
switchContainer.appendChild(checkbox);
switchContainer.appendChild(span);
wrapper.appendChild(switchContainer);
parent.appendChild(wrapper);
}
function createToggleTabs(scope, parent, config) {
let wrapper = document.createElement("div");
wrapper.classList.add("module-row");
let buttonWrapper = document.createElement("div");
buttonWrapper.classList.add("toggle-wrapper");
let header = document.createElement("h4");
let left = document.createElement("div");
let pL = document.createElement("p");
pL.innerHTML = "An";
left.appendChild(pL);
left.classList = "toggle-left";
let right = document.createElement("div");
let pR = document.createElement("p");
pR.innerHTML = "Aus";
right.appendChild(pR);
left.classList = "toggle-left";
right.innerHMTL = "Aus";
right.classList = "toggle-right";
left.addEventListener("click", function () {
left.classList.add("toggle-active");
right.classList.remove("toggle-active");
config.callback(true);
});
right.addEventListener("click", function () {
left.classList.remove("toggle-active");
right.classList.add("toggle-active");
config.callback(false);
});
//SET THE DEFAULTS
if (config.default) {
left.classList.add("toggle-active");
} else {
right.classList.add("toggle-active");
}
header.innerHTML = name;
wrapper.appendChild(header);
buttonWrapper.appendChild(left);
buttonWrapper.appendChild(right);
wrapper.appendChild(buttonWrapper);
parent.appendChild(wrapper);
}
//GENERAL INTERFACE GENERATION
function createButton(scope, parent, config) {
let div = document.createElement("div");
let title = document.createElement("h4");
div.classList.add("button");
title.innerHTML = config.name;
div.appendChild(title);
parent.appendChild(div);
div.addEventListener("click", function () {
callback();
}, false);
};
function createSlider(scope, parent, config) {
let div = document.createElement("div");
div.classList.add("module-row");
let title = document.createElement("h4");
title.innerHTML = config.name + " " + config.default * 100 + " %";
let slider = document.createElement("input");
slider.value = config.default * 100;
slider.type = "range";
slider.min = config.min;
slider.max = config.max;
slider.addEventListener("input", function () {
config.callback(slider.value);
title.innerHTML = config.name + " " + slider.value + "%";
});
function handleOut() {
moduleWrapper.style.transition = "all 0s";
title.style.visibility = "visible";
interfaceWrapper.style.visibility = "hidden";
moduleWrapper.style.visibility = "hidden";
slider.style.visibility = "visible";
scope.rendering = true;
}
function handleIn() {
moduleWrapper.style.transition = "";
interfaceWrapper.style.visibility = "";
title.style.visibility = "";
moduleWrapper.style.visibility = "visible";
slider.style.visibility = "";
scope.rendering = false;
}
//HIDE THE BACKGROUND ON CHANGE
if (config.name === "Render Auflösung") {
slider.id = "render-quality-slider";
title.id = "render-quality-title";
if (isMobile) {
slider.addEventListener("touchstart", function () {
handleOut();
}, false);
slider.addEventListener("touchend", function () {
handleIn();
}, false);
slider.addEventListener("touchcancel", function () {
handleIn();
}, false);
} else {
slider.addEventListener("mousedown", function () {
handleOut();
}, false);
slider.addEventListener("mouseup", function () {
handleIn();
}, false);
}
}
div.appendChild(title);
div.appendChild(slider);
parent.appendChild(div);
}
function createToggle(scope, parent, config) {
switch (currentStyle) {
case "light":
createToggleSwitch(scope, parent, config);
break;
case "medium":
createToggleCheckbox(scope, parent, config);
break;
case "heavy":
createToggleTabs(scope, parent, config);
break;
default:
break;
}
}
function createDropdown(scope, parent, config) {
let wrapper = document.createElement("div");
wrapper.classList = "module-row";
let header = document.createElement("h4");
header.innerHTML = name;
let selectWrapper = document.createElement("div");
selectWrapper.classList = "select-wrapper";
let select = document.createElement("select");
let active;
for (let i = 0; i < config.options.length; i++) {
let _option = document.createElement("option");
_option.innerHTML = config.options[i];
_option.setAttribute("value", i);
if (localStorage.style == styles.indexOf(config.options[i])) {
_option.selected = "selected";
active = _option;
}
select.appendChild(_option);
}
select.addEventListener("change", function (ev) {
header.innerHTML = ev.srcElement.innerHTML;
config.callback(this.value);
});
wrapper.appendChild(header);
selectWrapper.append(select);
wrapper.appendChild(selectWrapper);
parent.appendChild(wrapper);
}
//EXPORT CLASS
export default class UserInterface {
constructor(lights, renderer, controls) {
var scope = this;
this.rendering = true;
this.state = false;
this.fullscreenState = false;
//SET CURRENT STYLE
interfaceWrapper.classList = currentStyle;
this.config = [
{
name: "Qualität",
children: [{
type: "slider",
mobileOnly: false,
name: "Render Auflösung",
default: renderer.getPixelRatio(),
min: 20,
max: 200,
callback: function (val) {
renderer.setPixelRatio(val / 100);
}
},
{
type: "toggle",
mobileOnly: false,
name: "High Quality Lights",
default: lights.state,
callback: function (val) {
if (val) {
lights.enable();
} else {
lights.disable();
}
}
}
]
},
{
name: "Steuerung",
children: [{
type: "slider",
mobileOnly: false,
name: "Geschwindigkeit",
default: controls.lookSpeed,
min: 0,
max: 200,
callback: function (val) {
controls.lookSpeed = val / 100;
localStorage.lookSpeed = controls.lookSpeed;
}
},
{
type: "toggle",
mobileOnly: false,
name: "Nachziehen",
default: controls.drag,
callback: function (val) {
controls.drag = val;
localStorage.drag = controls.drag;
}
},
{
type: "toggle",
mobileOnly: false,
name: "Automatisch drehen",
default: controls.autoRotate,
callback: function (val) {
controls.autoRotate = val;
localStorage.autoRotate = controls.autoRotate;
}
},
{
type: "toggle",
mobileOnly: true,
name: "Geräte Drehung nutzen",
default: controls.deviceorientation,
callback: function (val) {
controls.deviceorientation = val;
localStorage.deviceorientation = controls.deviceorientation;
}
},
{
type: "slider",
mobileOnly: true,
name: "Geräte Drehung Geschwindigkeit",
default: controls.deviceorientationSpeed * 100,
min: 10,
max: 150,
callback: function (val) {
controls.deviceorientationSpeed = val / 1000;
localStorage.deviceorientationSpeed = controls.deviceorientationSpeed;
}
},
{
type: "button",
mobileOnly: false,
name: "Kamera zurücksetzen",
callback: function () {
controls.reset();
}
}
]
},
{
name: "Interface",
children: [{
type: "dropdown",
mobileOnly: false,
name: "Stil",
options: [
"light",
"medium",
"heavy"
],
callback: function (val) {
scope.setStyle(val);
console.log("Setting val " + val);
localStorage.style = val;
}
}]
}
];
this.loadConfig();
}
loadConfig(callback) {
var scope = this;
//LOAD THE COGWHEEL OPTIONS
loadSVG("./icons/" + currentStyle + "_options.svg", (svg) => {
this.cogwheel = svg;
this.cogwheel.classList = "cogwheel";
this.cogwheel.addEventListener("click", () => {
this.toggle();
}, false);
interfaceWrapper.insertBefore(this.cogwheel, interfaceWrapper.firstChild);
});
//LOAD THE FULLSCREEN ICON
loadSVG("./icons/" + currentStyle + "_fullscreen.svg", (svg) => {
this.fullscreen = svg;
this.fullscreen.classList = "fullscreen";
this.fullscreen.addEventListener("click", () => {
this.toggleFullscreen();
}, false);
interfaceWrapper.insertBefore(this.fullscreen, interfaceWrapper.firstChild);
});
//CREATE ALL CHILDREN OF THE MODULE
for (let i = 0; i < this.config.length; i++) {
let _module = createModule(this.config[i].name);
for (let j = 0; j < this.config[i].children.length; j++) {
let obj = this.config[i].children[j];
if (isMobile === false && obj.mobileOnly === true) {
//DONT DO ANYTHING
} else {
//CREATE HAIR LINES
if (currentStyle !== "heavy") {
let hr = document.createElement("hr");
_module.appendChild(hr);
}
switch (obj.type) {
case "toggle":
createToggle(this, _module, obj);
break;
case "slider":
createSlider(this, _module, obj);
break;
case "button":
createButton(this, _module, obj);
break;
case "dropdown":
createDropdown(this, _module, obj);
break;
default:
break;
}
}
}
}
if (callback) {
callback();
}
}
toggleFullscreen() {
if (this.fullscreenState) {
this.fullscreenState = false;
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
} else {
this.fullscreenState = true;
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullscreen) {
document.documentElement.webkitRequestFullscreen();
} else if (document.documentElement.msRequestFullscreen) {
document.documentElement.msRequestFullscreen();
}
}
}
setStyle(style) {
var scope = this;
modules.length = 0;
currentStyle = styles[style];
interfaceWrapper.classList = currentStyle;
//REMOVE ALL CHILDREN
while (moduleWrapper.firstChild) {
moduleWrapper.removeChild(moduleWrapper.firstChild);
}
interfaceWrapper.removeChild(this.cogwheel);
interfaceWrapper.removeChild(this.fullscreen);
this.loadConfig(function () {
scope.animIn();
});
}
setRenderQuality(val) {
document.getElementById("render-quality-slider").value = Math.floor(val * 100);
document.getElementById("render-quality-title").innerHTML = "Render Auflösung " + Math.floor(val * 100) + "%";
}
animIn() {
this.state = true;
interfaceWrapper.classList.add("interface-in");
this.cogwheel.classList.add("cogwheel-in");
let i = modules.length - 1;
modules[i].classList.remove("module-out");
let int = window.setInterval(function () {
i--;
if (i >= 0) {
modules[i].classList.remove("module-out");
} else {
moduleWrapper.style.visibility = "visible";
clearInterval(int);
}
}, 100);
}
animOut() {
this.state = false;
interfaceWrapper.classList.remove("interface-in");
this.cogwheel.classList.remove("cogwheel-in");
let i = modules.length - 1;
modules[i].classList.add("module-out");
let int = window.setInterval(function () {
i--;
if (i >= 0) {
modules[i].classList.add("module-out");
} else {
moduleWrapper.style.visibility = "hidden";
clearInterval(int);
}
}, 100);
}
toggle() {
if (this.state) {
this.animOut();
this.rendering = true;
} else {
this.rendering = false;
this.animIn();
}
}
}