otsdaq_utilities  v2_05_02_indev
gauge.js
1 function Gauge(placeholderName, configuration)
2 {
3  this.placeholderName = placeholderName;
4 
5  var self = this; // for internal d3 functions
6 
7  this.configure = function(configuration)
8  {
9  this.config = configuration;
10 
11  this.config.size = this.config.size * 0.9;
12 
13  this.config.raduis = this.config.size * 0.97 / 2;
14  this.config.cx = this.config.size / 2;
15  this.config.cy = this.config.size / 2;
16 
17  this.config.min = undefined != configuration.min ? configuration.min : 0;
18  this.config.max = undefined != configuration.max ? configuration.max : 100;
19  this.config.range = this.config.max - this.config.min;
20 
21  this.config.majorTicks = configuration.majorTicks || 5;
22  this.config.minorTicks = configuration.minorTicks || 2;
23 
24  this.config.greenColor = configuration.greenColor || "#109618";
25  this.config.yellowColor = configuration.yellowColor || "#FF9900";
26  this.config.redColor = configuration.redColor || "#DC3912";
27 
28  this.config.transitionDuration = configuration.transitionDuration || 500;
29  }
30 
31  this.render = function()
32  {
33  this.body = d3.select("#" + this.placeholderName)
34  .append("svg:svg")
35  .attr("class", "gauge")
36  .attr("width", this.config.size)
37  .attr("height", this.config.size);
38 
39  this.body.append("svg:circle")
40  .attr("cx", this.config.cx)
41  .attr("cy", this.config.cy)
42  .attr("r", this.config.raduis)
43  .style("fill", "#ccc")
44  .style("stroke", "#000")
45  .style("stroke-width", "0.5px");
46 
47  this.body.append("svg:circle")
48  .attr("cx", this.config.cx)
49  .attr("cy", this.config.cy)
50  .attr("r", 0.9 * this.config.raduis)
51  .style("fill", "#fff")
52  .style("stroke", "#e0e0e0")
53  .style("stroke-width", "2px");
54 
55  for (var index in this.config.greenZones)
56  {
57  this.drawBand(this.config.greenZones[index].from, this.config.greenZones[index].to, self.config.greenColor);
58  }
59 
60  for (var index in this.config.yellowZones)
61  {
62  this.drawBand(this.config.yellowZones[index].from, this.config.yellowZones[index].to, self.config.yellowColor);
63  }
64 
65  for (var index in this.config.redZones)
66  {
67  this.drawBand(this.config.redZones[index].from, this.config.redZones[index].to, self.config.redColor);
68  }
69 
70  if (undefined != this.config.label)
71  {
72  var fontSize = Math.round(this.config.size / 9);
73  this.body.append("svg:text")
74  .attr("x", this.config.cx)
75  .attr("y", this.config.cy / 2 + fontSize / 2)
76  .attr("dy", fontSize / 2)
77  .attr("text-anchor", "middle")
78  .text(this.config.label)
79  .style("font-size", fontSize + "px")
80  .style("fill", "#333")
81  .style("stroke-width", "0px");
82  }
83 
84  var fontSize = Math.round(this.config.size / 16);
85  var majorDelta = this.config.range / (this.config.majorTicks - 1);
86  for (var major = this.config.min; major <= this.config.max; major += majorDelta)
87  {
88  var minorDelta = majorDelta / this.config.minorTicks;
89  for (var minor = major + minorDelta; minor < Math.min(major + majorDelta, this.config.max); minor += minorDelta)
90  {
91  var point1 = this.valueToPoint(minor, 0.75);
92  var point2 = this.valueToPoint(minor, 0.85);
93 
94  this.body.append("svg:line")
95  .attr("x1", point1.x)
96  .attr("y1", point1.y)
97  .attr("x2", point2.x)
98  .attr("y2", point2.y)
99  .style("stroke", "#666")
100  .style("stroke-width", "1px");
101  }
102 
103  var point1 = this.valueToPoint(major, 0.7);
104  var point2 = this.valueToPoint(major, 0.85);
105 
106  this.body.append("svg:line")
107  .attr("x1", point1.x)
108  .attr("y1", point1.y)
109  .attr("x2", point2.x)
110  .attr("y2", point2.y)
111  .style("stroke", "#333")
112  .style("stroke-width", "2px");
113 
114  if (major == this.config.min || major == this.config.max)
115  {
116  var point = this.valueToPoint(major, 0.63);
117 
118  this.body.append("svg:text")
119  .attr("x", point.x)
120  .attr("y", point.y)
121  .attr("dy", fontSize / 3)
122  .attr("text-anchor", major == this.config.min ? "start" : "end")
123  .text(major)
124  .style("font-size", fontSize + "px")
125  .style("fill", "#333")
126  .style("stroke-width", "0px");
127  }
128  }
129 
130  var pointerContainer = this.body.append("svg:g").attr("class", "pointerContainer");
131 
132  var midValue = (this.config.min + this.config.max) / 2;
133 
134  var pointerPath = this.buildPointerPath(midValue);
135 
136  var pointerLine = d3.svg.line()
137  .x(function(d) { return d.x })
138  .y(function(d) { return d.y })
139  .interpolate("basis");
140 
141  pointerContainer.selectAll("path")
142  .data([pointerPath])
143  .enter()
144  .append("svg:path")
145  .attr("d", pointerLine)
146  .style("fill", "#dc3912")
147  .style("stroke", "#c63310")
148  .style("fill-opacity", 0.7)
149 
150  pointerContainer.append("svg:circle")
151  .attr("cx", this.config.cx)
152  .attr("cy", this.config.cy)
153  .attr("r", 0.12 * this.config.raduis)
154  .style("fill", "#4684EE")
155  .style("stroke", "#666")
156  .style("opacity", 1);
157 
158  var fontSize = Math.round(this.config.size / 10);
159  pointerContainer.selectAll("text")
160  .data([midValue])
161  .enter()
162  .append("svg:text")
163  .attr("x", this.config.cx)
164  .attr("y", this.config.size - this.config.cy / 4 - fontSize)
165  .attr("dy", fontSize / 2)
166  .attr("text-anchor", "middle")
167  .style("font-size", fontSize + "px")
168  .style("fill", "#000")
169  .style("stroke-width", "0px");
170 
171  this.redraw(this.config.min, 0);
172  }
173 
174  this.buildPointerPath = function(value)
175  {
176  var delta = this.config.range / 13;
177 
178  var head = valueToPoint(value, 0.85);
179  var head1 = valueToPoint(value - delta, 0.12);
180  var head2 = valueToPoint(value + delta, 0.12);
181 
182  var tailValue = value - (this.config.range * (1/(270/360)) / 2);
183  var tail = valueToPoint(tailValue, 0.28);
184  var tail1 = valueToPoint(tailValue - delta, 0.12);
185  var tail2 = valueToPoint(tailValue + delta, 0.12);
186 
187  return [head, head1, tail2, tail, tail1, head2, head];
188 
189  function valueToPoint(value, factor)
190  {
191  var point = self.valueToPoint(value, factor);
192  point.x -= self.config.cx;
193  point.y -= self.config.cy;
194  return point;
195  }
196  }
197 
198  this.drawBand = function(start, end, color)
199  {
200  if (0 >= end - start) return;
201 
202  this.body.append("svg:path")
203  .style("fill", color)
204  .attr("d", d3.svg.arc()
205  .startAngle(this.valueToRadians(start))
206  .endAngle(this.valueToRadians(end))
207  .innerRadius(0.65 * this.config.raduis)
208  .outerRadius(0.85 * this.config.raduis))
209  .attr("transform", function() { return "translate(" + self.config.cx + ", " + self.config.cy + ") rotate(270)" });
210  }
211 
212  this.redraw = function(value, transitionDuration)
213  {
214  var pointerContainer = this.body.select(".pointerContainer");
215 
216  pointerContainer.selectAll("text").text(Math.round(value));
217 
218  var pointer = pointerContainer.selectAll("path");
219  pointer.transition()
220  .duration(undefined != transitionDuration ? transitionDuration : this.config.transitionDuration)
221  //.delay(0)
222  //.ease("linear")
223  //.attr("transform", function(d)
224  .attrTween("transform", function()
225  {
226  var pointerValue = value;
227  if (value > self.config.max) pointerValue = self.config.max + 0.02*self.config.range;
228  else if (value < self.config.min) pointerValue = self.config.min - 0.02*self.config.range;
229  var targetRotation = (self.valueToDegrees(pointerValue) - 90);
230  var currentRotation = self._currentRotation || targetRotation;
231  self._currentRotation = targetRotation;
232 
233  return function(step)
234  {
235  var rotation = currentRotation + (targetRotation-currentRotation)*step;
236  return "translate(" + self.config.cx + ", " + self.config.cy + ") rotate(" + rotation + ")";
237  }
238  });
239  }
240 
241  this.valueToDegrees = function(value)
242  {
243  // thanks @closealert
244  //return value / this.config.range * 270 - 45;
245  return value / this.config.range * 270 - (this.config.min / this.config.range * 270 + 45);
246  }
247 
248  this.valueToRadians = function(value)
249  {
250  return this.valueToDegrees(value) * Math.PI / 180;
251  }
252 
253  this.valueToPoint = function(value, factor)
254  {
255  return { x: this.config.cx - this.config.raduis * factor * Math.cos(this.valueToRadians(value)),
256  y: this.config.cy - this.config.raduis * factor * Math.sin(this.valueToRadians(value)) };
257  }
258 
259  // initialization
260  this.configure(configuration);
261 }
262 
263 
264 
265 
266