Custom palettes now editable

This commit is contained in:
Henrik 2023-04-23 21:32:52 +02:00
parent 480e1e17c8
commit 92f9c908f6

View File

@ -102,14 +102,62 @@
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
font-size: 12px; font-size: 12px;
position: relative; position: relative;
margin-top: 100px; margin-top: 10px;
line-height: 1; line-height: 1;
} }
.wrap{
width: 800px;
margin: 0 auto;
}
.palette{
height: 20px;
}
.paletteGradients{
flex: 1;
height: 20px;
border-radius: 3px;
}
.palettesMain {
margin-top: 50px;
width: 100%;
}
#palTop{
height: fit-content;
text-align: center;
color: #fff;
font-family: Arial, sans-serif;
font-size: 12px;
position: relative;
line-height: 1;
}
.palGradientParent{
display: flex;
align-items: center;
height: fit-content;
margin-top: 10px;
text-align: center;
color: #fff;
font-family: Arial, sans-serif;
font-size: 12px;
position: relative;
line-height: 1;
}
.buttonsDiv{
display: inline-flex;
margin-left: 5px;
width: 50px;
}
.sendSpan{
cursor: pointer;
}
.editSpan{
cursor: pointer;
}
</style> </style>
</head> </head>
<body> <body>
<div id="wrap" style="max-width: 800px;"> <div id="wrap" class="wrap">
<div style="display: flex; justify-content: center;"> <div style="display: flex; justify-content: center;">
<h1 style="display: flex; align-items: center;"> <h1 style="display: flex; align-items: center;">
<svg style="width:36px;height:36px;margin-right:6px;" viewBox="0 0 32 32"> <svg style="width:36px;height:36px;margin-right:6px;" viewBox="0 0 32 32">
@ -118,21 +166,19 @@
<rect style="fill:#003FFF" x="18" y="10" width="4" height="8"/> <rect style="fill:#003FFF" x="18" y="10" width="4" height="8"/>
<rect style="fill:#003FFF" x="22" y="6" width="8" height="4"/> <rect style="fill:#003FFF" x="22" y="6" width="8" height="4"/>
</svg> </svg>
<span id="head">WLED Custom Palette Creator</span> <span id="head">WLED Custom Palette Editor</span>
</h1> </h1>
</div> </div>
<div id="parent-container"> <div id="parent-container">
<div id="gradient-box"></div> <div id="gradient-box"></div>
</div> </div>
<div style="display: flex; justify-content: center;"> <div style="display: flex; justify-content: center;">
<div id="bottomContainer"> <div id="palettes" class="palettesMain">
<span id="idSpan"> <div id="palTop">
<label for="palId">Palette#: </label> Currently in use custom palettes
<input id="palId" type="number" min="0" max="9" style="background-color: #111; color: #fff; border: none; font-weight: bold; text-align: center; width: 40px;" value="0"> </div>
</span>
<span id="sendSpan" onclick="initiateUpload()"></span>
</div> </div>
</div> </div>
@ -142,7 +188,6 @@
<br> <br>
Currently in use Custom Palette IDs are 0 to <span id="cpaltx">-1</span>. Note!, IDs <u>must</u> be in uninterupted sequece from 0 and cannot excede 9. This number will only be updated on WLED reboot (or equivalent). Currently in use Custom Palette IDs are 0 to <span id="cpaltx">-1</span>. Note!, IDs <u>must</u> be in uninterupted sequece from 0 and cannot excede 9. This number will only be updated on WLED reboot (or equivalent).
</div> </div>
<div style="display: flex; justify-content: center;"></div>
</div> </div>
</body> </body>
@ -156,12 +201,14 @@
var rect = gradientBox.getBoundingClientRect(); var rect = gradientBox.getBoundingClientRect();
var gradientLength = rect.width; var gradientLength = rect.width;
var mOffs = Math.round((gradientLength / 256) / 2) - 5; var mOffs = Math.round((gradientLength / 256) / 2) - 5;
var paletteArray = []; //Holds the palettes after load.
var svgSave = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M7,12L12,17V14H16V10H12V7L7,12Z"/></svg>'
var svgEdit = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M15.1,7.07C15.24,7.07 15.38,7.12 15.5,7.23L16.77,8.5C17,8.72 17,9.07 16.77,9.28L15.77,10.28L13.72,8.23L14.72,7.23C14.82,7.12 14.96,7.07 15.1,7.07M13.13,8.81L15.19,10.87L9.13,16.93H7.07V14.87L13.13,8.81Z"/></svg>'
function recOf() { function recOf() {
rect = gradientBox.getBoundingClientRect(); rect = gradientBox.getBoundingClientRect();
gradientLength = rect.width; gradientLength = rect.width;
mOffs = Math.round((gradientLength / 256) / 2) - 5; mOffs = Math.round((gradientLength / 256) / 2) - 5;
console.log(mOffs)
} }
//Initiation //Initiation
@ -170,9 +217,7 @@
window.addEventListener('resize', chkW); window.addEventListener('resize', chkW);
gradientBox.addEventListener("click", clikOnGradient); gradientBox.addEventListener("click", clikOnGradient);
gId("sendSpan").innerHTML =
'<svg class="svg-icon" style="width:36px;height:36px" viewBox="0 0 24 24"> <path id=sendSvgP fill="#fff" d="M6.5 20Q4.22 20 2.61 18.43 1 16.85 1 14.58 1 12.63 2.17 11.1 3.35 9.57 5.25 9.15 5.88 6.85 7.75 5.43 9.63 4 12 4 14.93 4 16.96 6.04 19 8.07 19 11 20.73 11.2 21.86 12.5 23 13.78 23 15.5 23 17.38 21.69 18.69 20.38 20 18.5 20H13Q12.18 20 11.59 19.41 11 18.83 11 18V12.85L9.4 14.4L8 13L12 9L16 13L14.6 14.4L13 12.85V18H18.5Q19.55 18 20.27 17.27 21 16.55 21 15.5 21 14.45 20.27 13.73 19.55 13 18.5 13H17V11Q17 8.93 15.54 7.46 14.08 6 12 6 9.93 6 8.46 7.46 7 8.93 7 11H6.5Q5.05 11 4.03 12.03 3 13.05 3 14.5 3 15.95 4.03 17 5.05 18 6.5 18H9V20M12 13Z" /> </svg>';
//Sets start and stop, mandatory //Sets start and stop, mandatory
addC(0); addC(0);
addC(255); addC(255);
@ -185,7 +230,7 @@
} }
///////// Add a new colorMarker ///////// Add a new colorMarker
function addC(truePos){ function addC(truePos, thisColor = ''){
let position = -1; let position = -1;
let iExist = false; let iExist = false;
const colorMarkers = gradientBox.querySelectorAll('.color-marker'); const colorMarkers = gradientBox.querySelectorAll('.color-marker');
@ -209,8 +254,9 @@
} else{ } else{
position = truePos; position = truePos;
} }
if (thisColor == ''){
const thisColor = `#${(Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0')}`;// set random color as default thisColor = `#${(Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0')}`;// set random color as default
}
const colorMarker = cE('span'); // create a marker for the color position const colorMarker = cE('span'); // create a marker for the color position
colorMarker.className = 'color-marker'; colorMarker.className = 'color-marker';
@ -301,7 +347,6 @@
function cpClk(e){ function cpClk(e){
removeTrashcan(event) removeTrashcan(event)
e.stopPropagation(); e.stopPropagation();
console.log(e);
} }
//This neat little function makes any element draggable on the X-axis. //This neat little function makes any element draggable on the X-axis.
@ -428,32 +473,30 @@
return rStr; return rStr;
} }
function initiateUpload() { function initiateUpload(idx) {
const data = calcJSON(); const data = calcJSON();
const fileName = '/palette' + gId('palId').value + '.json'; const fileName = `/palette${idx}.json`;
uploadJSON(data, fileName); uploadJSON(data, fileName);
console.log('File: ', fileName, 'JSON: ', data);
} }
function uploadJSON(jsonString, fileName) { function uploadJSON(jsonString, fileName) {
const ss = gId('sendSvgP'); //Some indication on "I'm working"
ss.setAttribute('fill', '#555');
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
var blob = new Blob([jsonString], {type: "application/json"}); var blob = new Blob([jsonString], {type: "application/json"});
req.addEventListener('load', ()=>{ req.addEventListener('load', ()=>{
console.log(this.responseText, ' - ', this.status) console.log(this.responseText, ' - ', this.status)
ss.setAttribute('fill', '#056b0a');
localStorage.removeItem('wledPalx'); localStorage.removeItem('wledPalx');
setTimeout(()=>{ //setTimeout(()=>{
ss.setAttribute('fill', '#fff'); // ss.setAttribute('fill', '#fff');
}, 1000); //}, 1000);
setTimeout(()=>{window.location.href='/';},2000); //setTimeout(()=>{window.location.href='/';},2000);
window.location.href = '/'; //Guessing we want to return ASAP when we get confirmation save is done
}); });
req.addEventListener('error', (e)=>{ req.addEventListener('error', (e)=>{
console.log('Error: ', e); console.log(' Status: ', this.status); console.log('Error: ', e); console.log(' Status: ', this.status);
ss.setAttribute('fill', '#6b050c'); //Show some error notification for some time
setTimeout(()=>{ setTimeout(()=>{
ss.setAttribute('fill', '#fff'); //Remove it when time has pased
}, 1000); }, 1000);
}); });
req.open("POST", "/upload"); req.open("POST", "/upload");
@ -472,7 +515,9 @@
const json = await response.json(); const json = await response.json();
cpalc = json.cpalcount; cpalc = json.cpalcount;
gId('cpaltx').innerHTML = cpalc-1; gId('cpaltx').innerHTML = cpalc-1;
fetchPalettes(cpalc-1);
console.log('cpalc: ', cpalc); console.log('cpalc: ', cpalc);
console.log(paletteArray);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -480,5 +525,137 @@
console.error('cannot identify host'); console.error('cannot identify host');
} }
} }
async function fetchPalettes(lastPal) {
paletteArray.length = 0;
for (let i = 0; i <= lastPal; i++) {
const url = `http://${hst}/palette${i}.json`;
try {
const response = await fetch(url);
const json = await response.json();
paletteArray.push(json);
} catch (error) {
console.error(`Error fetching JSON from ${url}: `, error);
}
}
generatePaletteDivs();
}
function generatePaletteDivs() {
const palettesDiv = document.getElementById("palettes");
const paletteDivs = Array.from(palettesDiv.children).filter((child) => {
return child.id.match(/^palette\d$/); // match only elements with id starting with "palette" followed by a single digit
});
if (paletteArray.length < 10){
//Room for one more :)
paletteArray.push({"palette":[0,70,70,70,255,70,70,70]});
}
for (const div of paletteDivs) {
palettesDiv.removeChild(div); // remove each div that matches the above selector
}
for (let i = 0; i < paletteArray.length; i++) {
const palette = paletteArray[i];
const paletteDiv = document.createElement("div");
paletteDiv.id = `palette${i}`;
paletteDiv.classList.add("palette");
paletteDiv.dataset.colarray = JSON.stringify(palette.palette);
const gradientDiv = document.createElement("div");
gradientDiv.id = `paletteGradient${i}`
const buttonsDiv = document.createElement("div");
buttonsDiv.id = `buttonsDiv${i}`;
buttonsDiv.classList.add("buttonsDiv")
const sendSpan = document.createElement("span");
sendSpan.id = `sendSpan${i}`;
sendSpan.onclick = function() {initiateUpload(i)};
sendSpan.setAttribute('title', `Send current editor to slot ${i}`);
sendSpan.innerHTML = svgSave;
sendSpan.classList.add("sendSpan")
const editSpan = document.createElement("span");
editSpan.id = `editSpan${i}`;
editSpan.onclick = function() {loadForEdit(i)};
editSpan.setAttribute('title', `Copy slot ${i} palette to editor`);
editSpan.innerHTML = svgEdit;
editSpan.classList.add("editSpan")
gradientDiv.classList.add("paletteGradients");
let gradientColors = "";
for (let j = 0; j < palette.palette.length; j += 4) {
const position = palette.palette[j];
const red = palette.palette[j + 1];
const green = palette.palette[j + 2];
const blue = palette.palette[j + 3];
gradientColors += `rgba(${red}, ${green}, ${blue}, 1) ${position/255*100}%, `;
}
gradientColors = gradientColors.slice(0, -2); // remove the last comma and space
gradientDiv.style.backgroundImage = `linear-gradient(to right, ${gradientColors})`;
paletteDiv.className = "palGradientParent";
buttonsDiv.appendChild(sendSpan);
if(i<cpalc){
buttonsDiv.appendChild(editSpan); //Dont offer to edit the empty spot
}
paletteDiv.appendChild(gradientDiv);
paletteDiv.appendChild(buttonsDiv);
palettesDiv.appendChild(paletteDiv);
}
}
function loadForEdit(i){
console.log("Lets edit no: ", i);
document.querySelectorAll('input[id^="colorPicker"]').forEach((input) => {
input.parentNode.removeChild(input);
});
document.querySelectorAll('span[id^="colorMarker"], span[id^="colorPickerMarker"], span[id^="deleteMarker"]').forEach((span) => {
span.parentNode.removeChild(span);
});
let colArray = JSON.parse(gId(`palette${i}`).getAttribute("data-colarray"));
for (let j = 0; j < colArray.length; j += 4) {
const position = colArray[j];
const red = colArray[j + 1];
const green = colArray[j + 2];
const blue = colArray[j + 3];
const hex = rgbToHex(red, green, blue);
console.log(position, hex)
addC(position, hex);
}
}
function rgbToHex(r, g, b) {
const hex = ((r << 16) | (g << 8) | b).toString(16);
return "#" + "0".repeat(6 - hex.length) + hex;
}
function getLocalStorageData(){
// Retrieve the "wledPalx" JSON from local storage
const wledPalx = JSON.parse(localStorage.getItem('wledPalx'));
// Initialize an empty array to store the extracted arrays
const result = [];
// Loop through the "p" object in the "wledPalx" JSON
for (const key in wledPalx.p) {
if (wledPalx.p.hasOwnProperty(key)) {
// Check if the key is between 246 and 255
const numKey = parseInt(key, 10);
if (numKey >= 246 && numKey <= 255) {
// Replace the key with a new key that follows the mapping
const newKey = 255 - numKey;
// Add the array to the result array with the new key as the index
result[newKey] = wledPalx.p[key];
}
}
}
// The "result" array now contains arrays with the new keys
console.log(result);
}
</script> </script>