@@ -4,23 +4,24 @@ import { styleMap } from 'lit/directives/style-map.js';
4
4
import { analog , ElementPin } from './pin' ;
5
5
import { clamp } from './utils/clamp' ;
6
6
7
- interface Point {
8
- x : number ;
9
- y : number ;
10
- }
7
+ const knobCenter = {
8
+ x : 9.91 ,
9
+ y : 8.18 ,
10
+ } ;
11
11
12
12
/** The potentiometer SVG is taken from https://freesvg.org/potentiometer and some of the
13
13
functions are taken from https://github.com/vitaliy-bobrov/js-rocks knob component */
14
14
@customElement ( 'wokwi-potentiometer' )
15
15
export class PotentiometerElement extends LitElement {
16
16
@property ( { type : Number } ) min = 0 ;
17
- @property ( { type : Number } ) max = 100 ;
17
+ @property ( { type : Number } ) max = 1023 ;
18
18
@property ( ) value = 0 ;
19
19
@property ( ) step = 1 ;
20
20
@property ( ) startDegree = - 135 ;
21
21
@property ( ) endDegree = 135 ;
22
- private center : Point = { x : 0 , y : 0 } ;
22
+
23
23
private pressed = false ;
24
+ private pageToKnobMatrix : SVGMatrix | null = null ;
24
25
25
26
readonly pinInfo : ElementPin [ ] = [
26
27
{ name : 'GND' , x : 29 , y : 68.5 , number : 1 , signals : [ { type : 'power' , signal : 'GND' } ] } ,
@@ -117,8 +118,8 @@ export class PotentiometerElement extends LitElement {
117
118
< rect x ="5.4 " y =".70 " width ="9.1 " height ="1.9 " fill ="#ccdae3 " stroke-width =".15 " />
118
119
< ellipse
119
120
id ="knob "
120
- cx =" 9.91 "
121
- cy =" 8.18 "
121
+ cx =${ knobCenter . x }
122
+ cy =${ knobCenter . y }
122
123
rx="7.27"
123
124
ry="7.43"
124
125
fill="#e4e8eb"
@@ -169,7 +170,11 @@ export class PotentiometerElement extends LitElement {
169
170
private down ( event : MouseEvent ) {
170
171
if ( event . button === 0 || window . navigator . maxTouchPoints ) {
171
172
this . pressed = true ;
172
- this . updatePotentiometerPosition ( event ) ;
173
+
174
+ event . stopPropagation ( ) ;
175
+ event . preventDefault ( ) ;
176
+
177
+ this . updateKnobMatrix ( ) ;
173
178
}
174
179
}
175
180
@@ -184,38 +189,33 @@ export class PotentiometerElement extends LitElement {
184
189
this . pressed = false ;
185
190
}
186
191
187
- private updatePotentiometerPosition ( event : MouseEvent | TouchEvent ) {
188
- event . stopPropagation ( ) ;
189
- event . preventDefault ( ) ;
190
-
191
- const potentiometerRect = this . shadowRoot ?. querySelector ( '#knob' ) ?. getBoundingClientRect ( ) ;
192
-
193
- if ( potentiometerRect ) {
194
- this . center = {
195
- x : window . scrollX + potentiometerRect . left + potentiometerRect . width / 2 ,
196
- y : window . scrollY + potentiometerRect . top + potentiometerRect . height / 2 ,
197
- } ;
198
- }
192
+ private updateKnobMatrix ( ) {
193
+ const knob = this . shadowRoot ?. querySelector < SVGRectElement > ( '#knob' ) ;
194
+ this . pageToKnobMatrix = knob ?. getScreenCTM ( ) ?. inverse ( ) ?? null ;
199
195
}
200
196
201
197
private rotateHandler ( event : MouseEvent | TouchEvent ) {
202
198
event . stopPropagation ( ) ;
203
199
event . preventDefault ( ) ;
204
200
201
+ if ( ! this . pageToKnobMatrix ) {
202
+ return ;
203
+ }
204
+
205
205
const isTouch = event . type === 'touchmove' ;
206
206
const pageX = isTouch ? ( event as TouchEvent ) . touches [ 0 ] . pageX : ( event as MouseEvent ) . pageX ;
207
207
const pageY = isTouch ? ( event as TouchEvent ) . touches [ 0 ] . pageY : ( event as MouseEvent ) . pageY ;
208
- const x = this . center . x - pageX ;
209
- const y = this . center . y - pageY ;
208
+ const localPosition = new DOMPointReadOnly ( pageX , pageY ) . matrixTransform ( this . pageToKnobMatrix ) ;
209
+ const x = knobCenter . x - localPosition . x ;
210
+ const y = knobCenter . y - localPosition . y ;
210
211
let deg = Math . round ( ( Math . atan2 ( y , x ) * 180 ) / Math . PI ) ;
211
-
212
- if ( deg <= 0 ) {
212
+ if ( deg < 0 ) {
213
213
deg += 360 ;
214
214
}
215
215
216
216
deg -= 90 ;
217
217
218
- if ( x > 0 && y <= 0 ) {
218
+ if ( x > 0 && y <= 0 && deg > 0 ) {
219
219
deg -= 360 ;
220
220
}
221
221
0 commit comments