Mercurial > code > home > repos > light9
annotate web/fade/Light9Fader.ts @ 2405:69ca2b2fc133
overcomplicated attempt at persisting the pane layout in the rdf graph
this was hard because we have to somehow wait for the graph to load before config'ing the panes
author | drewp@bigasterisk.com |
---|---|
date | Fri, 17 May 2024 16:58:26 -0700 |
parents | 9a4bc2ea264e |
children |
rev | line source |
---|---|
2320 | 1 import debug from "debug"; |
2 import { css, html, LitElement, PropertyValueMap } from "lit"; | |
3 import { customElement, property, query } from "lit/decorators.js"; | |
4 | |
2372
06bf6dae8e64
reorg tools into light9/web/ and a single vite instance
drewp@bigasterisk.com
parents:
2355
diff
changeset
|
5 import { clamp } from "../floating_color_picker"; |
2320 | 6 const log = debug("fade"); |
7 | |
8 class Drag { | |
9 constructor(public startDragPxY: number, public startDragValue: number) {} | |
10 } | |
11 | |
12 @customElement("light9-fader") | |
13 export class Light9Fader extends LitElement { | |
14 static styles = [ | |
15 css` | |
16 :host { | |
17 display: inline-block; | |
18 border: 2px gray inset; | |
19 background: #000; | |
2355 | 20 height: 80px; |
2320 | 21 } |
22 #handle { | |
23 background: gray; | |
2400 | 24 border: 3px outset #838499; |
2320 | 25 position: relative; |
2400 | 26 left: 0px; |
2320 | 27 right: -25px; |
2400 | 28 border-radius: 4px; |
29 margin: 0 1px; | |
2320 | 30 } |
31 `, | |
32 ]; | |
33 | |
34 @property() value: number = 0; | |
35 | |
36 @query("#handle") handleEl!: HTMLElement; | |
37 | |
2355 | 38 troughHeight = 80 - 2 - 2 - 5 - 5; |
2400 | 39 handleHeight = 16; |
2320 | 40 |
41 drag?: Drag; | |
42 unmutedValue: number = 1; | |
43 | |
44 render() { | |
45 return html` <div id="handle"><hr /></div> `; | |
46 } | |
47 | |
48 protected update(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void { | |
49 super.update(changedProperties); | |
50 if (changedProperties.has("value")) { | |
51 } | |
52 } | |
2339
2210d934d62d
fader was echoing external edits as patches back into the graph. This fixes that the wrong way, circumventing lit
drewp@bigasterisk.com
parents:
2331
diff
changeset
|
53 valueChangedFromUi() { |
2400 | 54 this.value = clamp(this.value, 0, 1); |
2339
2210d934d62d
fader was echoing external edits as patches back into the graph. This fixes that the wrong way, circumventing lit
drewp@bigasterisk.com
parents:
2331
diff
changeset
|
55 this.dispatchEvent(new CustomEvent("change", { detail: { value: this.value } })); |
2210d934d62d
fader was echoing external edits as patches back into the graph. This fixes that the wrong way, circumventing lit
drewp@bigasterisk.com
parents:
2331
diff
changeset
|
56 } |
2320 | 57 |
58 protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void { | |
59 super.updated(_changedProperties); | |
60 const y = this.sliderTopY(this.value); | |
61 this.handleEl.style.top = y + "px"; | |
62 } | |
63 | |
64 protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void { | |
65 super.firstUpdated(_changedProperties); | |
66 this.handleEl.style.height = this.handleHeight + "px"; | |
67 this.events(); | |
68 } | |
69 | |
70 events() { | |
71 const hand = this.handleEl; | |
72 hand.addEventListener("mousedown", (ev: MouseEvent) => { | |
73 ev.stopPropagation(); | |
74 if (ev.buttons == 1) { | |
75 this.drag = new Drag(ev.clientY, this.value); | |
76 } else if (ev.buttons == 2) { | |
77 this.onRmb(); | |
78 } | |
79 }); | |
80 this.addEventListener("mousedown", (ev: MouseEvent) => { | |
81 ev.stopPropagation(); | |
82 if (ev.buttons == 1) { | |
83 this.value = this.sliderValue(ev.offsetY); | |
2400 | 84 this.valueChangedFromUi(); |
2320 | 85 this.drag = new Drag(ev.clientY, this.value); |
86 } else if (ev.buttons == 2) { | |
87 // RMB in trough | |
88 this.onRmb(); | |
89 } | |
90 }); | |
91 | |
92 this.addEventListener("contextmenu", (event) => { | |
93 event.preventDefault(); | |
94 }); | |
95 | |
96 this.addEventListener("wheel", (ev: WheelEvent) => { | |
97 ev.preventDefault(); | |
2400 | 98 this.value += (ev.deltaY / this.troughHeight) * -0.03; |
99 this.valueChangedFromUi(); | |
2320 | 100 }); |
101 | |
102 const maybeDrag = (ev: MouseEvent) => { | |
103 if (ev.buttons != 1) return; | |
104 if (this.drag === undefined) return; | |
105 ev.stopPropagation(); | |
106 this.onMouseDrag(ev.clientY - this.drag.startDragPxY!); | |
107 }; | |
108 hand.addEventListener("mousemove", maybeDrag); | |
109 this.addEventListener("mousemove", maybeDrag); | |
110 window.addEventListener("mousemove", maybeDrag); | |
111 | |
112 hand.addEventListener("mouseup", this.onMouseUpAnywhere.bind(this)); | |
113 this.addEventListener("mouseup", this.onMouseUpAnywhere.bind(this)); | |
114 window.addEventListener("mouseup", this.onMouseUpAnywhere.bind(this)); | |
115 } | |
116 onRmb() { | |
117 if (this.value > 0.1) { | |
118 // mute | |
119 this.unmutedValue = this.value; | |
120 this.value = 0; | |
121 } else { | |
122 // unmute | |
123 this.value = this.unmutedValue; | |
124 } | |
2400 | 125 this.valueChangedFromUi(); |
2320 | 126 } |
127 onMouseDrag(dy: number) { | |
128 if (this.drag === undefined) throw "unexpected"; | |
129 this.value = this.drag.startDragValue - dy / this.troughHeight; | |
2400 | 130 this.valueChangedFromUi(); |
2320 | 131 } |
132 | |
133 onMouseUpAnywhere() { | |
134 this.drag = undefined; | |
135 } | |
136 | |
137 sliderTopY(value: number): number { | |
2400 | 138 const usableY = this.troughHeight - this.handleHeight / 2 - 1; |
2320 | 139 const yAdj = this.handleHeight / 2 - 5 - 2; |
140 return (1 - value) * usableY + yAdj; | |
141 } | |
142 sliderValue(offsetY: number): number { | |
143 const usableY = this.troughHeight - this.handleHeight; | |
144 const yAdj = this.handleHeight / 2 - 5 - 2; | |
145 return clamp(1 - (offsetY - yAdj) / usableY, 0, 1); | |
146 } | |
147 } |