1065 lines
46 KiB
HTML
1065 lines
46 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="pt_BR">
|
||
|
<head>
|
||
|
<meta charset="UTF-8" />
|
||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
|
<!--link
|
||
|
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||
|
rel="stylesheet"
|
||
|
/-->
|
||
|
<link
|
||
|
rel="shortcut icon"
|
||
|
href="data:image/png;base64,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"
|
||
|
/>
|
||
|
<title>Pixel Magic Tool - @ajotanc</title>
|
||
|
</head>
|
||
|
<style>
|
||
|
* {
|
||
|
box-sizing: border-box;
|
||
|
}
|
||
|
|
||
|
::selection {
|
||
|
background: #1982c4;
|
||
|
color: #ffffff;
|
||
|
}
|
||
|
|
||
|
html {
|
||
|
scroll-behavior: smooth;
|
||
|
}
|
||
|
|
||
|
body {
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
min-height: 100vh;
|
||
|
margin: 0;
|
||
|
font-size: 12px;
|
||
|
font-family: "Tahoma", monospace;
|
||
|
}
|
||
|
|
||
|
h1,
|
||
|
h2,
|
||
|
h3,
|
||
|
h4,
|
||
|
h5,
|
||
|
h6 {
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
h3 {
|
||
|
color: #5f5f5f;
|
||
|
}
|
||
|
|
||
|
.divider {
|
||
|
width: calc(100% - 10px);
|
||
|
height: 1px;
|
||
|
background: #ececec;
|
||
|
margin: 20px auto;
|
||
|
}
|
||
|
|
||
|
.container {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
|
||
|
.content {
|
||
|
width: 100%;
|
||
|
min-width: 540px;
|
||
|
max-width: 900px;
|
||
|
margin: 20px;
|
||
|
}
|
||
|
|
||
|
#response,
|
||
|
#preview,
|
||
|
#image,
|
||
|
form,
|
||
|
canvas {
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
form {
|
||
|
margin: 0 auto;
|
||
|
padding: 20px;
|
||
|
background-color: #f8f8f8;
|
||
|
border-radius: 8px;
|
||
|
border: 1px solid #cccccc;
|
||
|
}
|
||
|
|
||
|
.row {
|
||
|
display: flex;
|
||
|
flex-wrap: wrap;
|
||
|
justify-content: space-between;
|
||
|
margin: 20px 0 0;
|
||
|
}
|
||
|
|
||
|
.row:nth-child(2) {
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
.column {
|
||
|
flex-basis: calc(50% - 10px);
|
||
|
|
||
|
position: relative;
|
||
|
padding: 0 5px;
|
||
|
}
|
||
|
|
||
|
label {
|
||
|
display: block;
|
||
|
margin-bottom: 5px;
|
||
|
font-weight: bold;
|
||
|
}
|
||
|
|
||
|
button {
|
||
|
font-family: "Tahoma", monospace;
|
||
|
}
|
||
|
|
||
|
input[type="text"],
|
||
|
input[type="number"],
|
||
|
input[type="email"],
|
||
|
input[type="tel"],
|
||
|
select,
|
||
|
textarea {
|
||
|
width: 100%;
|
||
|
padding: 10px;
|
||
|
border-radius: 5px;
|
||
|
border: none;
|
||
|
background-color: #f0f0f0;
|
||
|
font-size: 12px;
|
||
|
display: inline-block;
|
||
|
font-family: "Tahoma", monospace;
|
||
|
outline: none;
|
||
|
}
|
||
|
|
||
|
input[type="color"] {
|
||
|
width: 32px;
|
||
|
height: 32px;
|
||
|
cursor: pointer;
|
||
|
padding: 0px 1px;
|
||
|
outline: none;
|
||
|
}
|
||
|
|
||
|
.input-group {
|
||
|
display: flex;
|
||
|
}
|
||
|
|
||
|
.input-group input {
|
||
|
border-radius: 5px 0 0 5px;
|
||
|
}
|
||
|
|
||
|
.input-description {
|
||
|
padding: 10px;
|
||
|
font-size: 14px;
|
||
|
color: #626262;
|
||
|
background: #d9d9d9;
|
||
|
border-radius: 0px 5px 5px 0;
|
||
|
}
|
||
|
|
||
|
select {
|
||
|
appearance: none;
|
||
|
-webkit-appearance: none;
|
||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M.6 2.6L4 6l3.4-3.4L8 3.2 4 7.2.1 3.3z'/%3E%3C/svg%3E");
|
||
|
background-repeat: no-repeat;
|
||
|
background-position: right 10px center;
|
||
|
background-size: 10px 10px;
|
||
|
}
|
||
|
|
||
|
textarea {
|
||
|
resize: vertical;
|
||
|
min-height: 120px;
|
||
|
margin: 0 0 10px;
|
||
|
}
|
||
|
|
||
|
input[type="submit"] {
|
||
|
padding: 10px 20px;
|
||
|
border: none;
|
||
|
border-radius: 5px;
|
||
|
background-color: #4caf50;
|
||
|
color: #fff;
|
||
|
font-size: 12px;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
.dropzone {
|
||
|
width: 100%;
|
||
|
border: 1px dashed #a9a9a9;
|
||
|
background-color: #f5f5f5;
|
||
|
color: #666;
|
||
|
font-size: 12px;
|
||
|
text-align: center;
|
||
|
padding: 40px 10px;
|
||
|
border-radius: 5px;
|
||
|
margin: 20px 0;
|
||
|
transition: all 0.5s ease-in-out;
|
||
|
}
|
||
|
|
||
|
.dropzone p {
|
||
|
margin: 0;
|
||
|
padding: 0;
|
||
|
}
|
||
|
|
||
|
.dropzone:hover {
|
||
|
cursor: pointer;
|
||
|
background-color: #eee;
|
||
|
}
|
||
|
|
||
|
.dropzone.dragover {
|
||
|
background-color: #ddd;
|
||
|
}
|
||
|
|
||
|
.range-slider {
|
||
|
appearance: none;
|
||
|
background-color: #ddd;
|
||
|
height: 8px;
|
||
|
width: 100%;
|
||
|
border-radius: 10px;
|
||
|
outline: none;
|
||
|
margin: 16px 0;
|
||
|
}
|
||
|
|
||
|
.range-slider::-webkit-slider-thumb {
|
||
|
appearance: none;
|
||
|
height: 16px;
|
||
|
width: 16px;
|
||
|
background-color: #4caf50;
|
||
|
border-radius: 50%;
|
||
|
cursor: pointer;
|
||
|
border: 0;
|
||
|
}
|
||
|
|
||
|
.range-slider::-moz-range-thumb {
|
||
|
appearance: none;
|
||
|
height: 16px;
|
||
|
width: 16px;
|
||
|
background-color: #4caf50;
|
||
|
border-radius: 50%;
|
||
|
cursor: pointer;
|
||
|
border: 0;
|
||
|
}
|
||
|
|
||
|
.switch {
|
||
|
position: relative;
|
||
|
display: inline-block;
|
||
|
width: 38px;
|
||
|
height: 20px;
|
||
|
}
|
||
|
|
||
|
.switch input {
|
||
|
outline: none;
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
.switch-slider {
|
||
|
position: absolute;
|
||
|
cursor: pointer;
|
||
|
top: 0;
|
||
|
left: 0;
|
||
|
right: 0;
|
||
|
bottom: 0;
|
||
|
background-color: #ccc;
|
||
|
border-radius: 34px;
|
||
|
transition: 0.4s;
|
||
|
}
|
||
|
|
||
|
.switch-slider:before {
|
||
|
position: absolute;
|
||
|
content: "";
|
||
|
height: 14px;
|
||
|
width: 14px;
|
||
|
left: 3px;
|
||
|
bottom: 3px;
|
||
|
background-color: white;
|
||
|
border-radius: 50%;
|
||
|
transition: 0.4s;
|
||
|
}
|
||
|
|
||
|
input:checked + .switch-slider {
|
||
|
background-color: #4caf50;
|
||
|
}
|
||
|
|
||
|
input:focus + .switch-slider {
|
||
|
box-shadow: 0 0 1px #4caf50;
|
||
|
}
|
||
|
|
||
|
input:checked + .switch-slider:before {
|
||
|
transform: translateX(18px);
|
||
|
}
|
||
|
|
||
|
#toast-container {
|
||
|
position: fixed;
|
||
|
bottom: 20px;
|
||
|
right: 20px;
|
||
|
z-index: 9999;
|
||
|
}
|
||
|
|
||
|
.toast {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: space-between;
|
||
|
width: max-content;
|
||
|
padding: 6px 12px;
|
||
|
margin: 10px 0 0;
|
||
|
border-radius: 8px;
|
||
|
color: #fff;
|
||
|
font-size: 12px;
|
||
|
|
||
|
transform: translateY(30px);
|
||
|
opacity: 0;
|
||
|
visibility: hidden;
|
||
|
}
|
||
|
|
||
|
.toast-icon {
|
||
|
font-size: 22px;
|
||
|
margin-right: 8px;
|
||
|
}
|
||
|
|
||
|
.toast .toast-body {
|
||
|
padding: 8px 0;
|
||
|
color: #fdfdfd;
|
||
|
}
|
||
|
|
||
|
.toast.success {
|
||
|
background-color: #8ac926;
|
||
|
}
|
||
|
|
||
|
.toast.error {
|
||
|
background-color: #ff595e;
|
||
|
}
|
||
|
|
||
|
.toast.warning {
|
||
|
background-color: #ffca3a;
|
||
|
}
|
||
|
|
||
|
.toast-progress {
|
||
|
position: absolute;
|
||
|
left: 4px;
|
||
|
bottom: 4px;
|
||
|
width: calc(100% - 8px);
|
||
|
height: 3px;
|
||
|
transform: scaleX(0);
|
||
|
transform-origin: left;
|
||
|
border-radius: inherit;
|
||
|
}
|
||
|
|
||
|
.toast.success .toast-progress {
|
||
|
background: linear-gradient(to right, #8ac926, #c5ca30);
|
||
|
}
|
||
|
|
||
|
.toast.error .toast-progress {
|
||
|
background: linear-gradient(to right, #ff595e, #e23c4e);
|
||
|
}
|
||
|
|
||
|
.toast.warning .toast-progress {
|
||
|
background: linear-gradient(to right, #ffca3a, #ffda3d);
|
||
|
}
|
||
|
|
||
|
#multipleCanvas {
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
flex-direction: column;
|
||
|
position: relative;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .controls {
|
||
|
width: 100%;
|
||
|
position: absolute;
|
||
|
display: none;
|
||
|
justify-content: space-between;
|
||
|
align-items: center;
|
||
|
padding: 0 23px;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .controls button {
|
||
|
border: 0;
|
||
|
outline: 0;
|
||
|
width: 46px;
|
||
|
height: 46px;
|
||
|
background: rgba(0, 0, 0, 0.3);
|
||
|
color: #fdfdfd;
|
||
|
text-align: center;
|
||
|
font-size: 22px;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .controls span {
|
||
|
vertical-align: middle;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .carousel {
|
||
|
display: flex;
|
||
|
height: 100%;
|
||
|
width: 100%;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .carousel img {
|
||
|
display: block;
|
||
|
width: 100%;
|
||
|
height: 100%;
|
||
|
margin-right: 20px;
|
||
|
border: 0;
|
||
|
}
|
||
|
|
||
|
#multipleCanvas .carousel img:last-child {
|
||
|
margin-right: 0;
|
||
|
}
|
||
|
|
||
|
.button {
|
||
|
width: 100%;
|
||
|
border: 0;
|
||
|
padding: 10px 18px;
|
||
|
border-radius: 4px;
|
||
|
color: #fdfdfd;
|
||
|
cursor: pointer;
|
||
|
margin: 0 0 10px;
|
||
|
background: #1982c4;
|
||
|
transition: all 0.5s ease-in-out;
|
||
|
}
|
||
|
|
||
|
.button:hover {
|
||
|
background: #4267ac;
|
||
|
}
|
||
|
|
||
|
.button:last-child {
|
||
|
margin-bottom: 0;
|
||
|
}
|
||
|
|
||
|
.buttons {
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
.buttonRainbow {
|
||
|
width: 100%;
|
||
|
border: 0;
|
||
|
padding: 10px 18px;
|
||
|
border-radius: 4px;
|
||
|
color: #fdfdfd;
|
||
|
cursor: pointer;
|
||
|
background: linear-gradient(
|
||
|
to right,
|
||
|
#ff595e,
|
||
|
#ffca3a,
|
||
|
#8ac926,
|
||
|
#1982c4,
|
||
|
#6a4c93
|
||
|
);
|
||
|
}
|
||
|
|
||
|
.buttonRainbow:hover {
|
||
|
animation-play-state: paused;
|
||
|
}
|
||
|
|
||
|
#preview {
|
||
|
border: 1px solid #cccccc;
|
||
|
padding: 20px;
|
||
|
margin: 20px 0;
|
||
|
border-radius: 8px;
|
||
|
}
|
||
|
|
||
|
#preview .buttons {
|
||
|
margin: 0 0 20px;
|
||
|
}
|
||
|
|
||
|
.w-full {
|
||
|
flex-basis: 100% !important;
|
||
|
}
|
||
|
|
||
|
.margin-zero {
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
#overlay {
|
||
|
position: fixed;
|
||
|
top: 0;
|
||
|
left: 0;
|
||
|
width: 100%;
|
||
|
height: 100%;
|
||
|
background-color: rgba(0, 0, 0, 0.5);
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
#overlay.loading::after {
|
||
|
content: "";
|
||
|
display: block;
|
||
|
position: absolute;
|
||
|
top: calc(50% - 19px);
|
||
|
left: calc(50% - 19px);
|
||
|
width: 26px;
|
||
|
height: 26px;
|
||
|
border: 6px solid rgba(255, 255, 255, 0.5);
|
||
|
border-radius: 50%;
|
||
|
animation: spin 1s linear infinite;
|
||
|
}
|
||
|
|
||
|
input.invalid,
|
||
|
select.invalid,
|
||
|
textarea.invalid {
|
||
|
border: 1px solid #df1f1f;
|
||
|
}
|
||
|
|
||
|
input.invalid + .error-message,
|
||
|
select.invalid + .error-message,
|
||
|
textarea.invalid + .error-message {
|
||
|
display: block;
|
||
|
color: #df1f1f;
|
||
|
padding: 4px 0;
|
||
|
font-size: 14px;
|
||
|
font-weight: 600;
|
||
|
}
|
||
|
|
||
|
.slide-container {
|
||
|
width: 100%;
|
||
|
display: flex;
|
||
|
overflow-x: auto;
|
||
|
scroll-snap-type: x mandatory;
|
||
|
}
|
||
|
|
||
|
.slide {
|
||
|
scroll-snap-align: center;
|
||
|
}
|
||
|
|
||
|
.header {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
padding: 0 0 30px;
|
||
|
flex-direction: column;
|
||
|
}
|
||
|
|
||
|
.header .brand {
|
||
|
width: 100%;
|
||
|
max-width: 300px;
|
||
|
height: 100%;
|
||
|
display: block;
|
||
|
outline: none;
|
||
|
border: 0;
|
||
|
}
|
||
|
|
||
|
.header .title {
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
.github {
|
||
|
display: flex;
|
||
|
overflow: hidden;
|
||
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||
|
sans-serif;
|
||
|
font-size: 0;
|
||
|
line-height: 0;
|
||
|
white-space: nowrap;
|
||
|
font-size: 12px;
|
||
|
color: #24292f;
|
||
|
font-weight: 600;
|
||
|
margin: 10px 0;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
|
||
|
.github .widget {
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
margin-right: 5px;
|
||
|
}
|
||
|
|
||
|
.github .button {
|
||
|
margin: 0;
|
||
|
width: auto;
|
||
|
padding: 5px 10px;
|
||
|
color: #24292f;
|
||
|
background: #ebf0f4;
|
||
|
border: 1px solid rgba(31, 35, 40, 0.15);
|
||
|
background-image: linear-gradient(180deg, #f6f8fa, #ebf0f4 90%);
|
||
|
display: flex;
|
||
|
text-decoration: none;
|
||
|
align-items: center;
|
||
|
}
|
||
|
|
||
|
.github .button:not(:last-child) {
|
||
|
border-radius: 0.25em 0 0 0.25em;
|
||
|
}
|
||
|
|
||
|
.github .button:hover {
|
||
|
background-image: linear-gradient(180deg, #ebf0f4, #f6f8fa 90%);
|
||
|
}
|
||
|
|
||
|
.github .icon {
|
||
|
margin-right: 5px;
|
||
|
fill: #24292f;
|
||
|
}
|
||
|
|
||
|
.github .count {
|
||
|
display: block;
|
||
|
padding: 13px 10px;
|
||
|
border: 1px solid rgba(31, 35, 40, 0.15);
|
||
|
border-left: 0;
|
||
|
border-radius: 0 0.25em 0.25em 0;
|
||
|
}
|
||
|
|
||
|
#alert {
|
||
|
padding: 10px 20px;
|
||
|
border: 1px solid #ffe69c;
|
||
|
background: #fff3cd;
|
||
|
border-radius: 8px;
|
||
|
margin: 20px 0 0;
|
||
|
font-size: 14px;
|
||
|
font-weight: bold;
|
||
|
color: #664d03;
|
||
|
}
|
||
|
|
||
|
.subtitle {
|
||
|
display: block;
|
||
|
font-size: 11px;
|
||
|
font-weight: 400;
|
||
|
margin: 2px 0 5px;
|
||
|
color: #1982c4;
|
||
|
}
|
||
|
|
||
|
.subtitle a {
|
||
|
text-decoration: none;
|
||
|
font-weight: 600;
|
||
|
color: #1982c4;
|
||
|
}
|
||
|
|
||
|
.subtitle a:hover,
|
||
|
.subtitle a:focus,
|
||
|
.subtitle a:active {
|
||
|
color: #1982c4;
|
||
|
}
|
||
|
|
||
|
@media (max-width: 767px) {
|
||
|
.title h1 {
|
||
|
font-size: 20px;
|
||
|
}
|
||
|
.title h3 {
|
||
|
font-size: 14px;
|
||
|
}
|
||
|
|
||
|
.content {
|
||
|
min-width: 0;
|
||
|
}
|
||
|
|
||
|
.row {
|
||
|
flex-direction: column;
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
.column {
|
||
|
flex-basis: 100%;
|
||
|
margin: 20px 0 0;
|
||
|
padding: 0;
|
||
|
}
|
||
|
|
||
|
.divider {
|
||
|
margin: 20px auto 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@media (min-width: 768px) {
|
||
|
.row {
|
||
|
flex-wrap: nowrap;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@keyframes progress {
|
||
|
to {
|
||
|
transform: scaleX(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@keyframes spin {
|
||
|
to {
|
||
|
transform: rotate(360deg);
|
||
|
}
|
||
|
0% {
|
||
|
border-top-color: #ff595e;
|
||
|
}
|
||
|
25% {
|
||
|
border-top-color: #ffca3a;
|
||
|
}
|
||
|
50% {
|
||
|
border-top-color: #8ac926;
|
||
|
}
|
||
|
75% {
|
||
|
border-top-color: #1982c4;
|
||
|
}
|
||
|
100% {
|
||
|
border-top-color: #6a4c93;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@keyframes rainbow {
|
||
|
0% {
|
||
|
background-position: 0% 0%;
|
||
|
}
|
||
|
50% {
|
||
|
background-position: 100% 100%;
|
||
|
}
|
||
|
100% {
|
||
|
background-position: 0% 0%;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@keyframes fadeIn {
|
||
|
5% {
|
||
|
opacity: 1;
|
||
|
visibility: visible;
|
||
|
transform: translateY(0);
|
||
|
}
|
||
|
|
||
|
95% {
|
||
|
opacity: 1;
|
||
|
transform: translateY(0);
|
||
|
}
|
||
|
}
|
||
|
</style>
|
||
|
<body>
|
||
|
<div class="container">
|
||
|
<div class="content">
|
||
|
<form id="formGenerate" novalidate>
|
||
|
<div class="header">
|
||
|
<!--img
|
||
|
class="brand"
|
||
|
src="https://user-images.githubusercontent.com/47322034/244749589-300b240b-40a3-4a9a-a6f0-925631919d9b.png"
|
||
|
alt="Pixel Magic Tool"
|
||
|
title="Pixel Magic Tool"
|
||
|
/-->
|
||
|
<div class="title">
|
||
|
<h1>Pixel Magic Tool</h1>
|
||
|
<h3>Image converter for WLED presets and playlists JSON</h3>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column valitade">
|
||
|
<label for="hostname">Hostname</label>
|
||
|
<input type="text" name="hostname" id="hostname" required />
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="name">Preset Name</label>
|
||
|
<input
|
||
|
type="text"
|
||
|
name="name"
|
||
|
id="name"
|
||
|
value="New Preset"
|
||
|
required
|
||
|
/>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column valitade">
|
||
|
<label for="pattern">Pattern</label>
|
||
|
<select name="pattern" id="pattern" required>
|
||
|
<option value="">Select a choice</option>
|
||
|
<option value="1" title="['ffffff']" selected>
|
||
|
Individual
|
||
|
</option>
|
||
|
<option value="2" title="[0, 'ffffff']">Index</option>
|
||
|
<option value="3" title="[0, 5, 'ffffff']">Range</option>
|
||
|
</select>
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="output">Output</label>
|
||
|
<select name="output" id="output" required>
|
||
|
<option value="">Select a choice</option>
|
||
|
<option value="json" selected>WLED JSON</option>
|
||
|
<option value="ha">Home Assistant</option>
|
||
|
<option value="curl">CURL</option>
|
||
|
</select>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row output" style="display: none">
|
||
|
<div class="column valitade">
|
||
|
<label for="device">Device</label>
|
||
|
<input type="text" name="device" id="device" required />
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="uniqueId">Unique Id</label>
|
||
|
<input type="text" name="uniqueId" id="uniqueId" required />
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="friendlyName">Friendly Name</label>
|
||
|
<input
|
||
|
type="text"
|
||
|
name="friendlyName"
|
||
|
id="friendlyName"
|
||
|
required
|
||
|
/>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column valitade">
|
||
|
<label for="segments">Segment Id</label>
|
||
|
<select name="segments" id="segments" required>
|
||
|
<option value="">Select a choice</option>
|
||
|
</select>
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="brightness">Brightness</label>
|
||
|
<input
|
||
|
type="range"
|
||
|
name="brightness"
|
||
|
id="brightness"
|
||
|
min="0"
|
||
|
max="255"
|
||
|
value="128"
|
||
|
class="range-slider"
|
||
|
/>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column valitade">
|
||
|
<label for="animation">Animation</label>
|
||
|
<label class="switch">
|
||
|
<input type="checkbox" name="animation" id="animation" />
|
||
|
<span class="switch-slider"></span>
|
||
|
</label>
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="transparentImage">Transparent Image</label>
|
||
|
<label class="switch">
|
||
|
<input
|
||
|
type="checkbox"
|
||
|
name="transparentImage"
|
||
|
id="transparentImage"
|
||
|
/>
|
||
|
<span class="switch-slider"></span>
|
||
|
</label>
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="resizeImage">Resize Image</label>
|
||
|
<label class="switch">
|
||
|
<input type="checkbox" name="resizeImage" id="resizeImage" />
|
||
|
<span class="switch-slider"></span>
|
||
|
</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row resizeImage" style="display: none">
|
||
|
<div class="column valitade">
|
||
|
<label for="width">Width</label>
|
||
|
<input type="number" name="width" id="width" value="32" />
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="height">Height</label>
|
||
|
<input type="number" name="height" id="height" value="32" />
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row animation" style="display: none">
|
||
|
<div class="column valitade">
|
||
|
<label for="frames">Frames</label>
|
||
|
<input type="number" name="frames" id="frames" value="4" />
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="duration">Duration</label>
|
||
|
<div class="input-group">
|
||
|
<input
|
||
|
type="number"
|
||
|
name="duration"
|
||
|
id="duration"
|
||
|
value="0.5"
|
||
|
required="required"
|
||
|
min="0"
|
||
|
step="0.1"
|
||
|
inputmode="numeric"
|
||
|
/>
|
||
|
<div class="input-description">sec</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="column valitade">
|
||
|
<label for="transition">Transition</label>
|
||
|
<div class="input-group">
|
||
|
<input
|
||
|
type="number"
|
||
|
name="transition"
|
||
|
id="transition"
|
||
|
value="0.2"
|
||
|
required="required"
|
||
|
min="0"
|
||
|
step="0.1"
|
||
|
inputmode="numeric"
|
||
|
/>
|
||
|
<div class="input-description">sec</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row transparentImage" style="display: none">
|
||
|
<div class="column valitade w-full">
|
||
|
<label for="color">Choose a color</label>
|
||
|
<small class="subtitle"
|
||
|
>Color that will replace the
|
||
|
<strong>transparent pixels</strong> in the image</small
|
||
|
>
|
||
|
<input type="color" name="color" id="color" value="#ffffff" />
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column valitade w-full">
|
||
|
<label for="images">Images</label>
|
||
|
<small class="subtitle"
|
||
|
>Images uploaded to
|
||
|
<a href="http://[wled-ip]/edit" target="_blank">WLED</a>
|
||
|
or upload image</small
|
||
|
>
|
||
|
<select name="images" id="images" required>
|
||
|
<option value="">Select a choice</option>
|
||
|
</select>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="alert" style="display: none">
|
||
|
<span
|
||
|
>To define a large number of colors. 32x32 or larger matrix
|
||
|
presets need to be split into multiple requests at the same
|
||
|
time!</span
|
||
|
>
|
||
|
</div>
|
||
|
<div id="dropzone" class="dropzone valitade" style="display: none">
|
||
|
<p id="dropzoneLabel">
|
||
|
Drag and drop a file here or click to select a file
|
||
|
</p>
|
||
|
<input
|
||
|
type="file"
|
||
|
name="source"
|
||
|
id="source"
|
||
|
accept="image/*"
|
||
|
style="display: none"
|
||
|
/>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="column w-full">
|
||
|
<button type="button" class="buttonRainbow" id="btnGenerate">
|
||
|
Generate
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</form>
|
||
|
<div id="preview" style="display: none">
|
||
|
<div class="row margin-zero">
|
||
|
<div class="column w-full">
|
||
|
<textarea
|
||
|
name="response"
|
||
|
id="response"
|
||
|
cols="30"
|
||
|
rows="10"
|
||
|
readonly="readonly"
|
||
|
></textarea>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="isNotAnimation">
|
||
|
<div class="buttons">
|
||
|
<div class="row margin-zero">
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnCopyToClipboard">
|
||
|
Copy to Clipboard
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnDownloadPreset">
|
||
|
Download
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="divider"></div>
|
||
|
<div class="row margin-zero" id="notBigData">
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnSimulatePreset">
|
||
|
Simulate
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnSavePreset">
|
||
|
Save
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row margin-zero" id="bigData">
|
||
|
<div class="column w-full">
|
||
|
<button
|
||
|
type="button"
|
||
|
class="button"
|
||
|
id="btnSimulatePresetBigData"
|
||
|
>
|
||
|
Simulate
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="singleCanvas"></div>
|
||
|
</div>
|
||
|
<div id="isAnimation">
|
||
|
<div class="buttons">
|
||
|
<div class="row margin-zero">
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnCopyToClipboard">
|
||
|
Copy to Clipboard
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="column">
|
||
|
<button type="button" class="button" id="btnDownloadPreset">
|
||
|
Download
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="divider"></div>
|
||
|
<div class="row margin-zero">
|
||
|
<div class="column w-full">
|
||
|
<button type="button" class="button" id="btnSavePlaylist">
|
||
|
Save
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="multipleCanvas"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="github">
|
||
|
<div class="widget">
|
||
|
<a
|
||
|
class="button"
|
||
|
id="profile"
|
||
|
href="https://github.com/ajotanc"
|
||
|
target="_blank"
|
||
|
title="Alerson Jorge"
|
||
|
>
|
||
|
<svg class="icon" viewBox="0 0 16 16" width="16" height="16">
|
||
|
<path
|
||
|
d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"
|
||
|
></path>
|
||
|
</svg>
|
||
|
<span>Follow @ajotanc</span>
|
||
|
</a>
|
||
|
<span class="count" id="followers">0</span>
|
||
|
</div>
|
||
|
<div class="widget">
|
||
|
<a class="button" id="repository" target="_blank" href="#">
|
||
|
<svg class="icon" viewBox="0 0 16 16" width="16" height="16">
|
||
|
<path
|
||
|
d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"
|
||
|
></path>
|
||
|
</svg>
|
||
|
<span>Star</span>
|
||
|
</a>
|
||
|
<span class="count" id="star">0</span>
|
||
|
</div>
|
||
|
<div class="widget">
|
||
|
<a class="button" id="issue" target="_blank" href="#">
|
||
|
<svg class="icon" viewBox="0 0 16 16" width="16" height="16">
|
||
|
<path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path>
|
||
|
<path
|
||
|
d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"
|
||
|
></path>
|
||
|
</svg>
|
||
|
<span>Issue</span>
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="toast-container"></div>
|
||
|
<div id="overlay"></div>
|
||
|
</body>
|
||
|
<script>
|
||
|
const e="file:"===window.location.protocol?"http:":window.location.protocol,t=window.location.host||"0.0.0.0",n="PixelMagicTool";let a=`${e}//${t}`;const o=document.getElementById("hostname");o.value=t,o.addEventListener("change",(async()=>{a=`${e}//${o.value}`,await m(),await r(),i()}));let s=[],c={},l=[];function i(){const e=document.getElementById("images").parentNode.querySelector("a");e.href=e.href.replace("[wled-ip]",o.value)}async function d(e,t=!1,n=5e3){const o=`${a}/presets.json`,s=`${a}/json`;let c=0;B();const l=e.map((async e=>new Promise(((t,a)=>{setTimeout((async()=>{try{const t=await fetch(o),n=await t.json(),a=Object.keys(n),c=a.find((t=>"object"==typeof n[t]&&!n[t].playlist&&n[t].n===e.n))||parseInt(a.pop())+1,l=Object.assign(e,{psave:c}),i={method:"POST",body:JSON.stringify(l)};try{const t=await fetch(s,i),{success:n}=await t.json();n&&w(`Preset "${e.n}" save successfully!`)}catch(e){w(`Error saving preset: ${e}`,"error")}}catch(e){w(e,"error")}finally{t()}}),n*c++)}))));await Promise.all(l),t?setTimeout((async()=>{await async function(){const{value:e}=document.getElementById("duration"),{value:t}=document.getElementById("transition"),{value:n}=document.getElementById("name"),o=`${a}/presets.json`,s=`${a}/json`;try{const a=await fetch(o),c=await a.json(),l=Object.keys(c),i=l.filter((e=>"object"==typeof c[e]&&!c[e].playlist&&c[e].n&&c[e].n.includes(n))),d={psave:l.find((e=>"object"==typeof c[e]&&c[e].playlist&&c[e].n&&c[e].n===n))||parseInt(l.pop())+1,n:n,on:!0,o:!1,playlist:{ps:i,dur:Array.from({length:i.length},(()=>10*e)),transition:Array.from({length:i.length},(()=>10*t)),repeat:0,end:0}},r={method:"POST",body:JSON.stringify(d)};try{const e=await fetch(s,r),{success:t}=await e.json();t&&w(`Playlist "${n}" save successfully!`)}catch(e){w(`Error saving preset: ${e}`,"error")}}catch(e){w(e,"error")}}().then((()=>{b()})).catch((()=>{b()}))}),n):b()}async function r(){const e=`${a}/edit?list=/`,t=document.getElementById("images");t.innerHTML="";[{text:"Select a choice",value:""},{text:"Upload",value:"upload"}].forEach((({text:e,value:n})=>{const a=new Option(e,n);t.appendChild(a)})),B();try{const n=await fetch(e),o=await n.json(),s=["jpeg","jpg","png","gif"];o.filter((e=>{const{name:t}=e,[n,a]=t.split(".");return e.name=t.replace("/",""),s.includes(a)})).map((e=>{const{name:n}=e,o=document.createElement("option");o.text=n,o.value=`${a}/${n}`,t.add(o)}))}catch(e){w(e,"error")}finally{b()}}async function m(){const e=document.getElementById("segments"),t=document.getElementById("width"),n=document.getElementById("height"),o=`${a}/json/state`;e.innerHTML="";[{text:"Select a choice",value:""}].forEach((({text:t,value:n})=>{const a=new Option(t,n);e.appendChild(a)})),B();try{const a=await fetch(o),{seg:s}=await a.json();s&&s.forEach((function({id:a,n:o,stop:s,stopY:c},l){const i=document.createElement("option");i.text=o||`Segment ${a}`,i.value=a,i.setAttribute("data-width",s),i.setAttribute("data-height",c),0===l&&(i.selected=!0,t.value=s,n.value=c),e.add(i)}))}catch(e){w(e,"error")}finally{b()}}!async function(){await async function(){const e=document.getElementById("followers"),t=document.getElementById("repository"),a=document.getElementById("issue"),o=document.getElementById("star"),s="https://api.github.com/users/ajotanc";try{const t=await fetch(s),n=await t.json();e.textContent=n.followers}catch(e){w(e,"error")}try{const e=await fetch(`${s}/repos`),c=await e.json(),{name:l,html_url:i,stargazers_count:d}=c.find((({name:e})=>e===n));t.href=i,a.href=`${i}/issues`,o.textContent=d}catch(e){w(e,"error")}}(),await m(),await r(),i()}();const u=document.getElementById("dropzone"),y=document.getElementById("source");function p(e){return new Promise(((t,n)=>{const a=new Image;a.addEventListener("load",(function(){t(a)})),a.addEventListener("error",(function(){n(new Error("Error loading image"))})),a.src=e}))}function g(e){const{value:t}=document.getElementById("pattern"),{value:n}=document.getElementById("segments"),{value:a}=document.getElementById("brightness"),{value:o}=document.getElementById("width"),{valu
|
||
|
</script>
|
||
|
</html>
|