Segments: add graphical display of segments part 1

Custom Effects: Add 🥚🥚 for HBaas effect presons

Index.js/htm:
- add ctx (context)
- add hidden input field fx
- add draw() function for graphics (segment bounds, mirror/reverse/transpose/leds/Nr/FX

settings2D
- move ctx init to draw
- set space 0
- center text
This commit is contained in:
Ewoud
2023-02-06 19:57:25 +01:00
parent f71e6262f6
commit 2a890f5e1e
8 changed files with 2612 additions and 2432 deletions

View File

@@ -311,6 +311,10 @@
<div id="segutil2">
<button class="btn btn-s" id="rsbtn" onclick="rSegs()">Reset segments</button>
</div>
<br>
<canvas id="canvas"></canvas><br>
<div id="MD"></div> <!-- Matrix dimensions -->
<br>
<p>Transition: <input id="tt" class="noslide" type="number" min="0" max="65.5" step="0.1" value="0.7">&nbsp;s</p>
<p id="ledmap" class="hide"></p>
</div>

View File

@@ -36,6 +36,7 @@ var hol = [
[0,6,4,1,"https://initiate.alphacoders.com/download/wallpaper/516792/images/jpg/510921363292536"], // 4th of July
[0,0,1,1,"https://initiate.alphacoders.com/download/wallpaper/1198800/images/jpg/2522807481585600"] // new year
];
var ctx = null; // WLEDMM
function handleVisibilityChange() {if (!d.hidden && new Date () - lastUpdate > 3000) requestJson();}
function sCol(na, col) {d.documentElement.style.setProperty(na, col);}
@@ -706,6 +707,7 @@ function populateSegments(s)
segCount = 0; lowestUnused = 0; lSeg = 0;
for (var inst of (s.seg||[])) {
console.log("inst", inst);
segCount++;
let i = parseInt(inst.id);
@@ -769,6 +771,7 @@ function populateSegments(s)
<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})">&#xe395;</i>
${cfg.comp.segpwr?segp:''}
<div class="segin" id="seg${i}in">
<input id="seg${i}fx" value="${inst.fx}" type="hidden"/>
<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
<table class="infot segt">
<tr>
@@ -1070,6 +1073,7 @@ function toggleBubble(e)
// updates segment length upon input of segment values
function updateLen(s)
{
console.log("updateLen", s);
if (!gId(`seg${s}s`)) return;
var start = parseInt(gId(`seg${s}s`).value);
var stop = parseInt(gId(`seg${s}e`).value) + (cfg.comp.seglen?start:0);
@@ -1117,6 +1121,125 @@ function updateLen(s)
}
gId(`seg${s}len`).innerHTML = out;
draw();
}
function draw() {
if (!ctx) {
console.log("init", window.innerWidth);
//WLEDMM: add canvas, initialize and set UI
var canvas = gId("canvas");
// c.width = window.innerWidth > 800?300:300; //Mobile gets 400, pc 800
// c.height = c.width;
ctx = canvas.getContext('2d');
}
//calc max height and width
var maxWidth = 0;
var maxHeight = 0;
for (let p=0; p<gId("segcont").children.length; p++) {
var px = parseInt(gId("seg"+p+"s").value); //first led x
var py = parseInt(gId("seg"+p+"sY").value); //first led y
var pw = parseInt(gId("seg"+p+"e").value - gId("seg"+p+"s").value); //width
var ph = parseInt(gId("seg"+p+"eY").value - gId("seg"+p+"sY").value); //height
maxWidth = Math.max(maxWidth, px + pw);
maxHeight = Math.max(maxHeight, py + ph);
}
ctx.canvas.height = ctx.canvas.width / maxWidth * maxHeight;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
var space=0; // space between panels + margin
var ppL = (ctx.canvas.width - space * 2) / maxWidth; //pixels per led
// console.log("dim", ctx.canvas.width , maxWidth, ctx.canvas.height , maxHeight, ppL);
ctx.lineWidth = 1;
ctx.strokeStyle="yellow";
ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height); // add space between panels
var colorArray = ["red", "green", "blue", "magenta", "orange", "yellow"];
for (let p=0; p<gId("segcont").children.length; p++) {
// console.log(gId("P"+p+"X").value, gId("P"+p+"Y").value, gId("P"+p+"W").value, gId("P"+p+"H").value, gId("P"+p+"B").value, gId("P"+p+"R").value, gId("P"+p+"V").value, gId("P"+p+"S").checked);
var px = parseInt(gId("seg"+p+"s").value); //first led x
var py = parseInt(gId("seg"+p+"sY").value); //first led y
var pw = parseInt(gId("seg"+p+"e").value - gId("seg"+p+"s").value); //width
var ph = parseInt(gId("seg"+p+"eY").value - gId("seg"+p+"sY").value); //height
// console.log("sergment", p, px, py, pw, ph);
var topLeftX = px*ppL + space; //left margin
var topLeftY = py*ppL + space; //top margin
// console.log("rect", p, topLeftX, topLeftY, pw*ppL, ph*ppL);
ctx.lineWidth = 3;
ctx.strokeStyle="white";
ctx.strokeRect(topLeftX, topLeftY, pw*ppL, ph*ppL); // add space between panels
var fx = parseInt(gId("seg"+p+"fx").value);
var grp = parseInt(gId("seg"+p+"grp").value); //reverseX
var spc = parseInt(gId("seg"+p+"spc").value); //reverseX
var rx = gId("seg"+p+"rev").checked; //reverseX
var ry = gId("seg"+p+"rY").checked; //reverseY
var mx = gId("seg"+p+"mi").checked; //mirrorX
var my = gId("seg"+p+"mY").checked; //mirrorY
var tp = gId("seg"+p+"tp").checked; //mirrorY
ctx.lineWidth = 1;
if (mx) {
ctx.beginPath();
ctx.moveTo(topLeftX + pw/2*ppL, topLeftY);
ctx.lineTo(topLeftX + pw/2*ppL, topLeftY + ph*ppL);
ctx.stroke();
}
if (my) {
ctx.beginPath();
ctx.moveTo(topLeftX, topLeftY + ph/2*ppL);
ctx.lineTo(topLeftX + pw*ppL, topLeftY + ph/2*ppL);
ctx.stroke();
}
if (ry) {
ctx.beginPath();
ctx.moveTo(topLeftX + pw/8*ppL, topLeftY);
ctx.lineTo(topLeftX + pw/8*ppL, topLeftY + ph*ppL);
ctx.stroke();
}
if (rx) {
ctx.beginPath();
ctx.moveTo(topLeftX, topLeftY + ph/8*ppL);
ctx.lineTo(topLeftX + pw*ppL, topLeftY + ph/8*ppL);
ctx.stroke();
}
if (tp) {
ctx.beginPath();
ctx.moveTo(topLeftX, topLeftY);
ctx.lineTo(topLeftX + pw*ppL, topLeftY + ph*ppL);
ctx.stroke();
}
for (let x=0; x<pw; x++)
for (let y=0; y<ph; y++) {
ctx.fillStyle = colorArray[p%colorArray.length];
ctx.beginPath();
ctx.arc(topLeftX + ppL/2 + x*ppL, topLeftY + ppL/2 + y * ppL, ppL*0.4, 0, 2 * Math.PI);
ctx.fill();
}
ctx.font = '40px Arial';
ctx.fillStyle = "orange";
ctx.fillText(p, topLeftX + pw/2*ppL - 10, topLeftY + ph/2*ppL + 10);
ctx.font = '20px Arial';
ctx.fillStyle = "white";
var name = eJson.find((o)=>{return o.id==fx}).name;
ctx.fillText(name, topLeftX + ppL, topLeftY + ph*ppL - 10);
} // for each segment
gId("MD").innerHTML = "W*H=LC: " + maxWidth + " x " + maxHeight + " = " + maxWidth * maxHeight;
}
// updates background color of currently selected preset

