diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e66ee --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.ps1 diff --git a/assets/main.css b/assets/main.css index 3c0092e..0526143 100755 --- a/assets/main.css +++ b/assets/main.css @@ -46,6 +46,21 @@ ul { bottom: 30px; right: 30px; } +.subDivisions { + background-color: rgba(255,255,255,0.2); + padding: 0.2em; + box-shadow: 0 2px 5px rgba(0,0,0,0.1); +} + +.subDivisions label { + width: 150px !important; +} +.subDivisions > span.fd-slider { + width: 80px !important; +} +.subDivisions > input { + width: 80px !important; +} a { color: #333; } @@ -64,10 +79,13 @@ label { font-size: 14px; vertical-align: top; } -.opts label { +.opts label:not(.omit) { line-height: 25px; width: 80px; } +.omit{ + width: 40px; +} span.fd-slider { vertical-align: top; display: inline-block; @@ -135,8 +153,8 @@ h3 { background: #f9f9f9; position: relative; color: #fff; float: left; - width: 280px; - height: 280px; + width: 380px; + height: 320px; margin: 0 20px 20px 0; -webkit-border-radius: 10px; -moz-border-radius: 10px; @@ -144,7 +162,7 @@ h3 { clear: both; } #canvas-preview{ - width: 280px; top: 100px; + width: 380px; top: 100px; position: relative; } #preview-textfield{ @@ -152,8 +170,21 @@ h3 { text-align: center; font-size: 2em; font-weight: bold; color: black; font-family: 'Amaranth', sans-serif; } +#auto-animator { + position: absolute; top: 320px; left: 0; right: 0; + text-align: left; font-size: 2em; font-weight: bold; + color: black; font-family: 'Amaranth', sans-serif; +} +#auto-animator label{ + width: 200px; + vertical-align: baseline; +} +.reset { + top: 65px !important; + font-size: 2em; +} .donut #preview-textfield{ - top: 140px; font-size: 1.3em; + top: 180px; font-size: 1.3em; } .donut #opts-donut{ display: block; diff --git a/bower.json b/bower.json index f0495f1..7dccd9c 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "gauge.js", - "version": "1.3.5", + "version": "1.3.6", "main": [ "dist/gauge.js", "dist/gauge.min.js", diff --git a/dist/gauge.coffee b/dist/gauge.coffee index fde9c69..a36f12d 100644 --- a/dist/gauge.coffee +++ b/dist/gauge.coffee @@ -168,6 +168,9 @@ class AnimatedText extends ValueUpdater @value = 1 * value constructor: (@elem, @text=false) -> + super() + if @elem is undefined + throw new Error 'The element isn\'t defined.' @value = 1 * @elem.innerHTML if @text @value = 0 @@ -189,6 +192,9 @@ class GaugePointer extends ValueUpdater displayedValue: 0 value: 0 options: + pointerType: "triangle" # triangle / line + pointerEnd: "butt" # butt / round / square + hideCentre: false strokeWidth: 0.035 length: 0.1 color: "#000000" @@ -198,6 +204,9 @@ class GaugePointer extends ValueUpdater img: null constructor: (@gauge) -> + #super() + if @gauge is undefined + throw new Error 'The element isn\'t defined.' @ctx = @gauge.ctx @canvas = @gauge.canvas super(false, false) @@ -206,6 +215,7 @@ class GaugePointer extends ValueUpdater setOptions: (options=null) -> @options = mergeObjects(@options, options) @length = 2*@gauge.radius * @gauge.options.radiusScale * @options.length + @pointerEnd = @options.pointerEnd || "butt" @strokeWidth = @canvas.height * @options.strokeWidth @maxValue = @gauge.maxValue @minValue = @gauge.minValue @@ -227,17 +237,26 @@ class GaugePointer extends ValueUpdater endX = Math.round(@strokeWidth * Math.cos(angle + Math.PI/2)) endY = Math.round(@strokeWidth * Math.sin(angle + Math.PI/2)) - @ctx.fillStyle = @options.color - @ctx.beginPath() - - @ctx.arc(0, 0, @strokeWidth, 0, Math.PI*2, true) - @ctx.fill() - - @ctx.beginPath() - @ctx.moveTo(startX, startY) - @ctx.lineTo(x, y) - @ctx.lineTo(endX, endY) - @ctx.fill() + if(!@options.hideCentre) + @ctx.beginPath() + @ctx.fillStyle = @options.color + @ctx.arc(0, 0, @strokeWidth, 0, Math.PI*2, false) + @ctx.fill() + + if(@options.pointerType == "triangle") + @ctx.beginPath() + @ctx.moveTo(startX, startY) + @ctx.lineTo(x, y) + @ctx.lineTo(endX, endY) + @ctx.fill() + else + @ctx.beginPath() + @ctx.lineCap = @pointerEnd + @ctx.strokeStyle = @options.color + @ctx.lineWidth = @strokeWidth + @ctx.moveTo(0, 0) + @ctx.lineTo(x, y) + @ctx.stroke() if @img imgX = Math.round(@img.width * @options.iconScale) @@ -286,7 +305,11 @@ class Gauge extends BaseGauge colorStop: undefined gradientType: 0 # 0 : radial, 1 : linear strokeColor: "#e0e0e0" + labelHoriz: false pointer: + pointerType: "triangle" + pointerEnd: "butt" + hideCenter: false length: 0.8 strokeWidth: 0.035 iconScale: 1.0 @@ -308,9 +331,10 @@ class Gauge extends BaseGauge w = @canvas.clientWidth; @canvas.height = h; @canvas.width = w; + @gp = [new GaugePointer(@)] @setOptions() - @render() + setOptions: (options=null) -> super(options) @@ -323,10 +347,11 @@ class Gauge extends BaseGauge @lineWidth = @availableHeight * @options.lineWidth # .2 - .7 @radius = (@availableHeight - @lineWidth/2) / (1.0 + @extraPadding) @ctx.clearRect(0, 0, @canvas.width, @canvas.height) - # @render() + for gauge in @gp gauge.setOptions(@options.pointer) gauge.render() + @render() return @ configPercentColors: () -> @@ -419,36 +444,114 @@ class Gauge extends BaseGauge font = staticLabels.font or "10px Times" re = /\d+\.?\d?/ match = font.match(re)[0] - rest = font.slice(match.length); - fontsize = parseFloat(match) * this.displayScale; - @ctx.font = fontsize + rest; - @ctx.fillStyle = staticLabels.color || "#000000"; - + rest = font.slice(match.length) + fontsize = parseFloat(match) * this.displayScale + labelHoriz = @options.labelHoriz + @ctx.font = fontsize + rest + @ctx.fillStyle = staticLabels.color || "#000000" + @ctx.textBaseline = "bottom" @ctx.textAlign = "center" + for value in staticLabels.labels - # Draw labels depending on limitMin/Max - if (not @options.limitMin or value >= @minValue) and (not @options.limitMax or value <= @maxValue) - rotationAngle = @getAngle(value) - 3*Math.PI/2 - @ctx.rotate(rotationAngle) - @ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, -radius - @lineWidth/2) - @ctx.rotate(-rotationAngle) + if (value.label != undefined) + # Draw labels depending on limitMin/Max + if (not @options.limitMin or value >= @minValue) and (not @options.limitMax or value <= @maxValue) + font = value.font || staticLabels.font + match = font.match(re)[0] + rest = font.slice(match.length) + fontsize = parseFloat(match) * this.displayScale + @ctx.font = fontsize + rest + rotationAngle = @getAngle(value.label) - 3 * Math.PI / 2 + @ctx.rotate(rotationAngle) + if(labelHoriz == true) + # translate to position then render horizontal then reset + offset = (-radius - @lineWidth / 2) * (1.01 + (fontsize / 100)) + (value.label.toString().length / 20) + console.log(offset, value.label, fontsize) + @ctx.translate(0, offset) + @ctx.rotate(-rotationAngle) + @ctx.fillText(formatNumber(value.label, staticLabels.fractionDigits), 0, 0) + @ctx.rotate(rotationAngle) + @ctx.translate(0, -offset) + else + @ctx.fillText(formatNumber(value.label, staticLabels.fractionDigits), 0, -radius - @lineWidth / 2) + + @ctx.rotate(-rotationAngle) + else + # Draw labels depending on limitMin/Max + if (not @options.limitMin or value >= @minValue) and (not @options.limitMax or value <= @maxValue) + rotationAngle = @getAngle(value) - 3 * Math.PI / 2 + @ctx.rotate(rotationAngle) + if(labelHoriz == true) + offset = (-radius - @lineWidth / 2) * (1.01 + (fontsize / 100)) + (value.toString().length / 20) + @ctx.translate(0, offset) + @ctx.rotate(-rotationAngle) + @ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, 0) + @ctx.rotate(rotationAngle) + @ctx.translate(0, -offset) + else + @ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, -radius - @lineWidth / 2) + @ctx.rotate(-rotationAngle) + @ctx.restore() + renderTicks: (ticksOptions, w, h, radius) -> + if ticksOptions != {} + divisionCount = ticksOptions.divisions || 0 + subdivisionCount = ticksOptions.subDivisions || 0 + divColor = ticksOptions.divColor || '#fff' + subColor = ticksOptions.subColor || '#fff' + divLength = ticksOptions.divLength || 0.7; # default + subLength = ticksOptions.subLength || 0.2; # default + range = parseFloat(@maxValue) - parseFloat(@minValue) # total value range + rangeDivisions = parseFloat(range) / parseFloat(ticksOptions.divisions) # get division step + subDivisions = parseFloat(rangeDivisions) / parseFloat(ticksOptions.subDivisions) + currentDivision = parseFloat(@minValue) + currentSubDivision = 0.0 + subDivisions + lineWidth = range / 400 # base + divWidth = lineWidth * (ticksOptions.divWidth || 1) + subWidth = lineWidth * (ticksOptions.subWidth || 1) + + for t in [0...divisionCount + 1] by 1 + @ctx.lineWidth = @lineWidth * divLength + scaleMutate = (@lineWidth / 2) * ( 1 - divLength) + tmpRadius = (@radius * @options.radiusScale) + scaleMutate + + @ctx.strokeStyle = divColor + @ctx.beginPath() + @ctx.arc(0, 0, tmpRadius, @getAngle(currentDivision - divWidth), @getAngle(currentDivision + divWidth), false) + @ctx.stroke() + + currentSubDivision = currentDivision + subDivisions + currentDivision += rangeDivisions + if t != ticksOptions.divisions && subdivisionCount > 0 # if its not the last marker then draw subs + for st in [0...subdivisionCount - 1] by 1 + @ctx.lineWidth = @lineWidth * subLength + scaleMutate = (@lineWidth / 2) * ( 1 - subLength) + tmpRadius = (@radius * @options.radiusScale) + scaleMutate + + @ctx.strokeStyle = subColor + @ctx.beginPath() + @ctx.arc(0, 0, tmpRadius, @getAngle(currentSubDivision - subWidth), @getAngle(currentSubDivision + subWidth), false) + @ctx.stroke() + currentSubDivision += subDivisions + + #@ctx.restore() + render: () -> # Draw using canvas w = @canvas.width / 2 - h = @canvas.height*@paddingTop + @availableHeight - (@radius + @lineWidth/2)*@extraPadding + #h = (@canvas.height * @paddingTop + @availableHeight) - ((@radius + @lineWidth / 2) * @extraPadding) + h = (@canvas.height * @paddingTop + @availableHeight) - ((@radius + @lineWidth /2) * @extraPadding) displayedAngle = @getAngle(@displayedValue) if @textField @textField.render(@) @ctx.lineCap = "butt" - radius = @radius * @options.radiusScale if (@options.staticLabels) @renderStaticLabels(@options.staticLabels, w, h, radius) - + if (@options.staticZones) @ctx.save() @ctx.translate(w, h) @@ -461,11 +564,16 @@ class Gauge extends BaseGauge max = zone.max if @options.limitMax and max > @maxValue max = @maxValue + tmpRadius = @radius + if (zone.height) + @ctx.lineWidth = @lineWidth * zone.height + scaleMutate = (@lineWidth / 2) * (zone.offset || 1 - zone.height) + tmpRadius = (@radius * @options.radiusScale) + scaleMutate + @ctx.strokeStyle = zone.strokeStyle @ctx.beginPath() - @ctx.arc(0, 0, radius, @getAngle(min), @getAngle(max), false) + @ctx.arc(0, 0, tmpRadius, @getAngle(min), @getAngle(max), false) @ctx.stroke() - @ctx.restore() else if @options.customFillStyle != undefined @@ -492,9 +600,16 @@ class Gauge extends BaseGauge @ctx.beginPath() @ctx.arc(w, h, radius, displayedAngle, (2 - @options.angle) * Math.PI, false) @ctx.stroke() + @ctx.save() + @ctx.translate(w, h) + + if (@options.renderTicks) + @renderTicks(@options.renderTicks, w, h, radius) - + + @ctx.restore() # Draw pointers from (w, h) + @ctx.translate(w, h) for gauge in @gp gauge.update(true) diff --git a/dist/gauge.js b/dist/gauge.js index f7d7203..9a43c81 100644 --- a/dist/gauge.js +++ b/dist/gauge.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.11.1 +// Generated by CoffeeScript 1.10.0 (function() { var AnimatedText, AnimatedTextFactory, Bar, BaseDonut, BaseGauge, Donut, Gauge, GaugePointer, TextRenderer, ValueUpdater, addCommas, cutHex, formatNumber, mergeObjects, secondsToString, slice = [].slice, @@ -265,6 +265,10 @@ function AnimatedText(elem1, text) { this.elem = elem1; this.text = text != null ? text : false; + AnimatedText.__super__.constructor.call(this); + if (this.elem === void 0) { + throw new Error('The element isn\'t defined.'); + } this.value = 1 * this.elem.innerHTML; if (this.text) { this.value = 0; @@ -305,6 +309,9 @@ GaugePointer.prototype.value = 0; GaugePointer.prototype.options = { + pointerType: "triangle", + pointerEnd: "butt", + hideCentre: false, strokeWidth: 0.035, length: 0.1, color: "#000000", @@ -317,6 +324,9 @@ function GaugePointer(gauge1) { this.gauge = gauge1; + if (this.gauge === void 0) { + throw new Error('The element isn\'t defined.'); + } this.ctx = this.gauge.ctx; this.canvas = this.gauge.canvas; GaugePointer.__super__.constructor.call(this, false, false); @@ -329,6 +339,7 @@ } this.options = mergeObjects(this.options, options); this.length = 2 * this.gauge.radius * this.gauge.options.radiusScale * this.options.length; + this.pointerEnd = this.options.pointerEnd || "butt"; this.strokeWidth = this.canvas.height * this.options.strokeWidth; this.maxValue = this.gauge.maxValue; this.minValue = this.gauge.minValue; @@ -349,15 +360,27 @@ startY = Math.round(this.strokeWidth * Math.sin(angle - Math.PI / 2)); endX = Math.round(this.strokeWidth * Math.cos(angle + Math.PI / 2)); endY = Math.round(this.strokeWidth * Math.sin(angle + Math.PI / 2)); - this.ctx.fillStyle = this.options.color; - this.ctx.beginPath(); - this.ctx.arc(0, 0, this.strokeWidth, 0, Math.PI * 2, true); - this.ctx.fill(); - this.ctx.beginPath(); - this.ctx.moveTo(startX, startY); - this.ctx.lineTo(x, y); - this.ctx.lineTo(endX, endY); - this.ctx.fill(); + if (!this.options.hideCentre) { + this.ctx.beginPath(); + this.ctx.fillStyle = this.options.color; + this.ctx.arc(0, 0, this.strokeWidth, 0, Math.PI * 2, false); + this.ctx.fill(); + } + if (this.options.pointerType === "triangle") { + this.ctx.beginPath(); + this.ctx.moveTo(startX, startY); + this.ctx.lineTo(x, y); + this.ctx.lineTo(endX, endY); + this.ctx.fill(); + } else { + this.ctx.beginPath(); + this.ctx.lineCap = this.pointerEnd; + this.ctx.strokeStyle = this.options.color; + this.ctx.lineWidth = this.strokeWidth; + this.ctx.moveTo(0, 0); + this.ctx.lineTo(x, y); + this.ctx.stroke(); + } if (this.img) { imgX = Math.round(this.img.width * this.options.iconScale); imgY = Math.round(this.img.height * this.options.iconScale); @@ -435,7 +458,11 @@ colorStop: void 0, gradientType: 0, strokeColor: "#e0e0e0", + labelHoriz: false, pointer: { + pointerType: "triangle", + pointerEnd: "butt", + hideCenter: false, length: 0.8, strokeWidth: 0.035, iconScale: 1.0 @@ -463,7 +490,6 @@ this.canvas.width = w; this.gp = [new GaugePointer(this)]; this.setOptions(); - this.render(); } Gauge.prototype.setOptions = function(options) { @@ -488,6 +514,7 @@ gauge.setOptions(this.options.pointer); gauge.render(); } + this.render(); return this; }; @@ -597,7 +624,7 @@ }; Gauge.prototype.renderStaticLabels = function(staticLabels, w, h, radius) { - var font, fontsize, j, len, match, re, ref, rest, rotationAngle, value; + var font, fontsize, j, labelHoriz, len, match, offset, re, ref, rest, rotationAngle, value; this.ctx.save(); this.ctx.translate(w, h); font = staticLabels.font || "10px Times"; @@ -605,6 +632,7 @@ match = font.match(re)[0]; rest = font.slice(match.length); fontsize = parseFloat(match) * this.displayScale; + labelHoriz = this.options.labelHoriz; this.ctx.font = fontsize + rest; this.ctx.fillStyle = staticLabels.color || "#000000"; this.ctx.textBaseline = "bottom"; @@ -612,20 +640,105 @@ ref = staticLabels.labels; for (j = 0, len = ref.length; j < len; j++) { value = ref[j]; - if ((!this.options.limitMin || value >= this.minValue) && (!this.options.limitMax || value <= this.maxValue)) { - rotationAngle = this.getAngle(value) - 3 * Math.PI / 2; - this.ctx.rotate(rotationAngle); - this.ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, -radius - this.lineWidth / 2); - this.ctx.rotate(-rotationAngle); + if (value.label !== void 0) { + if ((!this.options.limitMin || value >= this.minValue) && (!this.options.limitMax || value <= this.maxValue)) { + font = value.font || staticLabels.font; + match = font.match(re)[0]; + rest = font.slice(match.length); + fontsize = parseFloat(match) * this.displayScale; + this.ctx.font = fontsize + rest; + rotationAngle = this.getAngle(value.label) - 3 * Math.PI / 2; + this.ctx.rotate(rotationAngle); + if (labelHoriz === true) { + offset = (-radius - this.lineWidth / 2) * (1.01 + (fontsize / 100)) + (value.label.toString().length / 20); + console.log(offset, value.label, fontsize); + this.ctx.translate(0, offset); + this.ctx.rotate(-rotationAngle); + this.ctx.fillText(formatNumber(value.label, staticLabels.fractionDigits), 0, 0); + this.ctx.rotate(rotationAngle); + this.ctx.translate(0, -offset); + } else { + this.ctx.fillText(formatNumber(value.label, staticLabels.fractionDigits), 0, -radius - this.lineWidth / 2); + } + this.ctx.rotate(-rotationAngle); + } + } else { + if ((!this.options.limitMin || value >= this.minValue) && (!this.options.limitMax || value <= this.maxValue)) { + rotationAngle = this.getAngle(value) - 3 * Math.PI / 2; + this.ctx.rotate(rotationAngle); + if (labelHoriz === true) { + offset = (-radius - this.lineWidth / 2) * (1.01 + (fontsize / 100)) + (value.toString().length / 20); + this.ctx.translate(0, offset); + this.ctx.rotate(-rotationAngle); + this.ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, 0); + this.ctx.rotate(rotationAngle); + this.ctx.translate(0, -offset); + } else { + this.ctx.fillText(formatNumber(value, staticLabels.fractionDigits), 0, -radius - this.lineWidth / 2); + } + this.ctx.rotate(-rotationAngle); + } } } return this.ctx.restore(); }; + Gauge.prototype.renderTicks = function(ticksOptions, w, h, radius) { + var currentDivision, currentSubDivision, divColor, divLength, divWidth, divisionCount, j, lineWidth, range, rangeDivisions, ref, results, scaleMutate, st, subColor, subDivisions, subLength, subWidth, subdivisionCount, t, tmpRadius; + if (ticksOptions !== {}) { + divisionCount = ticksOptions.divisions || 0; + subdivisionCount = ticksOptions.subDivisions || 0; + divColor = ticksOptions.divColor || '#fff'; + subColor = ticksOptions.subColor || '#fff'; + divLength = ticksOptions.divLength || 0.7; + subLength = ticksOptions.subLength || 0.2; + range = parseFloat(this.maxValue) - parseFloat(this.minValue); + rangeDivisions = parseFloat(range) / parseFloat(ticksOptions.divisions); + subDivisions = parseFloat(rangeDivisions) / parseFloat(ticksOptions.subDivisions); + currentDivision = parseFloat(this.minValue); + currentSubDivision = 0.0 + subDivisions; + lineWidth = range / 400; + divWidth = lineWidth * (ticksOptions.divWidth || 1); + subWidth = lineWidth * (ticksOptions.subWidth || 1); + results = []; + for (t = j = 0, ref = divisionCount + 1; j < ref; t = j += 1) { + this.ctx.lineWidth = this.lineWidth * divLength; + scaleMutate = (this.lineWidth / 2) * (1 - divLength); + tmpRadius = (this.radius * this.options.radiusScale) + scaleMutate; + this.ctx.strokeStyle = divColor; + this.ctx.beginPath(); + this.ctx.arc(0, 0, tmpRadius, this.getAngle(currentDivision - divWidth), this.getAngle(currentDivision + divWidth), false); + this.ctx.stroke(); + currentSubDivision = currentDivision + subDivisions; + currentDivision += rangeDivisions; + if (t !== ticksOptions.divisions && subdivisionCount > 0) { + results.push((function() { + var k, ref1, results1; + results1 = []; + for (st = k = 0, ref1 = subdivisionCount - 1; k < ref1; st = k += 1) { + this.ctx.lineWidth = this.lineWidth * subLength; + scaleMutate = (this.lineWidth / 2) * (1 - subLength); + tmpRadius = (this.radius * this.options.radiusScale) + scaleMutate; + this.ctx.strokeStyle = subColor; + this.ctx.beginPath(); + this.ctx.arc(0, 0, tmpRadius, this.getAngle(currentSubDivision - subWidth), this.getAngle(currentSubDivision + subWidth), false); + this.ctx.stroke(); + results1.push(currentSubDivision += subDivisions); + } + return results1; + }).call(this)); + } else { + results.push(void 0); + } + } + return results; + } + }; + Gauge.prototype.render = function() { - var displayedAngle, fillStyle, gauge, h, j, k, len, len1, max, min, radius, ref, ref1, w, zone; + var displayedAngle, fillStyle, gauge, h, j, k, len, len1, max, min, radius, ref, ref1, scaleMutate, tmpRadius, w, zone; w = this.canvas.width / 2; - h = this.canvas.height * this.paddingTop + this.availableHeight - (this.radius + this.lineWidth / 2) * this.extraPadding; + h = (this.canvas.height * this.paddingTop + this.availableHeight) - ((this.radius + this.lineWidth / 2) * this.extraPadding); displayedAngle = this.getAngle(this.displayedValue); if (this.textField) { this.textField.render(this); @@ -650,12 +763,17 @@ if (this.options.limitMax && max > this.maxValue) { max = this.maxValue; } + tmpRadius = this.radius; + if (zone.height) { + this.ctx.lineWidth = this.lineWidth * zone.height; + scaleMutate = (this.lineWidth / 2) * (zone.offset || 1 - zone.height); + tmpRadius = (this.radius * this.options.radiusScale) + scaleMutate; + } this.ctx.strokeStyle = zone.strokeStyle; this.ctx.beginPath(); - this.ctx.arc(0, 0, radius, this.getAngle(min), this.getAngle(max), false); + this.ctx.arc(0, 0, tmpRadius, this.getAngle(min), this.getAngle(max), false); this.ctx.stroke(); } - this.ctx.restore(); } else { if (this.options.customFillStyle !== void 0) { fillStyle = this.options.customFillStyle(this); @@ -681,7 +799,13 @@ this.ctx.beginPath(); this.ctx.arc(w, h, radius, displayedAngle, (2 - this.options.angle) * Math.PI, false); this.ctx.stroke(); + this.ctx.save(); + this.ctx.translate(w, h); } + if (this.options.renderTicks) { + this.renderTicks(this.options.renderTicks, w, h, radius); + } + this.ctx.restore(); this.ctx.translate(w, h); ref1 = this.gp; for (k = 0, len1 = ref1.length; k < len1; k++) { @@ -891,5 +1015,3 @@ } }).call(this); - -//# sourceMappingURL=gauge.js.map diff --git a/dist/gauge.min.js b/dist/gauge.min.js index a291409..f0bedbf 100644 --- a/dist/gauge.min.js +++ b/dist/gauge.min.js @@ -1 +1 @@ -(function(){var t,i,e,s,n,o,a,h,r,l,p,c,u,d=[].slice,g={}.hasOwnProperty,m=function(t,i){function e(){this.constructor=t}for(var s in i)g.call(i,s)&&(t[s]=i[s]);return e.prototype=i.prototype,t.prototype=new e,t.__super__=i.prototype,t};!function(){var t,i,e,s,n,o,a;for(e=0,n=(a=["ms","moz","webkit","o"]).length;e1&&(n="."+e[1]),i=/(\d+)(\d{3})/;i.test(s);)s=s.replace(i,"$1,$2");return s+n},l=function(t){return"#"===t.charAt(0)?t.substring(1,7):t},e=function(t){function i(){return i.__super__.constructor.apply(this,arguments)}return m(i,t),i.prototype.displayScale=1,i.prototype.forceUpdate=!0,i.prototype.setTextField=function(t,i){return this.textField=t instanceof a?t:new a(t,i)},i.prototype.setMinValue=function(t,i){var e,s,n,o,a;if(this.minValue=t,null==i&&(i=!0),i){for(this.displayedValue=this.minValue,a=[],s=0,n=(o=this.gp||[]).length;s.5&&(this.options.angle=.5),this.configDisplayScale(),this},i.prototype.configDisplayScale=function(){var t,i,e,s,n;return s=this.displayScale,!1===this.options.highDpiSupport?delete this.displayScale:(i=window.devicePixelRatio||1,t=this.ctx.webkitBackingStorePixelRatio||this.ctx.mozBackingStorePixelRatio||this.ctx.msBackingStorePixelRatio||this.ctx.oBackingStorePixelRatio||this.ctx.backingStorePixelRatio||1,this.displayScale=i/t),this.displayScale!==s&&(n=this.canvas.G__width||this.canvas.width,e=this.canvas.G__height||this.canvas.height,this.canvas.width=n*this.displayScale,this.canvas.height=e*this.displayScale,this.canvas.style.width=n+"px",this.canvas.style.height=e+"px",this.canvas.G__width=n,this.canvas.G__height=e),this},i.prototype.parseValue=function(t){return t=parseFloat(t)||Number(t),isFinite(t)?t:0},i}(h=function(){function t(t,i){null==t&&(t=!0),this.clear=null==i||i,t&&AnimationUpdater.add(this)}return t.prototype.animationSpeed=32,t.prototype.update=function(t){var i;return null==t&&(t=!1),!(!t&&this.displayedValue===this.value)&&(this.ctx&&this.clear&&this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),i=this.value-this.displayedValue,Math.abs(i/this.animationSpeed)<=.001?this.displayedValue=this.value:this.displayedValue=this.displayedValue+i/this.animationSpeed,this.render(),!0)},t}()),a=function(){function t(t,i){this.el=t,this.fractionDigits=i}return t.prototype.render=function(t){return this.el.innerHTML=p(t.displayedValue,this.fractionDigits)},t}(),t=function(t){function i(t,i){this.elem=t,this.text=null!=i&&i,this.value=1*this.elem.innerHTML,this.text&&(this.value=0)}return m(i,t),i.prototype.displayedValue=0,i.prototype.value=0,i.prototype.setVal=function(t){return this.value=1*t},i.prototype.render=function(){var t;return t=this.text?u(this.displayedValue.toFixed(0)):r(p(this.displayedValue)),this.elem.innerHTML=t},i}(h),o=function(t){function i(t){this.gauge=t,this.ctx=this.gauge.ctx,this.canvas=this.gauge.canvas,i.__super__.constructor.call(this,!1,!1),this.setOptions()}return m(i,t),i.prototype.displayedValue=0,i.prototype.value=0,i.prototype.options={strokeWidth:.035,length:.1,color:"#000000",iconPath:null,iconScale:1,iconAngle:0},i.prototype.img=null,i.prototype.setOptions=function(t){if(null==t&&(t=null),this.options=c(this.options,t),this.length=2*this.gauge.radius*this.gauge.options.radiusScale*this.options.length,this.strokeWidth=this.canvas.height*this.options.strokeWidth,this.maxValue=this.gauge.maxValue,this.minValue=this.gauge.minValue,this.animationSpeed=this.gauge.animationSpeed,this.options.angle=this.gauge.options.angle,this.options.iconPath)return this.img=new Image,this.img.src=this.options.iconPath},i.prototype.render=function(){var t,i,e,s,n,o,a,h,r;if(t=this.gauge.getAngle.call(this,this.displayedValue),h=Math.round(this.length*Math.cos(t)),r=Math.round(this.length*Math.sin(t)),o=Math.round(this.strokeWidth*Math.cos(t-Math.PI/2)),a=Math.round(this.strokeWidth*Math.sin(t-Math.PI/2)),i=Math.round(this.strokeWidth*Math.cos(t+Math.PI/2)),e=Math.round(this.strokeWidth*Math.sin(t+Math.PI/2)),this.ctx.fillStyle=this.options.color,this.ctx.beginPath(),this.ctx.arc(0,0,this.strokeWidth,0,2*Math.PI,!0),this.ctx.fill(),this.ctx.beginPath(),this.ctx.moveTo(o,a),this.ctx.lineTo(h,r),this.ctx.lineTo(i,e),this.ctx.fill(),this.img)return s=Math.round(this.img.width*this.options.iconScale),n=Math.round(this.img.height*this.options.iconScale),this.ctx.save(),this.ctx.translate(h,r),this.ctx.rotate(t+Math.PI/180*(90+this.options.iconAngle)),this.ctx.drawImage(this.img,-s/2,-n/2,s,n),this.ctx.restore()},i}(h),function(){function t(t){this.elem=t}t.prototype.updateValues=function(t){return this.value=t[0],this.maxValue=t[1],this.avgValue=t[2],this.render()},t.prototype.render=function(){var t,i;return this.textField&&this.textField.text(p(this.value)),0===this.maxValue&&(this.maxValue=2*this.avgValue),i=this.value/this.maxValue*100,t=this.avgValue/this.maxValue*100,$(".bar-value",this.elem).css({width:i+"%"}),$(".typical-value",this.elem).css({width:t+"%"})}}(),n=function(t){function i(t){var e,s;this.canvas=t,i.__super__.constructor.call(this),this.percentColors=null,"undefined"!=typeof G_vmlCanvasManager&&(this.canvas=window.G_vmlCanvasManager.initElement(this.canvas)),this.ctx=this.canvas.getContext("2d"),e=this.canvas.clientHeight,s=this.canvas.clientWidth,this.canvas.height=e,this.canvas.width=s,this.gp=[new o(this)],this.setOptions(),this.render()}return m(i,t),i.prototype.elem=null,i.prototype.value=[20],i.prototype.maxValue=80,i.prototype.minValue=0,i.prototype.displayedAngle=0,i.prototype.displayedValue=0,i.prototype.lineWidth=40,i.prototype.paddingTop=.1,i.prototype.paddingBottom=.1,i.prototype.percentColors=null,i.prototype.options={colorStart:"#6fadcf",colorStop:void 0,gradientType:0,strokeColor:"#e0e0e0",pointer:{length:.8,strokeWidth:.035,iconScale:1},angle:.15,lineWidth:.44,radiusScale:1,fontSize:40,limitMax:!1,limitMin:!1},i.prototype.setOptions=function(t){var e,s,n,o,a;for(null==t&&(t=null),i.__super__.setOptions.call(this,t),this.configPercentColors(),this.extraPadding=0,this.options.angle<0&&(o=Math.PI*(1+this.options.angle),this.extraPadding=Math.sin(o)),this.availableHeight=this.canvas.height*(1-this.paddingTop-this.paddingBottom),this.lineWidth=this.availableHeight*this.options.lineWidth,this.radius=(this.availableHeight-this.lineWidth/2)/(1+this.extraPadding),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),s=0,n=(a=this.gp).length;s=n;e=0<=n?++s:--s)a=parseInt(l(this.options.percentColors[e][1]).substring(0,2),16),i=parseInt(l(this.options.percentColors[e][1]).substring(2,4),16),t=parseInt(l(this.options.percentColors[e][1]).substring(4,6),16),o.push(this.percentColors[e]={pct:this.options.percentColors[e][0],color:{r:a,g:i,b:t}});return o}},i.prototype.set=function(t){var i,e,s,n,a,h,r,l,p;for(t instanceof Array||(t=[t]),e=s=0,r=t.length-1;0<=r?s<=r:s>=r;e=0<=r?++s:--s)t[e]=this.parseValue(t[e]);if(t.length>this.gp.length)for(e=n=0,l=t.length-this.gp.length;0<=l?nl;e=0<=l?++n:--n)(i=new o(this)).setOptions(this.options.pointer),this.gp.push(i);else t.lengththis.maxValue?this.options.limitMax?p=this.maxValue:this.maxValue=p+1:p=h;n=0<=h?++o:--o)if(t<=this.percentColors[n].pct){!0===i?(r=this.percentColors[n-1]||this.percentColors[0],s=this.percentColors[n],a=(t-r.pct)/(s.pct-r.pct),e={r:Math.floor(r.color.r*(1-a)+s.color.r*a),g:Math.floor(r.color.g*(1-a)+s.color.g*a),b:Math.floor(r.color.b*(1-a)+s.color.b*a)}):e=this.percentColors[n].color;break}return"rgb("+[e.r,e.g,e.b].join(",")+")"},i.prototype.getColorForValue=function(t,i){var e;return e=(t-this.minValue)/(this.maxValue-this.minValue),this.getColorForPercentage(e,i)},i.prototype.renderStaticLabels=function(t,i,e,s){var n,o,a,h,r,l,c,u,d,g;for(this.ctx.save(),this.ctx.translate(i,e),l=/\d+\.?\d?/,r=(n=t.font||"10px Times").match(l)[0],u=n.slice(r.length),o=parseFloat(r)*this.displayScale,this.ctx.font=o+u,this.ctx.fillStyle=t.color||"#000000",this.ctx.textBaseline="bottom",this.ctx.textAlign="center",a=0,h=(c=t.labels).length;a=this.minValue)&&(!this.options.limitMax||g<=this.maxValue)&&(d=this.getAngle(g)-3*Math.PI/2,this.ctx.rotate(d),this.ctx.fillText(p(g,t.fractionDigits),0,-s-this.lineWidth/2),this.ctx.rotate(-d));return this.ctx.restore()},i.prototype.render=function(){var t,i,e,s,n,o,a,h,r,l,p,c,u,d;if(u=this.canvas.width/2,e=this.canvas.height*this.paddingTop+this.availableHeight-(this.radius+this.lineWidth/2)*this.extraPadding,t=this.getAngle(this.displayedValue),this.textField&&this.textField.render(this),this.ctx.lineCap="butt",l=this.radius*this.options.radiusScale,this.options.staticLabels&&this.renderStaticLabels(this.options.staticLabels,u,e,l),this.options.staticZones){for(this.ctx.save(),this.ctx.translate(u,e),this.ctx.lineWidth=this.lineWidth,s=0,o=(p=this.options.staticZones).length;sthis.maxValue&&(h=this.maxValue),this.ctx.strokeStyle=d.strokeStyle,this.ctx.beginPath(),this.ctx.arc(0,0,l,this.getAngle(r),this.getAngle(h),!1),this.ctx.stroke();this.ctx.restore()}else void 0!==this.options.customFillStyle?i=this.options.customFillStyle(this):null!==this.percentColors?i=this.getColorForValue(this.displayedValue,this.options.generateGradient):void 0!==this.options.colorStop?((i=0===this.options.gradientType?this.ctx.createRadialGradient(u,e,9,u,e,70):this.ctx.createLinearGradient(0,0,u,0)).addColorStop(0,this.options.colorStart),i.addColorStop(1,this.options.colorStop)):i=this.options.colorStart,this.ctx.strokeStyle=i,this.ctx.beginPath(),this.ctx.arc(u,e,l,(1+this.options.angle)*Math.PI,t,!1),this.ctx.lineWidth=this.lineWidth,this.ctx.stroke(),this.ctx.strokeStyle=this.options.strokeColor,this.ctx.beginPath(),this.ctx.arc(u,e,l,t,(2-this.options.angle)*Math.PI,!1),this.ctx.stroke();for(this.ctx.translate(u,e),n=0,a=(c=this.gp).length;nthis.maxValue?this.options.limitMax?this.value=this.maxValue:this.maxValue=this.value:this.value1&&(n="."+e[1]),i=/(\d+)(\d{3})/;i.test(s);)s=s.replace(i,"$1,$2");return s+n},l=function(t){return"#"===t.charAt(0)?t.substring(1,7):t},h=function(){function t(t,i){null==t&&(t=!0),this.clear=null==i||i,t&&AnimationUpdater.add(this)}return t.prototype.animationSpeed=32,t.prototype.update=function(t){var i;return null==t&&(t=!1),!(!t&&this.displayedValue===this.value)&&(this.ctx&&this.clear&&this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),i=this.value-this.displayedValue,Math.abs(i/this.animationSpeed)<=.001?this.displayedValue=this.value:this.displayedValue=this.displayedValue+i/this.animationSpeed,this.render(),!0)},t}(),e=function(t){function i(){return i.__super__.constructor.apply(this,arguments)}return x(i,t),i.prototype.displayScale=1,i.prototype.forceUpdate=!0,i.prototype.setTextField=function(t,i){return this.textField=t instanceof a?t:new a(t,i)},i.prototype.setMinValue=function(t,i){var e,s,n,o,a;if(this.minValue=t,null==i&&(i=!0),i){for(this.displayedValue=this.minValue,o=this.gp||[],a=[],s=0,n=o.length;s.5&&(this.options.angle=.5),this.configDisplayScale(),this},i.prototype.configDisplayScale=function(){var t,i,e,s,n;return s=this.displayScale,!1===this.options.highDpiSupport?delete this.displayScale:(i=window.devicePixelRatio||1,t=this.ctx.webkitBackingStorePixelRatio||this.ctx.mozBackingStorePixelRatio||this.ctx.msBackingStorePixelRatio||this.ctx.oBackingStorePixelRatio||this.ctx.backingStorePixelRatio||1,this.displayScale=i/t),this.displayScale!==s&&(n=this.canvas.G__width||this.canvas.width,e=this.canvas.G__height||this.canvas.height,this.canvas.width=n*this.displayScale,this.canvas.height=e*this.displayScale,this.canvas.style.width=n+"px",this.canvas.style.height=e+"px",this.canvas.G__width=n,this.canvas.G__height=e),this},i.prototype.parseValue=function(t){return t=parseFloat(t)||Number(t),isFinite(t)?t:0},i}(h),a=function(){function t(t,i){this.el=t,this.fractionDigits=i}return t.prototype.render=function(t){return this.el.innerHTML=p(t.displayedValue,this.fractionDigits)},t}(),t=function(t){function i(t,e){if(this.elem=t,this.text=null!=e&&e,i.__super__.constructor.call(this),void 0===this.elem)throw new Error("The element isn't defined.");this.value=1*this.elem.innerHTML,this.text&&(this.value=0)}return x(i,t),i.prototype.displayedValue=0,i.prototype.value=0,i.prototype.setVal=function(t){return this.value=1*t},i.prototype.render=function(){var t;return t=this.text?u(this.displayedValue.toFixed(0)):r(p(this.displayedValue)),this.elem.innerHTML=t},i}(h),o=function(t){function i(t){if(this.gauge=t,void 0===this.gauge)throw new Error("The element isn't defined.");this.ctx=this.gauge.ctx,this.canvas=this.gauge.canvas,i.__super__.constructor.call(this,!1,!1),this.setOptions()}return x(i,t),i.prototype.displayedValue=0,i.prototype.value=0,i.prototype.options={pointerType:"triangle",pointerEnd:"butt",hideCentre:!1,strokeWidth:.035,length:.1,color:"#000000",iconPath:null,iconScale:1,iconAngle:0},i.prototype.img=null,i.prototype.setOptions=function(t){if(null==t&&(t=null),this.options=c(this.options,t),this.length=2*this.gauge.radius*this.gauge.options.radiusScale*this.options.length,this.pointerEnd=this.options.pointerEnd||"butt",this.strokeWidth=this.canvas.height*this.options.strokeWidth,this.maxValue=this.gauge.maxValue,this.minValue=this.gauge.minValue,this.animationSpeed=this.gauge.animationSpeed,this.options.angle=this.gauge.options.angle,this.options.iconPath)return this.img=new Image,this.img.src=this.options.iconPath},i.prototype.render=function(){var t,i,e,s,n,o,a,h,r;if(t=this.gauge.getAngle.call(this,this.displayedValue),h=Math.round(this.length*Math.cos(t)),r=Math.round(this.length*Math.sin(t)),o=Math.round(this.strokeWidth*Math.cos(t-Math.PI/2)),a=Math.round(this.strokeWidth*Math.sin(t-Math.PI/2)),i=Math.round(this.strokeWidth*Math.cos(t+Math.PI/2)),e=Math.round(this.strokeWidth*Math.sin(t+Math.PI/2)),this.options.hideCentre||(this.ctx.beginPath(),this.ctx.fillStyle=this.options.color,this.ctx.arc(0,0,this.strokeWidth,0,2*Math.PI,!1),this.ctx.fill()),"triangle"===this.options.pointerType?(this.ctx.beginPath(),this.ctx.moveTo(o,a),this.ctx.lineTo(h,r),this.ctx.lineTo(i,e),this.ctx.fill()):(this.ctx.beginPath(),this.ctx.lineCap=this.pointerEnd,this.ctx.strokeStyle=this.options.color,this.ctx.lineWidth=this.strokeWidth,this.ctx.moveTo(0,0),this.ctx.lineTo(h,r),this.ctx.stroke()),this.img)return s=Math.round(this.img.width*this.options.iconScale),n=Math.round(this.img.height*this.options.iconScale),this.ctx.save(),this.ctx.translate(h,r),this.ctx.rotate(t+Math.PI/180*(90+this.options.iconAngle)),this.ctx.drawImage(this.img,-s/2,-n/2,s,n),this.ctx.restore()},i}(h),function(){function t(t){this.elem=t}t.prototype.updateValues=function(t){return this.value=t[0],this.maxValue=t[1],this.avgValue=t[2],this.render()},t.prototype.render=function(){var t,i;return this.textField&&this.textField.text(p(this.value)),0===this.maxValue&&(this.maxValue=2*this.avgValue),i=this.value/this.maxValue*100,t=this.avgValue/this.maxValue*100,$(".bar-value",this.elem).css({width:i+"%"}),$(".typical-value",this.elem).css({width:t+"%"})}}(),n=function(t){function i(t){var e,s;this.canvas=t,i.__super__.constructor.call(this),this.percentColors=null,"undefined"!=typeof G_vmlCanvasManager&&(this.canvas=window.G_vmlCanvasManager.initElement(this.canvas)),this.ctx=this.canvas.getContext("2d"),e=this.canvas.clientHeight,s=this.canvas.clientWidth,this.canvas.height=e,this.canvas.width=s,this.gp=[new o(this)],this.setOptions()}return x(i,t),i.prototype.elem=null,i.prototype.value=[20],i.prototype.maxValue=80,i.prototype.minValue=0,i.prototype.displayedAngle=0,i.prototype.displayedValue=0,i.prototype.lineWidth=40,i.prototype.paddingTop=.1,i.prototype.paddingBottom=.1,i.prototype.percentColors=null,i.prototype.options={colorStart:"#6fadcf",colorStop:void 0,gradientType:0,strokeColor:"#e0e0e0",labelHoriz:!1,pointer:{pointerType:"triangle",pointerEnd:"butt",hideCenter:!1,length:.8,strokeWidth:.035,iconScale:1},angle:.15,lineWidth:.44,radiusScale:1,fontSize:40,limitMax:!1,limitMin:!1},i.prototype.setOptions=function(t){var e,s,n,o,a;for(null==t&&(t=null),i.__super__.setOptions.call(this,t),this.configPercentColors(),this.extraPadding=0,this.options.angle<0&&(o=Math.PI*(1+this.options.angle),this.extraPadding=Math.sin(o)),this.availableHeight=this.canvas.height*(1-this.paddingTop-this.paddingBottom),this.lineWidth=this.availableHeight*this.options.lineWidth,this.radius=(this.availableHeight-this.lineWidth/2)/(1+this.extraPadding),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),a=this.gp,s=0,n=a.length;s=n;e=0<=n?++s:--s)a=parseInt(l(this.options.percentColors[e][1]).substring(0,2),16),i=parseInt(l(this.options.percentColors[e][1]).substring(2,4),16),t=parseInt(l(this.options.percentColors[e][1]).substring(4,6),16),o.push(this.percentColors[e]={pct:this.options.percentColors[e][0],color:{r:a,g:i,b:t}});return o}},i.prototype.set=function(t){var i,e,s,n,a,h,r,l,p;for(t instanceof Array||(t=[t]),e=s=0,r=t.length-1;0<=r?s<=r:s>=r;e=0<=r?++s:--s)t[e]=this.parseValue(t[e]);if(t.length>this.gp.length)for(e=n=0,l=t.length-this.gp.length;0<=l?nl;e=0<=l?++n:--n)i=new o(this),i.setOptions(this.options.pointer),this.gp.push(i);else t.lengththis.maxValue?this.options.limitMax?p=this.maxValue:this.maxValue=p+1:p=h;n=0<=h?++o:--o)if(t<=this.percentColors[n].pct){!0===i?(r=this.percentColors[n-1]||this.percentColors[0],s=this.percentColors[n],a=(t-r.pct)/(s.pct-r.pct),e={r:Math.floor(r.color.r*(1-a)+s.color.r*a),g:Math.floor(r.color.g*(1-a)+s.color.g*a),b:Math.floor(r.color.b*(1-a)+s.color.b*a)}):e=this.percentColors[n].color;break}return"rgb("+[e.r,e.g,e.b].join(",")+")"},i.prototype.getColorForValue=function(t,i){var e;return e=(t-this.minValue)/(this.maxValue-this.minValue),this.getColorForPercentage(e,i)},i.prototype.renderStaticLabels=function(t,i,e,s){var n,o,a,h,r,l,c,u,d,g,x,m;for(this.ctx.save(),this.ctx.translate(i,e),n=t.font||"10px Times",u=/\d+\.?\d?/,l=n.match(u)[0],g=n.slice(l.length),o=parseFloat(l)*this.displayScale,h=this.options.labelHoriz,this.ctx.font=o+g,this.ctx.fillStyle=t.color||"#000000",this.ctx.textBaseline="bottom",this.ctx.textAlign="center",d=t.labels,a=0,r=d.length;a=this.minValue)&&(!this.options.limitMax||m<=this.maxValue)&&(n=m.font||t.font,l=n.match(u)[0],g=n.slice(l.length),o=parseFloat(l)*this.displayScale,this.ctx.font=o+g,x=this.getAngle(m.label)-3*Math.PI/2,this.ctx.rotate(x),!0===h?(c=(-s-this.lineWidth/2)*(1.01+o/100)+m.label.toString().length/20,console.log(c,m.label,o),this.ctx.translate(0,c),this.ctx.rotate(-x),this.ctx.fillText(p(m.label,t.fractionDigits),0,0),this.ctx.rotate(x),this.ctx.translate(0,-c)):this.ctx.fillText(p(m.label,t.fractionDigits),0,-s-this.lineWidth/2),this.ctx.rotate(-x)):(!this.options.limitMin||m>=this.minValue)&&(!this.options.limitMax||m<=this.maxValue)&&(x=this.getAngle(m)-3*Math.PI/2,this.ctx.rotate(x),!0===h?(c=(-s-this.lineWidth/2)*(1.01+o/100)+m.toString().length/20,this.ctx.translate(0,c),this.ctx.rotate(-x),this.ctx.fillText(p(m,t.fractionDigits),0,0),this.ctx.rotate(x),this.ctx.translate(0,-c)):this.ctx.fillText(p(m,t.fractionDigits),0,-s-this.lineWidth/2),this.ctx.rotate(-x));return this.ctx.restore()},i.prototype.renderTicks=function(t,i,e,s){var n,o,a,h,r,l,p,c,u,d,g,x,m,f,v,y,V,w,S,C,M;if(t!=={}){for(l=t.divisions||0,S=t.subDivisions||0,a=t.divColor||"#fff",v=t.subColor||"#fff",h=t.divLength||.7,V=t.subLength||.2,u=parseFloat(this.maxValue)-parseFloat(this.minValue),d=parseFloat(u)/parseFloat(t.divisions),y=parseFloat(d)/parseFloat(t.subDivisions),n=parseFloat(this.minValue),o=0+y,c=u/400,r=c*(t.divWidth||1),w=c*(t.subWidth||1),x=[],C=p=0,g=l+1;p0?x.push(function(){var t,i,e;for(e=[],f=t=0,i=S-1;tthis.maxValue&&(r=this.maxValue),g=this.radius,m.height&&(this.ctx.lineWidth=this.lineWidth*m.height,d=this.lineWidth/2*(m.offset||1-m.height),g=this.radius*this.options.radiusScale+d),this.ctx.strokeStyle=m.strokeStyle,this.ctx.beginPath(),this.ctx.arc(0,0,g,this.getAngle(l),this.getAngle(r),!1),this.ctx.stroke();else void 0!==this.options.customFillStyle?i=this.options.customFillStyle(this):null!==this.percentColors?i=this.getColorForValue(this.displayedValue,this.options.generateGradient):void 0!==this.options.colorStop?(i=0===this.options.gradientType?this.ctx.createRadialGradient(x,s,9,x,s,70):this.ctx.createLinearGradient(0,0,x,0),i.addColorStop(0,this.options.colorStart),i.addColorStop(1,this.options.colorStop)):i=this.options.colorStart,this.ctx.strokeStyle=i,this.ctx.beginPath(),this.ctx.arc(x,s,p,(1+this.options.angle)*Math.PI,t,!1),this.ctx.lineWidth=this.lineWidth,this.ctx.stroke(),this.ctx.strokeStyle=this.options.strokeColor,this.ctx.beginPath(),this.ctx.arc(x,s,p,t,(2-this.options.angle)*Math.PI,!1),this.ctx.stroke(),this.ctx.save(),this.ctx.translate(x,s);for(this.options.renderTicks&&this.renderTicks(this.options.renderTicks,x,s,p),this.ctx.restore(),this.ctx.translate(x,s),u=this.gp,o=0,h=u.length;othis.maxValue?this.options.limitMax?this.value=this.maxValue:this.maxValue=this.value:this.valueVariant selection
  • -
  • +
  • +
- -
+ +
+
+

Options:

-
+




-
+



@@ -67,6 +70,28 @@

Options:




+ +
+
+ + + + +
+
+ +
+ +

@@ -93,8 +118,12 @@

Usage

angle: 7, // The span of the gauge arc lineWidth: 5, // The line thickness radiusScale: 1.0, // Relative radius + labelHoriz: true, // Show Horizontal labels with arc pointer: { - length: 10, // // Relative to gauge radius + pointerType: 'triangle', // triangle / line + pointerEnd: 'butt', // butt / round / square + hideCentre: false, // show/hide pointer center circle + length: 10, // Relative to gauge radius strokeWidth: 0, // The thickness color: '#000000' // Fill color }, @@ -104,7 +133,19 @@

Usage

colorStop: '0', // just experiment with them strokeColor: '0', // to see which ones work best for you generateGradient: true, - highDpiSupport: true // High resolution support + highDpiSupport: true, // High resolution support + }; var target = document.getElementById('foo'); // your canvas element var gauge = new Gauge(target).setOptions(opts); // create sexy gauge! @@ -137,6 +178,7 @@

Advanced options

color: "#000000", // Optional: Label text color fractionDigits: 0 // Optional: Numerical precision. 0=round off. }, +
  • @@ -151,8 +193,51 @@

    Advanced options

    {strokeStyle: "#F03E3E", min: 260, max: 300} // Red ], -

    staticZones, percentColors and gradient are mutually exclusive. If staticZones is defined, it will take precedence.

    -

    Note: Zones should always be defined within the gauge objects .minValue and .maxValue limits.

    +

    staticZones, percentColors and gradient are mutually exclusive. If staticZones is defined, it will take precedence.

    +

    Note: Zones should always be defined within the gauge objects .minValue and .maxValue limits.

    +
  • +
  • +

    Additionally, a height parameter may be passed in to increase the size of the zone (see example 4 gauge above).

    +
    +  staticZones: [
    +    {strokeStyle: "rgb(255,0,0)", min: 0, max: 500, height: 1.4},
    +    {strokeStyle: "rgb(200,100,0)", min: 500, max: 1000, height: 1.2},
    +    {strokeStyle: "rgb(150,150,0)", min: 1000, max: 1500, height: 1},
    +    {strokeStyle: "rgb(100,200,0)", min: 1500, max: 2000, height: 0.8},
    +    {strokeStyle: "rgb(0,255,0)", min: 2000, max: 3100, height: 0.6}
    +  ],
    +  
    +

    Note: +

    {strokeStyle: "rgb(80,80,80)", min: 2470, max: 2530, height: 1.3}
    + You can use this as an additional indicator (like in example 4) by making its color stand out, having a tall height and narrow range.

    +
  • +
  • + Tick marks +

    Now you may also add Ticks on two levels, major and minor (or divisions and sub divisions).

    + renderTicks options: +
      +
    • divisions This is the number of major divisions around your arc.
    • +
    • divWidth This is to set the width of the indicator.
    • +
    • divLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
    • +
    • divColor This sets the color of the division markers
    • +
    • subDivisions This sets the minor tick marks count between major ticks.
    • +
    • subLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
    • +
    • subWidth This is to set the width of the indicator.
    • +
    • subColor This sets the color of the subdivision markers
    • +
    +

    Example:

    +
    +        renderTicks: {
    +          divisions: 5,
    +          divWidth: 1.1,
    +          divLength: 0.7,
    +          divColor: #333333,
    +          subDivisions: 3,
    +          subLength: 0.5,
    +          subWidth: 0.6,
    +          subColor: #666666
    +        }
    +    
  • Gauge pointer tip icon @@ -203,84 +288,93 @@

    Supported browsers

  • Android 2.3+
  • +
    +

    Changes

    -

    Changes

    - -

    Version 1.3.5 (08.07.2017)

    +

    Version 1.3.6 (28.11.2017)

    -

      -
    • Fixed issue #139: Donut support for limitMin and -Max. -
    +
      +
    • Added support for scalable staticzone sections
    • +
    • Added optional Ticks(Major/Minor)
    • +

    -

    Version 1.3.4 (13.05.2017)

    -

    -

      -
    • New feature: Add icon to tip of gauge pointer PR #133 -
    • Fixed issue #17 for Donut. -
    -

    +

    Version 1.3.5 (08.07.2017)

    +

    +

      +
    • Fixed issue #139: Donut support for limitMin and -Max. +
    +

    -

    Version 1.3.3 (09.04.2017)

    -

    - Improved protection for non-numerical inputs to .set(), which could cause problems like #124. -

    +

    Version 1.3.4 (13.05.2017)

    +

    +

      +
    • New feature: Add icon to tip of gauge pointer PR #133 +
    • Fixed issue #17 for Donut. +
    +

    -

    Version 1.3.2 (11.02.2017)

    -

    - Bug-fixes (#116 and #117), performance improvements. -

    +

    Version 1.3.3 (09.04.2017)

    +

    + Improved protection for non-numerical inputs to .set(), which could cause problems like #124. +

    -

    Version 1.3.1 (05.02.2017)

    - Highlights: -
      -
    • Added option 'minLimit' and improved max/min-hit value a lot (issue #84).
    • -
    • Fixed multiple pointers color problem, issue #26 and #72.
    • -
    • Added ability to scale the gauge radius to deal with issue #112.
    • -
    -

    - A couple of other bugs and issues sorted out as well. -

    +

    Version 1.3.2 (11.02.2017)

    +

    + Bug-fixes (#116 and #117), performance improvements. +

    -

    Version 1.3 (07.01.2017)

    -

    - This version is a mix of new functionality and various smaller fixes and improvements. Some of the inner transformations - and options definition have been slightly altered/improved and made more consistent. -

    - Highlights: -
      -
    • New feature: Value lables above the dial.
    • -
    • New feature: Static color setting of the dial issue #81. Based on rsreimer's work.
    • -
    • Gauge dial can be more than 180 degress. Negative options.angle allowed. (New feature)
    • -
    • Better scaling in parent canvas. (Improvement)
    • -
    • Set numerical precision for value fiels (Improvement)
    • -
    +

    Version 1.3.1 (05.02.2017)

    + Highlights: +
      +
    • Added option 'minLimit' and improved max/min-hit value a lot (issue #84).
    • +
    • Fixed multiple pointers color problem, issue #26 and #72.
    • +
    • Added ability to scale the gauge radius to deal with issue #112.
    • +
    +

    + A couple of other bugs and issues sorted out as well. +

    + +

    Version 1.3 (07.01.2017)

    +

    + This version is a mix of new functionality and various smaller fixes and improvements. Some of the inner transformations + and options definition have been slightly altered/improved and made more consistent. +

    + Highlights: +
      +
    • New feature: Value lables above the dial.
    • +
    • New feature: Static color setting of the dial issue #81. Based on rsreimer's work.
    • +
    • Gauge dial can be more than 180 degress. Negative options.angle allowed. (New feature)
    • +
    • Better scaling in parent canvas. (Improvement)
    • +
    • Set numerical precision for value fiels (Improvement)
    • +
    -

    Version 1.2.1 (9.03.2014)

    -
      -
    • Proper handling of color params issue #47.
    • -
    • Moved percentage color to example/docs + JSFiddle
    • -
    +

    Version 1.2.1 (9.03.2014)

    +
      +
    • Proper handling of color params issue #47.
    • +
    • Moved percentage color to example/docs + JSFiddle
    • +
    -

    Version 1.2 (16.08.2012)

    -
      -
    • Prototype chain fix. See issue #7.
    • -
    • Refactored code a bit to make it more flexible. Default class that has some extra features like gradient shadows is called Donut while more flexible one (for devs) is called BaseDonut - use it if you would don't need extra automatic stuff.
    • -
    • Ability to scale gauges (requested via email) - example at JSFiddle
    • -
    +

    Version 1.2 (16.08.2012)

    +
      +
    • Prototype chain fix. See issue #7.
    • +
    • Refactored code a bit to make it more flexible. Default class that has some extra features like gradient shadows is called Donut while more flexible one (for devs) is called BaseDonut - use it if you would don't need extra automatic stuff.
    • +
    • Ability to scale gauges (requested via email) - example at JSFiddle
    • +
    -

    Version 1.1 (15.08.2012)

    -
      -
    • Fixed color picker bug in FF & Opera
    • -
    • Added a shadow option. See issue #5.
    • -
    • Added multiple pointer option (requested via email). This needed some code refactoring. No demo for it yet. Use array of values to check it ex. gauge.set([44, 554]);
    • -
    • Added wrapper for formatting text output issue #4.
    • -
    +

    Version 1.1 (15.08.2012)

    +
      +
    • Fixed color picker bug in FF & Opera
    • +
    • Added a shadow option. See issue #5.
    • +
    • Added multiple pointer option (requested via email). This needed some code refactoring. No demo for it yet. Use array of values to check it ex. gauge.set([44, 554]);
    • +
    • Added wrapper for formatting text output issue #4.
    • +
    -

    Version 1.0 (27.6.2012)

    -
      -
    • Initial release
    • -
    +

    Version 1.0 (27.6.2012)

    +
      +
    • Initial release
    • +
    +

    Contact

    @@ -296,11 +390,80 @@

    Contact

    -