diff options
author | Kyle Gunger <kgunger12@gmail.com> | 2024-11-20 00:38:14 -0500 |
---|---|---|
committer | Kyle Gunger <kgunger12@gmail.com> | 2024-11-20 00:38:14 -0500 |
commit | d33658089c6ab9fe0317e942161856bfcd242e93 (patch) | |
tree | bcf65fbd3820b76866d193ad7f0578502d5bdb10 | |
parent | 074fc672900cb569e530ce6edbceb0a086150fa1 (diff) |
Poorly constructed scrubber
-rw-r--r-- | scripts/gui-common/widgets.js | 218 | ||||
-rw-r--r-- | styles/themes/base.css | 3 | ||||
-rw-r--r-- | styles/widgets.css | 91 |
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 |