|
|
@ -44,6 +44,7 @@ function Graph3d(container, data, options) { |
|
|
|
|
|
|
|
this.filterLabel = 'time'; |
|
|
|
this.legendLabel = 'value'; |
|
|
|
this.showLegend = undefined; // auto by default (based on graph style)
|
|
|
|
|
|
|
|
this.style = Graph3d.STYLE.DOT; |
|
|
|
this.showPerspective = true; |
|
|
@ -494,7 +495,11 @@ Graph3d.prototype._dataInitialize = function (rawData, style) { |
|
|
|
this.valueMax = (this.defaultValueMax !== undefined) ? this.defaultValueMax : valueRange.max; |
|
|
|
if (this.valueMax <= this.valueMin) this.valueMax = this.valueMin + 1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// these styles default to having legends
|
|
|
|
var isLegendGraphStyle = this.style === Graph3d.STYLE.DOTCOLOR || this.style === Graph3d.STYLE.DOTSIZE; |
|
|
|
this.showLegend = (this.defaultShowLegend !== undefined) ? this.defaultShowLegend : isLegendGraphStyle; |
|
|
|
|
|
|
|
// set the scale dependent on the ranges.
|
|
|
|
this._setScale(); |
|
|
|
}; |
|
|
@ -838,6 +843,7 @@ Graph3d.prototype.setOptions = function (options) { |
|
|
|
|
|
|
|
if (options.filterLabel !== undefined) this.filterLabel = options.filterLabel; |
|
|
|
if (options.legendLabel !== undefined) this.legendLabel = options.legendLabel; |
|
|
|
if (options.showLegend !== undefined) this.defaultShowLegend = options.showLegend; |
|
|
|
if (options.xLabel !== undefined) this.xLabel = options.xLabel; |
|
|
|
if (options.yLabel !== undefined) this.yLabel = options.yLabel; |
|
|
|
if (options.zLabel !== undefined) this.zLabel = options.zLabel; |
|
|
@ -972,46 +978,64 @@ Graph3d.prototype._redrawClear = function() { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Redraw the legend showing the colors |
|
|
|
* Get legend width |
|
|
|
*/ |
|
|
|
Graph3d.prototype._redrawLegend = function() { |
|
|
|
var y; |
|
|
|
|
|
|
|
if (this.style === Graph3d.STYLE.DOTCOLOR || |
|
|
|
this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
|
|
|
|
Graph3d.prototype._getLegendWidth = function() { |
|
|
|
var width; |
|
|
|
if (this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
var dotSize = this.frame.clientWidth * this.dotSizeRatio; |
|
|
|
width = dotSize / 2 + dotSize * 2; |
|
|
|
} else if (this.style === Graph3d.STYLE.BARSIZE) { |
|
|
|
width = this.xBarWidth ; |
|
|
|
} else { |
|
|
|
width = 20; |
|
|
|
} |
|
|
|
return width; |
|
|
|
} |
|
|
|
|
|
|
|
var widthMin, widthMax; |
|
|
|
if (this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
widthMin = dotSize / 2; // px
|
|
|
|
widthMax = dotSize / 2 + dotSize * 2; // Todo: put this in one function
|
|
|
|
} |
|
|
|
else { |
|
|
|
widthMin = 20; // px
|
|
|
|
widthMax = 20; // px
|
|
|
|
} |
|
|
|
|
|
|
|
var height = Math.max(this.frame.clientHeight * 0.25, 100); |
|
|
|
var top = this.margin; |
|
|
|
var right = this.frame.clientWidth - this.margin; |
|
|
|
var left = right - widthMax; |
|
|
|
var bottom = top + height; |
|
|
|
} |
|
|
|
/** |
|
|
|
* Redraw the legend based on size, dot color, or surface height |
|
|
|
*/ |
|
|
|
Graph3d.prototype._redrawLegend = function() { |
|
|
|
|
|
|
|
//Return without drawing anything, if no legend is specified
|
|
|
|
if (this.showLegend !== true) {return;} |
|
|
|
|
|
|
|
// Do not draw legend when graph style does not support
|
|
|
|
if (this.style === Graph3d.STYLE.LINE |
|
|
|
|| this.style === Graph3d.STYLE.BARSIZE //TODO add legend support for BARSIZE
|
|
|
|
){return;} |
|
|
|
|
|
|
|
// Legend types - size and color. Determine if size legend.
|
|
|
|
var isSizeLegend = (this.style === Graph3d.STYLE.BARSIZE |
|
|
|
|| this.style === Graph3d.STYLE.DOTSIZE) ; |
|
|
|
|
|
|
|
// Legend is either tracking z values or style values. This flag if false means use z values.
|
|
|
|
var isValueLegend = (this.style === Graph3d.STYLE.DOTSIZE |
|
|
|
|| this.style === Graph3d.STYLE.DOTCOLOR |
|
|
|
|| this.style === Graph3d.STYLE.BARCOLOR); |
|
|
|
|
|
|
|
var height = Math.max(this.frame.clientHeight * 0.25, 100); |
|
|
|
var top = this.margin; |
|
|
|
var width = this._getLegendWidth() ; // px - overwritten by size legend
|
|
|
|
var right = this.frame.clientWidth - this.margin; |
|
|
|
var left = right - width; |
|
|
|
var bottom = top + height; |
|
|
|
|
|
|
|
var canvas = this.frame.canvas; |
|
|
|
var ctx = canvas.getContext('2d'); |
|
|
|
ctx.lineWidth = 1; |
|
|
|
ctx.font = '14px arial'; // TODO: put in options
|
|
|
|
|
|
|
|
if (this.style === Graph3d.STYLE.DOTCOLOR) { |
|
|
|
if (isSizeLegend === false) { |
|
|
|
// draw the color bar
|
|
|
|
var ymin = 0; |
|
|
|
var ymax = height; // Todo: make height customizable
|
|
|
|
var y; |
|
|
|
|
|
|
|
for (y = ymin; y < ymax; y++) { |
|
|
|
var f = (y - ymin) / (ymax - ymin); |
|
|
|
|
|
|
|
//var width = (dotSize / 2 + (1-f) * dotSize * 2); // Todo: put this in one function
|
|
|
|
var hue = f * 240; |
|
|
|
var color = this._hsv2rgb(hue, 1, 1); |
|
|
|
|
|
|
@ -1021,55 +1045,63 @@ Graph3d.prototype._redrawLegend = function() { |
|
|
|
ctx.lineTo(right, top + y); |
|
|
|
ctx.stroke(); |
|
|
|
} |
|
|
|
|
|
|
|
ctx.strokeStyle = this.axisColor; |
|
|
|
ctx.strokeRect(left, top, widthMax, height); |
|
|
|
} |
|
|
|
ctx.strokeRect(left, top, width, height); |
|
|
|
|
|
|
|
if (this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
// draw border around color bar
|
|
|
|
} else { |
|
|
|
|
|
|
|
// draw the size legend box
|
|
|
|
var widthMin; |
|
|
|
if (this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
var dotSize = this.frame.clientWidth * this.dotSizeRatio; |
|
|
|
widthMin = dotSize / 2; // px
|
|
|
|
} else if (this.style === Graph3d.STYLE.BARSIZE) { |
|
|
|
//widthMin = this.xBarWidth * 0.2 this is wrong - barwidth measures in terms of xvalues
|
|
|
|
} |
|
|
|
ctx.strokeStyle = this.axisColor; |
|
|
|
ctx.fillStyle = this.dataColor.fill; |
|
|
|
ctx.beginPath(); |
|
|
|
ctx.moveTo(left, top); |
|
|
|
ctx.lineTo(right, top); |
|
|
|
ctx.lineTo(right - widthMax + widthMin, bottom); |
|
|
|
ctx.lineTo(right - width + widthMin, bottom); |
|
|
|
ctx.lineTo(left, bottom); |
|
|
|
ctx.closePath(); |
|
|
|
ctx.fill(); |
|
|
|
ctx.stroke(); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.style === Graph3d.STYLE.DOTCOLOR || |
|
|
|
this.style === Graph3d.STYLE.DOTSIZE) { |
|
|
|
// print values along the color bar
|
|
|
|
var gridLineLen = 5; // px
|
|
|
|
var step = new StepNumber(this.valueMin, this.valueMax, (this.valueMax-this.valueMin)/5, true); |
|
|
|
step.start(); |
|
|
|
if (step.getCurrent() < this.valueMin) { |
|
|
|
step.next(); |
|
|
|
} |
|
|
|
while (!step.end()) { |
|
|
|
y = bottom - (step.getCurrent() - this.valueMin) / (this.valueMax - this.valueMin) * height; |
|
|
|
|
|
|
|
ctx.beginPath(); |
|
|
|
ctx.moveTo(left - gridLineLen, y); |
|
|
|
ctx.lineTo(left, y); |
|
|
|
ctx.stroke(); |
|
|
|
|
|
|
|
ctx.textAlign = 'right'; |
|
|
|
ctx.textBaseline = 'middle'; |
|
|
|
ctx.fillStyle = this.axisColor; |
|
|
|
ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); |
|
|
|
// print value text along the legend edge
|
|
|
|
var gridLineLen = 5; // px
|
|
|
|
|
|
|
|
var legendMin = isValueLegend ? this.valueMin : this.zMin; |
|
|
|
var legendMax = isValueLegend ? this.valueMax : this.zMax; |
|
|
|
var step = new StepNumber(legendMin, legendMax, (legendMax-legendMin)/5, true); |
|
|
|
step.start(); |
|
|
|
if (step.getCurrent() < legendMin) { |
|
|
|
step.next(); |
|
|
|
} |
|
|
|
var y; |
|
|
|
while (!step.end()) { |
|
|
|
y = bottom - (step.getCurrent() - legendMin) / (legendMax - legendMin) * height; |
|
|
|
|
|
|
|
step.next(); |
|
|
|
} |
|
|
|
ctx.beginPath(); |
|
|
|
ctx.moveTo(left - gridLineLen, y); |
|
|
|
ctx.lineTo(left, y); |
|
|
|
ctx.stroke(); |
|
|
|
|
|
|
|
ctx.textAlign = 'right'; |
|
|
|
ctx.textBaseline = 'top'; |
|
|
|
var label = this.legendLabel; |
|
|
|
ctx.fillText(label, right, bottom + this.margin); |
|
|
|
ctx.textBaseline = 'middle'; |
|
|
|
ctx.fillStyle = this.axisColor; |
|
|
|
ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); |
|
|
|
|
|
|
|
step.next(); |
|
|
|
} |
|
|
|
|
|
|
|
ctx.textAlign = 'right'; |
|
|
|
ctx.textBaseline = 'top'; |
|
|
|
var label = this.legendLabel; |
|
|
|
ctx.fillText(label, right, bottom + this.margin); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|