summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2024-11-20 00:38:14 -0500
committerKyle Gunger <kgunger12@gmail.com>2024-11-20 00:38:14 -0500
commitd33658089c6ab9fe0317e942161856bfcd242e93 (patch)
treebcf65fbd3820b76866d193ad7f0578502d5bdb10
parent074fc672900cb569e530ce6edbceb0a086150fa1 (diff)
Poorly constructed scrubber
-rw-r--r--scripts/gui-common/widgets.js218
-rw-r--r--styles/themes/base.css3
-rw-r--r--styles/widgets.css91
3 files changed, 293 insertions, 19 deletions
diff --git a/scripts/gui-common/widgets.js b/scripts/gui-common/widgets.js
index 8293b74..40b8bae 100644
--- a/scripts/gui-common/widgets.js
+++ b/scripts/gui-common/widgets.js
@@ -78,6 +78,8 @@ class Widget extends EventTarget{
this.#value[id] = v;
if (emit)
this.#emitChangeEvent();
+ else if (id == "value")
+ this.update();
}
/** @param {boolean} i */
@@ -244,6 +246,16 @@ class WidgetButton extends Widget
this.#touching[i.identifier] = 1;
}
}
+
+ setId(id, v, emit = false)
+ {
+ if (id == "false" || id == "true")
+ {
+ if (this.get() == this.get(id))
+ super.setId("value", v);
+ }
+ super.setId(id, v, emit);
+ }
}
/**
@@ -358,10 +370,8 @@ class WidgetToggle extends Widget
{
if (this.get() == this.get(id))
super.setId("value", v);
- super.setId(id, v, emit);
}
- else
- super.setId(id, v, emit);
+ super.setId(id, v, emit);
}
}
@@ -1158,26 +1168,214 @@ class WidgetSelectButton extends Widget
*/
class WidgetScrubber extends WidgetDragable
{
- constructor()
+ /** @type {HTMLElement} */
+ #detail = null;
+ /** @type {HTMLElement} */
+ #fill = null;
+
+ #binder = null;
+
+ /** @type {number} */
+ #tmpNum = 0;
+ #percent = 0;
+
+ /** @type {number} */
+ #interval = null;
+
+ /** @type {number} */
+ #zone = 0;
+
+ /**
+ *
+ * @param {number} value Starting value
+ * @param {number} max Maximum value
+ * @param {number} min Minimum value
+ * @param {number} step Step increace/decrease per zone
+ * @param {number} zones Zones on either side of the zero-point
+ * @param {number} speed Speed per value change (ms)
+ */
+ constructor(value = 5, max = 10, min = 1, step = 0.5, zones = 3, speed = 350, spring = 1.5)
{
super(1);
this.element.classList.add("scrubber");
- let fill = document.createElement("div");
- fill.classList.add("fill");
- this.element.appendChild(fill);
+ this.#fill = document.createElement("div");
+ this.#fill.classList.add("fill");
+ this.element.appendChild(this.#fill);
+
+ this.#detail = document.createElement("div");
+ this.#detail.classList.add("detail");
+ this.element.appendChild(this.#detail);
this.element.style.setProperty("--percent", 0);
+
+ super.setId("max", max);
+ super.setId("min", min);
+ super.setId("step", step);
+ super.setId("zones", zones);
+ super.setId("speed", speed);
+ super.setId("spring", spring);
+ super.setId("value", value);
+
+ this.#binder = this.#i_update.bind(this);
+ this.#detail.innerText = this.get();
+ }
+
+ #clear()
+ {
+ let a = this.#interval;
+ if (this.#interval != null)
+ {
+ this.#interval = null;
+ clearInterval(a);
+ }
+ }
+
+ #common_move(x, y)
+ {
+ let rect = this.element.getBoundingClientRect();
+ let point = 0, dist = 0;
+ if (this.element.classList.contains("h"))
+ {
+ dist = rect.width / 2;
+ point = x - (rect.left + dist);
+ }
+ else
+ {
+ dist = rect.height / 2;
+ point = (rect.top + dist) - y;
+ }
+
+ if (dist != 0)
+ this.#percent = point / dist;
+ else
+ this.#percent = 0;
+
+ this.update();
}
- move(e)
+ /**
+ * @param {MouseEvent} event
+ * @param {number} btns
+ * @param {boolean} gone
+ */
+ move(event, btns, gone)
+ {
+ if (btns == 0)
+ {
+ if (event.type == "mouseup")
+ {
+ if (this.#interval != null)
+ this.#clear();
+ this.#zone = 0;
+ this.set(this.#tmpNum);
+ this.element.style.setProperty("--percent", 0);
+ }
+
+ return;
+ }
+ else if (event.type == "mousedown")
+ {
+ this.#tmpNum = this.get();
+ }
+
+ this.#common_move(event.clientX, event.clientY);
+ }
+
+ /**
+ * @param {"touchstart" | "touchend" | "touchmove"} type
+ * @param {Touch[]} touches
+ */
+ touch(type, touches)
{
- console.log(e);
+ if (type == "touchend")
+ {
+ if (this.#interval != null)
+ this.#clear();
+ this.#zone = 0;
+ this.set(this.#tmpNum);
+ this.element.style.setProperty("--percent", 0);
+ }
+ else if (type == "touchstart")
+ {
+ this.#tmpNum = this.get();
+ }
+
+ if (touches.length < 1)
+ return;
+
+ this.#common_move(touches[0].clientX, touches[0].clientY);
}
- touch()
+ #f_update()
{
+ let zones = this.get("zones");
+ if (this.#fill.children.length != zones * 2 + 1)
+ {
+ while (this.#fill.firstElementChild != null)
+ this.#fill.firstElementChild.remove();
+
+
+ for (let i = -zones; i <= zones; i++)
+ {
+ let z = document.createElement("div");
+ z.className = "zone";
+ z.style.setProperty("--zone", i);
+ this.#fill.appendChild(z);
+ }
+
+ this.#fill.style.setProperty("--zones", zones);
+ }
+ for(let i = 0; i < this.#fill.children.length; i++)
+ {
+ if (i == zones + this.#zone)
+ this.#fill.children[i].classList.add("active");
+ else
+ this.#fill.children[i].classList.remove("active");
+ }
+ }
+
+ update()
+ {
+ let zones = this.get("zones"), spring = this.get("spring");
+ this.#f_update();
+
+ let percent = Math.min(Math.max(this.#percent / spring, -1), 1);
+ this.#zone = Math.round(percent * zones);
+
+ this.element.style.setProperty("--percent", percent);
+ if (this.#interval == null && this.#zone != 0)
+ {
+ this.#interval = setInterval(this.#binder, this.get("speed"));
+ }
+ }
+
+ #i_update()
+ {
+ if (this.#zone == 0 && this.#interval != null)
+ this.#clear();
+
+ let step = this.get("step"), max = this.get("max"), min = this.get("min");
+
+ this.#tmpNum = Math.max(Math.min(this.#tmpNum + this.#zone * step, max), min);
+
+ this.#detail.innerText = this.#tmpNum;
+ }
+
+ setId(id, v, emit = false)
+ {
+ super.setId(id, v, emit);
+ if (id == "max" || id == "min" || id == "step" || id == "zones" || id == "spring")
+ {
+ this.update();
+ }
+ else if (id == "speed" && this.#interval != null)
+ {
+ let a = this.#interval;
+ this.#interval = setInterval(this.#binder, v);
+ clearInterval(a);
+ }
}
}
diff --git a/styles/themes/base.css b/styles/themes/base.css
index 68f07e1..53ac83f 100644
--- a/styles/themes/base.css
+++ b/styles/themes/base.css
@@ -46,4 +46,7 @@
--w-scr-nub: #eee;
--w-scr-nub-hover: white;
--w-scr-nub-active: white;
+ --w-scr-back: rgba(255, 255, 255, 0);
+ --w-scr-back-other: rgba(255, 255, 255, 0.3);
+ --w-scr-back-active: rgba(62, 162, 255, 0.5);
} \ No newline at end of file
diff --git a/styles/widgets.css b/styles/widgets.css
index c3e6f67..53f3568 100644
--- a/styles/widgets.css
+++ b/styles/widgets.css
@@ -190,7 +190,7 @@
display: block;
position: absolute;
- left: calc(100% + 20px);
+ right: calc(100% + 20px);
bottom: calc(-1 * var(--base-unit) / 2 + 100% * var(--percent));
background-color: rgba(0, 132, 255, 0);
@@ -214,8 +214,8 @@
}
.slider.h > .detail, .color-light.h > .detail, .color-temp.h > .detail {
- top: calc(100% + 20px);
- left: calc(-1.2 * var(--base-unit) / 2 + 100% * var(--percent));
+ bottom: calc(100% + 20px);
+ right: calc(-1.2 * var(--base-unit) / 2 + 100% * (1 - var(--percent)));
}
.slider:active > .detail, .slider.touch > .detail {
@@ -599,16 +599,17 @@
.scrubber {
width: calc(var(--base-unit) + 5px);
- height: calc(3 * var(--base-unit) + 5px);
+ height: calc(4 * var(--base-unit) + 5px);
margin: 10px;
box-shadow: inset 5px 5px var(--w-shadow);
--w-bg-hover: var(--w-bg);
--w-bg-active: var(--w-bg);
+ overflow: unset;
}
.scrubber.h {
height: calc(var(--base-unit) + 5px);
- width: calc(3 * var(--base-unit) + 5px);
+ width: calc(6 * var(--base-unit) + 5px);
}
.scrubber > .fill {
@@ -617,9 +618,11 @@
height: 100%;
left: 0;
top: 0;
+ overflow: hidden;
+ border-radius: 10px;
}
-.scrubber > .fill::before {
+.scrubber > .fill::after {
content: '◈';
display: block;
height: calc(var(--base-unit) - 10px);
@@ -638,16 +641,86 @@
transition-duration: 0.15s;
}
-.scrubber.h > .fill::before {
+.scrubber.h > .fill::after {
left: calc(50% - (var(--base-unit) - 10px) / 2 + (50% * var(--percent)));
bottom: calc(50% - (var(--base-unit) - 10px) / 2);
}
-.scrubber:hover > .fill::before, .scrubber.touch > .fill::before {
+.scrubber:hover > .fill::after, .scrubber.touch > .fill::after {
background-color: var(--w-scr-nub-hover);
}
-.scrubber:active > .fill::before, .scrubber.touch > .fill::before {
+.scrubber:active > .fill::after, .scrubber.touch > .fill::after {
background-color: var(--w-scr-nub-active);
transition-duration: 0s;
+}
+
+.scrubber > .fill > .zone
+{
+ width: 100%;
+ height: calc(50% / var(--zones));
+ box-sizing: border-box;
+
+ background-color: var(--w-scr-back);
+
+ position:absolute;
+ bottom: calc(50% * (var(--zone) + var(--zones)) / var(--zones) - (25% / var(--zones)));
+ left: 0;
+ transition-duration: 0.15s;
+}
+
+.scrubber.h > .fill > .zone
+{
+ height: 100%;
+ width: calc(50% / var(--zones));
+ border-bottom: none;
+
+ left: calc(50% * (var(--zone) + var(--zones)) / var(--zones) - (25% / var(--zones)));
+ bottom: 0;
+}
+
+.scrubber > .fill > .zone:nth-child(2n) {
+ background-color: var(--w-scr-back-other);
+}
+
+.scrubber:active > .fill > .zone.active, .scrubber.touch > .fill > .zone.active {
+ background-color: var(--w-scr-back-active);
+}
+
+.scrubber > .detail {
+ display: block;
+ position: absolute;
+
+ right: calc(100% + 20px);
+ bottom: calc(50% - var(--base-unit) / 2);
+
+ background-color: rgba(0, 132, 255, 0);
+ color: rgba(255, 255, 255, 0);
+
+ border-radius: 10px;
+
+ z-index: 2;
+
+ font-weight: bold;
+ width: calc(1.2 * var(--base-unit));
+ height: var(--base-unit);
+ pointer-events: none;
+ user-select: none;
+
+ align-content: center;
+ text-align: center;
+ padding: 2px;
+
+ transition-duration: 0.15s;
+}
+
+.scrubber.h > .detail {
+ bottom: calc(100% + 20px);
+ right: calc(50% - 1.2 * var(--base-unit) / 2);
+}
+
+.scrubber:active > .detail, .scrubber.touch > .detail {
+ background-color: rgba(0, 132, 255, 1);
+ color: rgba(255, 255, 255, 1);
+ transition-duration: 0s;
} \ No newline at end of file