@@ -4,23 +4,24 @@ import { styleMap } from 'lit/directives/style-map.js';
44import { analog , ElementPin } from './pin' ;
55import { clamp } from './utils/clamp' ;
66
7- interface Point {
8- x : number ;
9- y : number ;
10- }
7+ const knobCenter = {
8+ x : 9.91 ,
9+ y : 8.18 ,
10+ } ;
1111
1212/** The potentiometer SVG is taken from https://freesvg.org/potentiometer and some of the
1313 functions are taken from https://github.com/vitaliy-bobrov/js-rocks knob component */
1414@customElement ( 'wokwi-potentiometer' )
1515export class PotentiometerElement extends LitElement {
1616 @property ( { type : Number } ) min = 0 ;
17- @property ( { type : Number } ) max = 100 ;
17+ @property ( { type : Number } ) max = 1023 ;
1818 @property ( ) value = 0 ;
1919 @property ( ) step = 1 ;
2020 @property ( ) startDegree = - 135 ;
2121 @property ( ) endDegree = 135 ;
22- private center : Point = { x : 0 , y : 0 } ;
22+
2323 private pressed = false ;
24+ private pageToKnobMatrix : SVGMatrix | null = null ;
2425
2526 readonly pinInfo : ElementPin [ ] = [
2627 { name : 'GND' , x : 29 , y : 68.5 , number : 1 , signals : [ { type : 'power' , signal : 'GND' } ] } ,
@@ -117,8 +118,8 @@ export class PotentiometerElement extends LitElement {
117118 < rect x ="5.4 " y =".70 " width ="9.1 " height ="1.9 " fill ="#ccdae3 " stroke-width =".15 " />
118119 < ellipse
119120 id ="knob "
120- cx =" 9.91 "
121- cy =" 8.18 "
121+ cx =${ knobCenter . x }
122+ cy =${ knobCenter . y }
122123 rx="7.27"
123124 ry="7.43"
124125 fill="#e4e8eb"
@@ -169,7 +170,11 @@ export class PotentiometerElement extends LitElement {
169170 private down ( event : MouseEvent ) {
170171 if ( event . button === 0 || window . navigator . maxTouchPoints ) {
171172 this . pressed = true ;
172- this . updatePotentiometerPosition ( event ) ;
173+
174+ event . stopPropagation ( ) ;
175+ event . preventDefault ( ) ;
176+
177+ this . updateKnobMatrix ( ) ;
173178 }
174179 }
175180
@@ -184,38 +189,33 @@ export class PotentiometerElement extends LitElement {
184189 this . pressed = false ;
185190 }
186191
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 ;
199195 }
200196
201197 private rotateHandler ( event : MouseEvent | TouchEvent ) {
202198 event . stopPropagation ( ) ;
203199 event . preventDefault ( ) ;
204200
201+ if ( ! this . pageToKnobMatrix ) {
202+ return ;
203+ }
204+
205205 const isTouch = event . type === 'touchmove' ;
206206 const pageX = isTouch ? ( event as TouchEvent ) . touches [ 0 ] . pageX : ( event as MouseEvent ) . pageX ;
207207 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 ;
210211 let deg = Math . round ( ( Math . atan2 ( y , x ) * 180 ) / Math . PI ) ;
211-
212- if ( deg <= 0 ) {
212+ if ( deg < 0 ) {
213213 deg += 360 ;
214214 }
215215
216216 deg -= 90 ;
217217
218- if ( x > 0 && y <= 0 ) {
218+ if ( x > 0 && y <= 0 && deg > 0 ) {
219219 deg -= 360 ;
220220 }
221221
0 commit comments