View File

@@ -9,7 +9,7 @@
var d=document;
var loc = false, locip;
var maxPanels=64;
var ctx; // WLEDMM
var ctx = null; // WLEDMM
var ledIndex = 0; // WLEDMM
var wasAdvanced = -1; //WLEDMM
function H(){window.open("https://mm.kno.wled.ge/features/2D");}
@@ -48,16 +48,6 @@
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
//WLEDMM: add canvas, initialize and set UI
var c = gId("canvas");
c.width = window.innerWidth > 800?800:400; //Mobile gets 400, pc 800
c.height = c.width;
ctx = c.getContext('2d');
// window.requestAnimationFrame(animate);
}
function UI() {
@@ -122,7 +112,7 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
//WLEDMM
function baChange(radioElement=null) {
console.log("baChange", gId("form_s"), radioElement, gId("form_s").elements, d.Sf.BA.value);
// console.log("baChange", gId("form_s"), radioElement, gId("form_s").elements, d.Sf.BA.value);
if (radioElement) {
if (d.Sf.BA.value == 0 && wasAdvanced == 1) {
if (!confirm('Are you sure to go back to basic (advanced settings will be lost)?')) {
@@ -143,7 +133,7 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
//WLEDMM
function fieldChange(force=false) { //Done on all fields of matrix setup area
console.log("fieldChange", force);
// console.log("fieldChange", force);
var pansH = parseInt(d.Sf.MPH.value);
var pansV = parseInt(d.Sf.MPV.value);
if ((pansH>0 && pansV>0 && d.Sf.BA.value == 0) || force) gen(); //Generate if basic or forced (in advanced by populate button)
@@ -193,6 +183,16 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
//WLEDMM
function draw() {
if (!ctx) {
//WLEDMM: add canvas, initialize and set UI
var canvas = gId("canvas");
canvas.width = window.innerWidth > 800?800:400; //Mobile gets 400, pc 800
canvas.height = canvas.width;
ctx = canvas.getContext('2d');
// window.requestAnimationFrame(animate);
}
//calc max height and width
var maxWidth = 0;
var maxHeight = 0;
@@ -205,9 +205,9 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
maxHeight = Math.max(maxHeight, py + ph);
}
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.canvas.height = ctx.canvas.width / maxWidth * maxHeight;
var space=20; // space between panels + margin
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
var space=0; // space between panels + margin
var ppL = (ctx.canvas.width - space * 2) / maxWidth; //pixels per led
// console.log("dim", ctx.canvas.width , maxWidth, ctx.canvas.height , maxHeight, ppL);
@@ -302,7 +302,7 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
ctx.font = '40px Arial';
ctx.fillStyle = "orange";
ctx.fillText(p, topLeftX-ppL/2 + (pw*ppL+ppL)/2, topLeftY-ppL/2 + (ph*ppL+ppL)/2);
ctx.fillText(p, topLeftX + pw/2*ppL - 10, topLeftY + ph/2*ppL + 10);
}
gId("MD").innerHTML = "Matrix Dimensions (W*H=LC): " + maxWidth + " x " + maxHeight + " = " + maxWidth * maxHeight;

View File

@@ -116,7 +116,7 @@
<hr>
<h3>About</h3>
<!-- WLEDMM additions -->
<a href="https://github.com/MoonModules/WLED/" target="_blank">WLEDMM</a> version ##VERSION##<!-- Autoreplaced from package.json --><br>
<a href="https://github.com/MoonModules/WLED/" target="_blank">WLEDMM</a> version ##VERSION##<!-- Autoreplaced from package.json --><br>
(c) 2023 <a href="https://github.com/Aircoookie/WLED/compare/main...MoonModules:WLED:mdev" target="_blank">Github MoonModules WLED Commit Authors</a><br><br>
fork of <a href="https://github.com/Aircoookie/WLED/" target="_blank">WLED:</a><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits" target="_blank">Contributors, dependencies and special thanks</a><br>