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 |