Color selection and animation implemented
This commit is contained in:
parent
2dfb26bf13
commit
018142d257
49
public/graphics/icon-dropdown.svg
Normal file
49
public/graphics/icon-dropdown.svg
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="31.694466mm"
|
||||
height="15.84723mm"
|
||||
viewBox="0 0 31.694466 15.84723"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="icon-dropdown.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="0.74742565"
|
||||
inkscape:cx="220.75774"
|
||||
inkscape:cy="230.12323"
|
||||
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(-46.599199,-87.42651)">
|
||||
<path
|
||||
id="rect234"
|
||||
style="fill:#ffffff;stroke-width:0.264999;stroke-linecap:round;stroke-dasharray:1.06, 0.264999"
|
||||
d="M 78.293664,87.42651 62.446432,103.27374 46.599199,87.42651 Z"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -9,153 +9,37 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="cube-window">
|
||||
<div id="cube">
|
||||
<!--
|
||||
<div class="layer">
|
||||
<div class="row">
|
||||
<div class="led led-off"></div>
|
||||
<div class="led led-previous"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="layer-submenu">
|
||||
<div class="submenu-line"></div>
|
||||
<div class="layer-buttons">
|
||||
<div class="layer-button layer-button-on" title="Alle an"></div>
|
||||
<div class="layer-button layer-button-off" title="Alle aus"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="header-menu">
|
||||
<div id="color-selector" class="selector">
|
||||
<div class="selector-title">LED-Farbe</div>
|
||||
<div class="selector-display">Weiß</div>
|
||||
<div class="selector-items">
|
||||
<div class="selector-item">Weiß</div>
|
||||
<div class="selector-item">Rot</div>
|
||||
<div class="selector-item">Grün</div>
|
||||
<div class="selector-item">Blau</div>
|
||||
</div>
|
||||
|
||||
<div class="layer">
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layer">
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layer">
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
<div class="led"></div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="cube-window">
|
||||
<div id="cube"></div>
|
||||
</div>
|
||||
|
||||
<div id="animation-window">
|
||||
<div id="frame-menu">
|
||||
<button class="icon-button icon-button-play" id="button-play-frames" title="Animation abspielen"></button>
|
||||
<button id="button-stop-frames" class="icon-button icon-button-stop" title="Animation stoppen"></button>
|
||||
<button class="icon-button icon-button-play" id="button-toggle-animation" title="Animation abspielen" disabled></button>
|
||||
|
||||
<button id="button-add-frame-before" title="Frame davor hinzufügen">+</button>
|
||||
|
||||
<div id="frame-bar">
|
||||
<div id="frame-display">Frame: <span id="current-frame">1</span>/<span id="frame-number">1</span></div>
|
||||
<input id="frame-slider" type="range" step="1" min="1" max="1" value="1">
|
||||
</div>
|
||||
|
||||
<input type="number" class="suffix suffix-ms" min="1" step="1" max="65355" value="100" title="Frame-Dauer (ms)">
|
||||
<input type="number" id="frame-duration" class="suffix suffix-ms" min="1" step="1" max="65355" value="100" title="Frame-Dauer (ms)">
|
||||
|
||||
<button id="button-add-frame" title="Frame hinzufügen">+</button>
|
||||
<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"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
269
public/index.js
269
public/index.js
@ -3,6 +3,61 @@ const Frame = function (duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
const LED_COLOR = {
|
||||
WHITE: 0,
|
||||
RED: 1,
|
||||
GREEN: 2,
|
||||
BLUE: 3,
|
||||
}
|
||||
|
||||
const ANIMATION_FRAME_QUEUE = [];
|
||||
|
||||
const COLOR_CLASS = [];
|
||||
COLOR_CLASS[LED_COLOR.WHITE] = 'led-white';
|
||||
COLOR_CLASS[LED_COLOR.RED] = 'led-red';
|
||||
COLOR_CLASS[LED_COLOR.GREEN] = 'led-green';
|
||||
COLOR_CLASS[LED_COLOR.BLUE] = 'led-blue';
|
||||
|
||||
const Selector = function (id) {
|
||||
this.items = [];
|
||||
this.currentItem = 0;
|
||||
this.html = document.getElementById(id);
|
||||
this.htmlDisplay = this.html.querySelector('.selector-display');
|
||||
this.htmlItems = this.html.querySelector('.selector-items');
|
||||
|
||||
this.htmlItems.hidden = true;
|
||||
|
||||
this.htmlDisplay.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
this.htmlItems.hidden = !this.htmlItems.hidden;
|
||||
}
|
||||
);
|
||||
|
||||
for (const i in this.htmlItems.children) {
|
||||
this.htmlItems.children.item(i).addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
this.selectItem(i);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.onSelect = function () {};
|
||||
|
||||
this.selectItem = function (index) {
|
||||
this.htmlItems.hidden = true;
|
||||
|
||||
if (index !== this.currentItem) {
|
||||
this.currentItem = index;
|
||||
|
||||
this.htmlDisplay.innerHTML = this.htmlItems.children.item(index).innerHTML;
|
||||
|
||||
this.onSelect(index);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const FrameFactory = function (width, depth, height) {
|
||||
this.width = width;
|
||||
this.depth = depth;
|
||||
@ -43,8 +98,11 @@ const Cube = function (width, depth, height) {
|
||||
this._loadFrame(frameIndex);
|
||||
}
|
||||
|
||||
this.addFrame = function (frame) {
|
||||
this.frames.push(frame);
|
||||
}
|
||||
|
||||
this.switchLed = function (layerIndex, ledIndex) {
|
||||
console.log(layerIndex);
|
||||
this.frames[this.currentFrame].layers[layerIndex][ledIndex] = !this.frames[this.currentFrame].layers[layerIndex][ledIndex];
|
||||
}
|
||||
|
||||
@ -53,20 +111,34 @@ const Cube = function (width, depth, height) {
|
||||
this.frames[this.currentFrame].layers[layerIndex][index] = state;
|
||||
}
|
||||
|
||||
for (const row of this.html.children[this.height - layerIndex - 1].children) {
|
||||
for (const row of this.html.children.item(this.height - layerIndex - 1).children) {
|
||||
for (const led of row.children) {
|
||||
this._setLed(led, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setLedColor = function (color) {
|
||||
for (const layer of this.html.children) {
|
||||
for (const row of layer.children) {
|
||||
for (const led of row.children) {
|
||||
for (const cssClass of COLOR_CLASS) {
|
||||
led.classList.remove(cssClass);
|
||||
}
|
||||
|
||||
led.classList.add(COLOR_CLASS[color]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._loadFrame = function (frameIndex) {
|
||||
for (let layer = 0; layer < this.frames[frameIndex].layers.length; layer++) {
|
||||
for (let row = 0; row < this.depth; row++) {
|
||||
for (let led = 0; led < this.width; led++) {
|
||||
const state = this.frames[frameIndex].layers[layer][row * this.depth + led];
|
||||
|
||||
this._setLed(this.html.children[layer].children[row].children[led], state);
|
||||
this._setLed(this.html.children.item(this.height - layer - 1).children.item(row).children.item(led), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,6 +168,19 @@ const Cube = function (width, depth, height) {
|
||||
}
|
||||
);
|
||||
|
||||
led.addEventListener(
|
||||
'mouseover',
|
||||
(event) => {
|
||||
if (event.buttons === 1) {
|
||||
const index = y * this.depth + x;
|
||||
const layer = this.height - z - 1;
|
||||
|
||||
this.switchLed(layer, index);
|
||||
this._setLed(event.target, this.frames[this.currentFrame].layers[layer][index]);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
row.appendChild(led);
|
||||
}
|
||||
|
||||
@ -115,6 +200,110 @@ const Cube = function (width, depth, height) {
|
||||
}
|
||||
}
|
||||
|
||||
const FrameMenu = function (id) {
|
||||
this.html = document.getElementById(id);
|
||||
this.htmlSlider = this.html.querySelector('#frame-slider');
|
||||
this.htmlDisplayCurrentFrame = this.html.querySelector('#current-frame');
|
||||
this.htmlDisplayFrames = this.html.querySelector('#frame-number');
|
||||
this.htmlButtonAddFrameBefore = this.html.querySelector('#button-add-frame-before');
|
||||
this.htmlButtonAddFrameAfter = this.html.querySelector('#button-add-frame-after');
|
||||
this.htmlButtonToggleAnimation = this.html.querySelector('#button-toggle-animation');
|
||||
this.htmlInputDuration = this.html.querySelector('#frame-duration');
|
||||
|
||||
this.isAnimationPlaying = false;
|
||||
|
||||
this.htmlSlider.addEventListener(
|
||||
'input',
|
||||
() => {
|
||||
this._updateFramePosition();
|
||||
}
|
||||
);
|
||||
|
||||
this.htmlButtonAddFrameBefore.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
this._increaseSliderMax();
|
||||
this.onFramePrepend();
|
||||
}
|
||||
);
|
||||
|
||||
this.htmlButtonAddFrameAfter.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
this._increaseSliderMax();
|
||||
this.onFrameAppend();
|
||||
}
|
||||
);
|
||||
|
||||
this.htmlInputDuration.addEventListener(
|
||||
'input',
|
||||
() => {
|
||||
this.onInputDuration(this.htmlInputDuration.value);
|
||||
}
|
||||
);
|
||||
|
||||
this.htmlButtonToggleAnimation.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
this.isAnimationPlaying = !this.isAnimationPlaying;
|
||||
|
||||
this._updateToggleButton();
|
||||
this.onToggleAnimation(this.isAnimationPlaying);
|
||||
}
|
||||
);
|
||||
|
||||
this.slideToFrame = function (frameIndex) {
|
||||
this.htmlSlider.value = frameIndex + 1;
|
||||
this._updateFramePosition();
|
||||
}
|
||||
|
||||
this.setDuration = function (duration) {
|
||||
this.htmlInputDuration.value = duration;
|
||||
}
|
||||
|
||||
this.stopAnimation = function () {
|
||||
this.isAnimationPlaying = false;
|
||||
|
||||
this._updateToggleButton();
|
||||
}
|
||||
|
||||
this.onFramePrepend = function () {}
|
||||
|
||||
this.onFrameAppend = function () {}
|
||||
|
||||
this.onSlide = function () {}
|
||||
|
||||
this.onInputDuration = function () {}
|
||||
|
||||
this.onToggleAnimation = function () {}
|
||||
|
||||
this._increaseSliderMax = function () {
|
||||
const frameNumber = parseInt(this.htmlSlider.max) + 1;
|
||||
|
||||
this.htmlSlider.max = frameNumber;
|
||||
this.htmlDisplayFrames.innerText = frameNumber;
|
||||
|
||||
if (frameNumber > 1) {
|
||||
this.htmlButtonToggleAnimation.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
this._updateFramePosition = function () {
|
||||
this.htmlDisplayCurrentFrame.innerText = this.htmlSlider.value;
|
||||
this.onSlide(this.htmlSlider.value - 1);
|
||||
}
|
||||
|
||||
this._updateToggleButton = function () {
|
||||
if (this.isAnimationPlaying) {
|
||||
this.htmlButtonToggleAnimation.classList.add('icon-button-stop');
|
||||
this.htmlButtonToggleAnimation.classList.remove('icon-button-play');
|
||||
} else {
|
||||
this.htmlButtonToggleAnimation.classList.add('icon-button-play');
|
||||
this.htmlButtonToggleAnimation.classList.remove('icon-button-stop');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const WIDTH = 4;
|
||||
const DEPTH = 4;
|
||||
const HEIGHT = 4;
|
||||
@ -122,10 +311,76 @@ const HEIGHT = 4;
|
||||
const cube = new Cube(WIDTH, DEPTH, HEIGHT);
|
||||
cube.setup();
|
||||
|
||||
console.log(cube.html.children);
|
||||
|
||||
const frameFactory = new FrameFactory(WIDTH, DEPTH, HEIGHT);
|
||||
|
||||
cube.frames.push(frameFactory.getFrame(100));
|
||||
cube.frames.push(frameFactory.getFrame(500));
|
||||
cube.setCurrentFrame(0);
|
||||
cube.setLayer(2, true);
|
||||
cube.setLedColor(LED_COLOR.RED);
|
||||
|
||||
const colorSelector = new Selector('color-selector');
|
||||
colorSelector.onSelect = (index) => {
|
||||
cube.setLedColor(index);
|
||||
};
|
||||
colorSelector.selectItem(LED_COLOR.RED);
|
||||
|
||||
const frameMenu = new FrameMenu('frame-menu');
|
||||
frameMenu.onSlide = (frameIndex) => {
|
||||
cube.setCurrentFrame(frameIndex);
|
||||
frameMenu.setDuration(cube.frames[cube.currentFrame].duration);
|
||||
}
|
||||
frameMenu.onFramePrepend = () => {
|
||||
cube.frames = cube.frames.slice(0, cube.currentFrame).concat(
|
||||
[frameFactory.getFrame(cube.frames[cube.currentFrame].duration)].concat(
|
||||
cube.frames.slice(cube.currentFrame)
|
||||
)
|
||||
);
|
||||
|
||||
frameMenu.slideToFrame(cube.currentFrame - 1);
|
||||
}
|
||||
frameMenu.onFrameAppend = () => {
|
||||
cube.frames = cube.frames.slice(0, cube.currentFrame + 1).concat(
|
||||
[frameFactory.getFrame(cube.frames[cube.currentFrame].duration)].concat(
|
||||
cube.frames.slice(cube.currentFrame + 1)
|
||||
)
|
||||
);
|
||||
|
||||
frameMenu.slideToFrame(cube.currentFrame + 1);
|
||||
}
|
||||
frameMenu.onInputDuration = (duration) => {
|
||||
if (+duration <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cube.frames[cube.currentFrame].duration = +duration;
|
||||
}
|
||||
frameMenu.onToggleAnimation = (isPlaying) => {
|
||||
if (isPlaying) {
|
||||
let duration = 0;
|
||||
|
||||
for (let frame = cube.currentFrame; frame < cube.frames.length; frame++) {
|
||||
duration += cube.frames[frame].duration;
|
||||
|
||||
if (frame === cube.frames.length - 1) {
|
||||
setTimeout(
|
||||
() => {
|
||||
frameMenu.stopAnimation();
|
||||
},
|
||||
duration
|
||||
);
|
||||
}
|
||||
|
||||
ANIMATION_FRAME_QUEUE.push(
|
||||
setTimeout(
|
||||
() => {
|
||||
frameMenu.slideToFrame(frame + 1);
|
||||
},
|
||||
duration
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
for (const frame of ANIMATION_FRAME_QUEUE) {
|
||||
clearTimeout(frame);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
input {
|
||||
input, select {
|
||||
border: 2px solid white;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
@ -26,6 +26,10 @@ input {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=number] {
|
||||
max-width: 100px;
|
||||
}
|
||||
@ -42,6 +46,10 @@ button {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
filter: grayscale();
|
||||
}
|
||||
|
||||
.suffix-ms::after {
|
||||
content: "ms";
|
||||
}
|
||||
@ -88,7 +96,7 @@ button:hover {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#frame-menu {
|
||||
#frame-menu, #header-menu {
|
||||
border: 2px solid white;
|
||||
border-radius: 20px;
|
||||
padding: 20px;
|
||||
@ -96,6 +104,13 @@ button:hover {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#header-menu {
|
||||
border: none;
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
#frame-menu > * {
|
||||
margin: 0 10px;
|
||||
}
|
||||
@ -143,6 +158,48 @@ button:hover {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.selector-title {
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.selector-title::after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
.selector-display, .selector-items {
|
||||
border: 2px solid white;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
padding-bottom:12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector-display {
|
||||
padding-right: 40px;
|
||||
background-image: url("graphics/icon-dropdown.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: auto 8px;
|
||||
background-position: right 10px top 15px;
|
||||
}
|
||||
|
||||
.selector-items {
|
||||
border-radius: 0 0 10px 10px;
|
||||
position: relative;
|
||||
background-color: black;
|
||||
top: -8px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.selector-item {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.selector-item:hover {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.layer:hover .layer-submenu {
|
||||
visibility: visible;
|
||||
}
|
||||
@ -164,7 +221,7 @@ button:hover {
|
||||
}
|
||||
|
||||
.layer-button-on {
|
||||
background-color: red;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.layer-button-off {
|
||||
@ -172,14 +229,14 @@ button:hover {
|
||||
}
|
||||
|
||||
.led {
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px white;
|
||||
border-radius: 50%;
|
||||
background-color: red;
|
||||
width: 32px;
|
||||
height: 48px;
|
||||
margin: 8px 16px;
|
||||
transform: rotate(45deg);
|
||||
cursor: pointer;
|
||||
box-shadow: 0 0 10px red;
|
||||
}
|
||||
|
||||
.led-off {
|
||||
@ -193,14 +250,17 @@ button:hover {
|
||||
|
||||
.led-red {
|
||||
background-color: red;
|
||||
box-shadow: 0 0 10px red;
|
||||
}
|
||||
|
||||
.led-blue {
|
||||
background-color: #3333ff;
|
||||
box-shadow: 0 0 10px #3333ff;
|
||||
}
|
||||
|
||||
.led-green {
|
||||
background-color: #00ff00;
|
||||
box-shadow: 0 0 10px #00ff00;
|
||||
}
|
||||
|
||||
.row {
|
||||
|
Loading…
Reference in New Issue
Block a user