Global frame duration scaling implemented

This commit is contained in:
Mal 2023-01-19 00:03:33 +01:00
parent aaee5ef34c
commit 288be2eac0
5 changed files with 303 additions and 3 deletions

72
public/graphics/app-icon Normal file
View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="89.076279mm"
height="59.384003mm"
viewBox="0 0 89.076279 59.384003"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="app-icon"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.4948513"
inkscape:cx="176.6062"
inkscape:cy="160.55109"
inkscape:window-width="1840"
inkscape:window-height="1011"
inkscape:window-x="80"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-58.395082,-106.02511)">
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290"
cx="-77.475471"
cy="167.1925"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-3"
cx="-43.482342"
cy="167.1925"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-6"
cx="-77.475471"
cy="201.18575"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-3-7"
cx="-43.482342"
cy="201.18575"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="89.076279mm"
height="59.384003mm"
viewBox="0 0 89.076279 59.384003"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="app-icon.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.4948513"
inkscape:cx="176.6062"
inkscape:cy="160.55109"
inkscape:window-width="1840"
inkscape:window-height="1011"
inkscape:window-x="80"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-58.395082,-106.02511)">
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290"
cx="-77.475471"
cy="167.1925"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-3"
cx="-43.482342"
cy="167.1925"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-6"
cx="-77.475471"
cy="201.18575"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
<circle
style="fill:#ff0000;stroke:none;stroke-width:16.721;stroke-linecap:round"
id="path290-3-7"
cx="-43.482342"
cy="201.18575"
r="13.813293"
transform="matrix(0.83205109,-0.55469901,0.83205109,0.55469901,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -5,6 +5,7 @@
<title>LED Cube</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="shortcut icon" type="application/svg+xml" href="graphics/app-icon.svg">
<script defer type="text/javascript" src="index.js"></script>
</head>
@ -39,6 +40,22 @@
<input type="number" id="frame-duration" class="suffix suffix-ms" min="1" step="1" max="65355" value="100" title="Frame-Dauer (ms)">
<div id="duration-scale">
<button id="button-scale-duration" class="icon-button icon-button-timer" title="Framedauer global ändern"></button>
<div id="global-duration-popup" class="submenu-popup">
<div class="value-slider">
<input id="global-duration-slider" style="flex-grow: 1" type="range" min="1" max="1000" step="1" value="100">
<span class="container-slider-value"><span id="global-duration-value" class="slider-value">100</span>%</span>
</div>
<div class="menu-fullscreen-button-line">
<button id="button-change-global-duration">Anpassen</button>
<button id="button-close-menu">Abbrechen</button>
</div>
</div>
</div>
<button id="button-add-frame-after" title="Frame danach hinzufügen">+</button>
<button id="button-delete-frame" class="icon-button icon-button-delete" title="Frame löschen" disabled></button>
</div>

View File

