Dynamic gauge
An example of advanced decoration, which supports changing data
Download original notebookDefine
gauge /: MakeBoxes[g_gauge, StandardForm] := ViewBox[g, g]
Now we need to implement the interpretation function on the frontend
.js core.gauge = async (args, env) => { // Create a gauge meter element const gauge = document.createElement('div'); gauge.style.width = '100px'; // half the original width gauge.style.height = '50px'; // half the original height gauge.style.border = '1px solid #000'; gauge.style.borderRadius = '50px 50px 0 0'; // adjusted for smaller size gauge.style.position = 'relative'; gauge.style.background = 'linear-gradient(to right, red 0%, yellow 50%, green 100%)'; // Create a needle for the gauge const needle = document.createElement('div'); needle.style.width = '2px'; needle.style.height = '40px'; // made the needle longer for better visibility needle.style.background = '#000'; needle.style.position = 'absolute'; needle.style.bottom = '0'; needle.style.left = '50%'; needle.style.transformOrigin = 'bottom'; // Function to set the needle position based on input value function setNeedlePosition(value) { // Ensure value is between 0 and 1 value = Math.max(0, Math.min(1, value)); // Convert value to angle const angle = value * 180 - 90; // -90 to 90 degrees needle.style.transform = `rotate(${angle}deg)`; } // Set initial needle position const pos = await interpretate(args[0], env); setNeedlePosition(pos); // Middle position gauge.appendChild(needle); env.element.appendChild(gauge); env.local.update = setNeedlePosition; } core.gauge.update = async (args, env) => { const val = await interpretate(args[0], env); env.local.update(val); } core.gauge.destroy = () => { console.log('Nothing to do'); } core.gauge.virtual = true;
core.gauge = async (args, env) => { // Create a gauge meter element const gauge = document.createElement('div'); gauge.style.width = '100px'; // half the original width gauge.style.height = '50px'; // half the original height gauge.style.border = '1px solid #000'; gauge.style.borderRadius = '50px 50px 0 0'; // adjusted for smaller size gauge.style.position = 'relative'; gauge.style.background = 'linear-gradient(to right, red 0%, yellow 50%, green 100%)'; // Create a needle for the gauge const needle = document.createElement('div'); needle.style.width = '2px'; needle.style.height = '40px'; // made the needle longer for better visibility needle.style.background = '#000'; needle.style.position = 'absolute'; needle.style.bottom = '0'; needle.style.left = '50%'; needle.style.transformOrigin = 'bottom'; // Function to set the needle position based on input value function setNeedlePosition(value) { // Ensure value is between 0 and 1 value = Math.max(0, Math.min(1, value)); // Convert value to angle const angle = value * 180 - 90; // -90 to 90 degrees needle.style.transform = `rotate(${angle}deg)`; } // Set initial needle position const pos = await interpretate(args[0], env); setNeedlePosition(pos); // Middle position gauge.appendChild(needle); env.element.appendChild(gauge); env.local.update = setNeedlePosition; } core.gauge.update = async (args, env) => { const val = await interpretate(args[0], env); env.local.update(val); } core.gauge.destroy = () => { console.log('Nothing to do'); } core.gauge.virtual = true;
Let us test it!
gauge[0.3]
(*VB[*)(gauge[0.3])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRAeK5BITyxNTy0yBoPL9gCxdwlI"*)(*]VB*)
Dynamics
gvalue = 0.1; EventHandler[InputRange[0, 1, 0.1, 0.1], (gvalue = #) &] gauge[gvalue // Offload]
(*VB[*)(EventObject[<|"Id" -> "779cc45c-7931-400c-a30b-10b1478d8fbd", "Initial" -> 0.1, "View" -> "43a61dc6-e46a-46ab-a0e1-140f93d421a9"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKmxgnmhmmJJvpppqYJeoCcZJuokGqoa6hiUGapXGKiZFhoiUAhbUVjw=="*)(*]VB*)
(*VB[*)(gauge[Offload[gvalue]])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRAeK5BITyxNT4Vw2YGEf1paTn5iSjEbSKosMac0FQBuxw0r"*)(*]VB*)