1+ import { BaseCustomWebComponentConstructorAppend , css , html } from "@node-projects/base-custom-webcomponent" ;
2+
3+ export class MaterialGaugeComponent extends BaseCustomWebComponentConstructorAppend {
4+
5+ static override readonly style = css `
6+ .gauge {
7+ position: relative;
8+ }
9+
10+ .gauge__container {
11+ margin: 0;
12+ padding: 0;
13+ position: absolute;
14+ left: 50%;
15+ overflow: hidden;
16+ text-align: center;
17+ transform: translateX(-50%);
18+ }
19+
20+ .gauge__background {
21+ z-index: 0;
22+ position: absolute;
23+ background-color: #C5CAE9;
24+ top: 0;
25+ border-radius: 300px 300px 0 0;
26+ }
27+
28+ .gauge__data {
29+ z-index: 1;
30+ position: absolute;
31+ background-color: #3F51B5;
32+ margin-left: auto;
33+ margin-right: auto;
34+ border-radius: 300px 300px 0 0;
35+ transform-origin: center bottom;
36+ }
37+
38+ .gauge__center {
39+ z-index: 2;
40+ position: absolute;
41+ background-color: #fff;
42+ margin-right: auto;
43+ border-radius: 300px 300px 0 0;
44+ }
45+
46+ .gauge__marker {
47+ z-index: 3;
48+ background-color: #fff;
49+ position: absolute;
50+ width: 1px;
51+ }
52+
53+ .gauge__needle {
54+ z-index: 4;
55+ background-color: #E91E63;
56+ height: 3px;
57+ position: absolute;
58+ transform-origin: left center;
59+ }
60+
61+ .gauge__labels {
62+ display: table;
63+ margin: 0 auto;
64+ position: relative;
65+ }
66+
67+ .gauge__label--low {
68+ display: table-cell;
69+ text-align: center;
70+ }
71+
72+ .gauge__label--spacer {
73+ display: table-cell;
74+ }
75+
76+ .gauge__label--high {
77+ display: table-cell;
78+ text-align: center;
79+ }
80+
81+ /*
82+ * Now define the rules that depend on the size of
83+ * the gauge. We start with sizing for a small mobile
84+ * device.
85+ */
86+
87+ .gauge { height: calc(120px + 3em); }
88+ .gauge__container { width: 240px; height: 120px; }
89+ .gauge__marker { height: 120px; left: 119.5px; }
90+ .gauge__background { width: 240px; height: 120px; }
91+ .gauge__center { width: 144px; height: 72px; top: 48px; margin-left: 48px; }
92+ .gauge__data { width: 240px; height: 120px; }
93+ .gauge__needle { left: 120px; top: 117px; width: 120px; }
94+ .gauge__labels { top: 120px; width: 240px; }
95+ .gauge__label--low { width: 48px; }
96+ .gauge__label--spacer { width: 144px; }
97+ .gauge__label--high { width: 48px; }
98+
99+ /*
100+ * Increase the gauge size slightly on larger viewports.
101+ */
102+
103+ @media only screen and (min-width: 400px) {
104+ .gauge { height: calc(150px + 3em); }
105+ .gauge__container { width: 300px; height: 150px; }
106+ .gauge__marker { height: 150px; left: 149.5px; }
107+ .gauge__background { width: 300px; height: 150px; }
108+ .gauge__center { width: 180px; height: 90px; top: 60px; margin-left: 60px; }
109+ .gauge__data { width: 300px; height: 150px; }
110+ .gauge__needle { left: 150px; top: 147px; width: 150px; }
111+ .gauge__labels { top: 150px; width: 300px; }
112+ .gauge__label--low { width: 60px; }
113+ .gauge__label--spacer { width: 180px; }
114+ .gauge__label--high { width: 60px; }
115+ }
116+
117+ /*
118+ * As an option, the 'gauge--liveupdate' class can be added
119+ * to the main gauge element. When this class is present,
120+ * we add a transition that animates any changes to the gauge
121+ * value. Currently, the app does not use this option because
122+ * all the inputs that can change gauge values are present
123+ * on tab panels that are different from the gauge itself.
124+ * Therefore, users won't be able to see any gauge changes
125+ * when they make input changes. The code is available, though,
126+ * should this change.
127+ */
128+
129+ .gauge--liveupdate .gauge__data,
130+ .gauge--liveupdate .gauge__needle {
131+ transition: all 1s ease-in-out;
132+ }
133+
134+ /*
135+ * For a given gauge value, x, ranging from 0.0 to 1.0, set
136+ * the 'transform: rotate()' property according to the
137+ * following equation: '-0.5 + 0.5x turns' The default
138+ * properties below represent an x value of 0.
139+ */
140+
141+ .gauge__data {
142+ transform: rotate(-.50turn);
143+ }
144+ .gauge__needle {
145+ -transform: rotate(-.50turn);
146+ }` ;
147+
148+ static override readonly template = html `
149+ < div class ="gauge gauge--liveupdate " id ="gauge ">
150+ < div class ="gauge__container ">
151+ < div class ="gauge__marker "> </ div >
152+ < div class ="gauge__background "> </ div >
153+ < div class ="gauge__center "> </ div >
154+ < div id ="gauge__data " class ="gauge__data "> </ div >
155+ < div id ="gauge__needle " class ="gauge__needle "> </ div >
156+ </ div >
157+ < div class ="gauge__labels mdl-typography__headline ">
158+ < span class ="gauge__label--low "> No</ span >
159+ < span class ="gauge__label--spacer "> </ span >
160+ < span class ="gauge__label--high "> Yes</ span >
161+ </ div >
162+ </ div > ` ;
163+
164+ static readonly is = "node-projects-material-gauge" ;
165+
166+ static readonly properties = {
167+ value : Number
168+ }
169+
170+ private _data : HTMLDivElement ;
171+ private _needle : HTMLDivElement ;
172+
173+ constructor ( ) {
174+ super ( ) ;
175+ this . _restoreCachedInititalValues ( ) ;
176+ this . _data = this . _getDomElement < HTMLDivElement > ( 'gauge__data' ) ;
177+ this . _needle = this . _getDomElement < HTMLDivElement > ( 'gauge__needle' ) ;
178+ }
179+
180+ ready ( ) {
181+ this . _parseAttributesToProperties ( ) ;
182+ this . refresh ( ) ;
183+ }
184+
185+ private _value : number = 0.0 ;
186+ get value ( ) { return this . _value ; }
187+ set value ( value : number ) { this . _value = value ; this . refresh ( ) ; }
188+
189+ refresh ( ) {
190+ const turns = - 0.5 + ( this . _value * 0.5 ) ;
191+ this . _data . style . transform = "rotate(" + turns + "turn)" ;
192+ this . _needle . style . transform = "rotate(" + turns + "turn)" ;
193+ }
194+ }
195+
196+ customElements . define ( MaterialGaugeComponent . is , MaterialGaugeComponent ) ;
0 commit comments