@ -216,6 +216,13 @@ const FrameMenu = function (id) {
this.htmlButtonToggleAnimation = this.html.querySelector('#button-toggle-animation');
this.htmlButtonDeleteFrame = this.html.querySelector('#button-delete-frame');
this.htmlInputDuration = this.html.querySelector('#frame-duration');
this.htmlMenuGlobalDuration = this.html.querySelector('#global-duration-popup');
this.htmlButtonGlobalDuration = this.html.querySelector('#button-scale-duration');
this.htmlGlobalDurationSlider = this.html.querySelector('#global-duration-slider');
this.htmlGlobalDurationValue = this.html.querySelector('#global-duration-value');
this.htmlButtonChangeGlobalDuration = this.html.querySelector('#button-change-global-duration');
this.htmlButtonCloseGlobalDurationPopup = this.html.querySelector('#button-close-menu');
this.isAnimationPlaying = false;
@ -267,6 +274,34 @@ const FrameMenu = function (id) {
}
);
this.htmlButtonGlobalDuration.addEventListener(
'click',
() => {
this.htmlMenuGlobalDuration.style.display = 'inherit';
}
);
this.htmlGlobalDurationSlider.addEventListener(
'input',
() => {
this.htmlGlobalDurationValue.innerText = this.htmlGlobalDurationSlider.value;
}
);
this.htmlButtonChangeGlobalDuration.addEventListener(
'click',
() => {
this.onChangeGlobalDuration();
}
);
this.htmlButtonCloseGlobalDurationPopup.addEventListener(
'click',
() => {
this.htmlMenuGlobalDuration.style.display = 'none';
}
)
this.slideToFrame = function (frameIndex) {
this.htmlSlider.value = frameIndex + 1;
this._updateFramePosition();
@ -300,6 +335,8 @@ const FrameMenu = function (id) {
this.onToggleAnimation = function () {}
this.onChangeGlobalDuration = function () {}
this._increaseSliderMax = function () {
const frameNumber = parseInt(this.htmlSlider.max) + 1;
@ -445,4 +482,15 @@ frameMenu.onFrameDelete = () => {
cube.currentFrame = cube.currentFrame < 0 ? 0 : cube.currentFrame;
frameMenu.slideToFrame(cube.currentFrame);
}
frameMenu.onChangeGlobalDuration = () => {
const factor = frameMenu.htmlGlobalDurationSlider.value / 100;
for (const frame of cube.frames) {
frame.duration *= factor;
}
frameMenu.htmlInputDuration.value = cube.frames[cube.currentFrame].duration;
frameMenu.htmlMenuGlobalDuration.style.display = 'none';
frameMenu,htmlGlobalDurationSlider.value = 100;
}

View File

@ -7,8 +7,10 @@ html {
}
body {
position: absolute;
width: 100%;
height: 100%;
top: 0;
bottom: 0;
padding: 0;
margin: 0;
background-color: black;
@ -92,9 +94,18 @@ button:hover {
justify-content: center;
align-items: center;
background-color: black;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
#animation-window {
position: fixed;
left: 0;
right: 0;
bottom: 50px;
display: flex;
justify-content: center;
align-items: center;
@ -106,6 +117,12 @@ button:hover {
padding: 20px;
display: flex;
align-items: center;
z-index: 1;
}
#frame-menu {
position: relative;
background-color: black;
}
#header-menu {
@ -129,7 +146,7 @@ button:hover {
#cube {
display: block;
padding-bottom: 80px;
padding-bottom: 200px;
}
.layer {
@ -185,6 +202,7 @@ button:hover {
.selector-display {
padding-right: 40px;
background-color: black;
background-image: url("graphics/icon-dropdown.svg");
background-repeat: no-repeat;
background-size: auto 8px;
@ -274,4 +292,77 @@ button:hover {
.row {
display: flex;
}
}
.menu-fullscreen {
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
justify-content: center;
align-items: center;
}
.submenu-popup {
display: none;
background-color: #091c59;
padding: 20px;
border: 2px solid white;
border-radius: 20px;
position: absolute;
right: -143px;
bottom: 57px;
box-shadow: 0 0 10px black;}
.submenu-popup::before {
position: absolute;
content: '';
width: 0;
height: 0;
bottom: -20px;
right: 50%;
border-width: 10px;
border-style: solid;
border-color: #091c59 #091c59 transparent transparent;
filter: drop-shadow(0 2px 0 white);
}
.submenu-popup::after {
position: absolute;
content: '';
width: 0;
height: 0;
bottom: -20px;
left: 50%;
border-width: 10px;
border-style: solid;
border-color: #091c59 transparent transparent #091c59;
filter: drop-shadow(0 2px 0 white);
}
.value-slider {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
}
.container-slider-value {
display: inline-block;
width: 55px;
}
.slider-value {
margin-left: 10px;
}
.menu-fullscreen-button-line {
display: flex;
justify-content: space-between;
}
#duration-scale {
position: relative;
}