Add box chart axis
This commit is contained in:
parent
f0450ea703
commit
ef276ed577
|
@ -47,6 +47,7 @@ body {
|
||||||
width: 950px;
|
width: 950px;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.linechart svg {
|
.linechart svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -69,13 +70,13 @@ body {
|
||||||
.linechart .dot.errors {
|
.linechart .dot.errors {
|
||||||
fill: #f64;
|
fill: #f64;
|
||||||
}
|
}
|
||||||
.linechart .axis {
|
.axis {
|
||||||
stroke: #888;
|
stroke: #888;
|
||||||
}
|
}
|
||||||
.linechart .arrow {
|
.arrow {
|
||||||
stroke: #888;
|
stroke: #888;
|
||||||
fill: #888;
|
fill: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -85,7 +86,7 @@ body {
|
||||||
.boxplot {
|
.boxplot {
|
||||||
float: left;
|
float: left;
|
||||||
width: 950px;
|
width: 950px;
|
||||||
height: 200px;
|
height: 170px;
|
||||||
}
|
}
|
||||||
.boxplot svg {
|
.boxplot svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -97,8 +97,13 @@ var Daemon = React.createClass({
|
||||||
var BoxPlot = React.createClass({
|
var BoxPlot = React.createClass({
|
||||||
render: function(){
|
render: function(){
|
||||||
var points = this.props.points,
|
var points = this.props.points,
|
||||||
maxHeight = 140,
|
chartWidth = 950,
|
||||||
padding = 5;
|
chartHeight = 170,
|
||||||
|
padLeft = 30,
|
||||||
|
padTop = 10,
|
||||||
|
padBottom = 20,
|
||||||
|
valueInterval = 5,
|
||||||
|
maxHeight = chartHeight - padTop - padBottom;
|
||||||
|
|
||||||
var min, max;
|
var min, max;
|
||||||
points.map(function(point) {
|
points.map(function(point) {
|
||||||
|
@ -112,14 +117,13 @@ var BoxPlot = React.createClass({
|
||||||
|
|
||||||
var renderBox = function(point, i) {
|
var renderBox = function(point, i) {
|
||||||
var relativeY = function(val) {
|
var relativeY = function(val) {
|
||||||
return maxHeight - Math.round((val-min)/(max-min) * maxHeight) + padding;
|
return maxHeight - Math.round((val-min)/(max-min) * maxHeight);
|
||||||
};
|
};
|
||||||
|
|
||||||
var width = 10;
|
var boxWidth = 10;
|
||||||
var padding = 5;
|
|
||||||
|
|
||||||
var x1 = (width + padding) * i + padding;
|
var x1 = (boxWidth + valueInterval) * i + padLeft + valueInterval;
|
||||||
var x2 = x1 + width;
|
var x2 = x1 + boxWidth;
|
||||||
var minY = relativeY(point.min);
|
var minY = relativeY(point.min);
|
||||||
var p25Y = relativeY(point.p25);
|
var p25Y = relativeY(point.p25);
|
||||||
var medianY = relativeY(point.median);
|
var medianY = relativeY(point.median);
|
||||||
|
@ -135,21 +139,21 @@ var BoxPlot = React.createClass({
|
||||||
y2={maxY}
|
y2={maxY}
|
||||||
className="tick" />
|
className="tick" />
|
||||||
<line key="max-whisker"
|
<line key="max-whisker"
|
||||||
x1={x1+width/2}
|
x1={x1+boxWidth/2}
|
||||||
x2={x1+width/2}
|
x2={x1+boxWidth/2}
|
||||||
y1={maxY}
|
y1={maxY}
|
||||||
y2={p75Y}
|
y2={p75Y}
|
||||||
className="whisker" />
|
className="whisker" />
|
||||||
<line key="min-whisker"
|
<line key="min-whisker"
|
||||||
x1={x1+width/2}
|
x1={x1+boxWidth/2}
|
||||||
x2={x1+width/2}
|
x2={x1+boxWidth/2}
|
||||||
y1={minY}
|
y1={minY}
|
||||||
y2={p25Y}
|
y2={p25Y}
|
||||||
className="whisker" />
|
className="whisker" />
|
||||||
<rect key="iqr"
|
<rect key="iqr"
|
||||||
x={x1}
|
x={x1}
|
||||||
y={p75Y}
|
y={p75Y}
|
||||||
width={width}
|
width={boxWidth}
|
||||||
height={p25Y - p75Y}
|
height={p25Y - p75Y}
|
||||||
className="iqr" />
|
className="iqr" />
|
||||||
<line key="median"
|
<line key="median"
|
||||||
|
@ -167,10 +171,22 @@ var BoxPlot = React.createClass({
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var yMaxX = padLeft - 3,
|
||||||
|
yMaxY = padTop + 5;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="boxplot">
|
<div className="boxplot">
|
||||||
<svg>
|
<svg>
|
||||||
|
<text key="title" x={-70} y={10} textAnchor="middle" transform="rotate(270)" className="axis-label">Speed</text>
|
||||||
{this.props.points.map(renderBox)}
|
{this.props.points.map(renderBox)}
|
||||||
|
<line key="y-axis" x1={padLeft} x2={padLeft} y1={0} y2={maxHeight} className="axis" />
|
||||||
|
<path key="y-arrow" d="M30,0 32,7 28,7 Z" className="arrow" />
|
||||||
|
<text key="y-max" x={yMaxX} y={yMaxY} textAnchor="end"className="axis-label">{max.toFixed(1)}</text>
|
||||||
|
<text key="y-zero" x={27} y={100} textAnchor="end" className="axis-label">0</text>
|
||||||
|
<line key="x-axis" x1={padLeft} x2={950} y1={maxHeight} y2={maxHeight} className="axis" />
|
||||||
|
<path key="x-arrow" d="M950,140 943,142 943,138 Z" className="arrow" />
|
||||||
|
<text key="x-label-now" x={940} y={chartHeight - padBottom} textAnchor="end" className="axis-label">now</text>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -179,17 +195,16 @@ var BoxPlot = React.createClass({
|
||||||
|
|
||||||
var LineChart = React.createClass({
|
var LineChart = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var width = 950,
|
|
||||||
height = 120,
|
|
||||||
paddingLeft = 30,
|
|
||||||
paddingTop = 10,
|
|
||||||
paddingBottom = 20;
|
|
||||||
|
|
||||||
var points = this.props.points,
|
var points = this.props.points,
|
||||||
maxHeight = height - paddingTop - paddingBottom,
|
chartWidth = 950,
|
||||||
padding = 30;
|
chartHeight = 120,
|
||||||
|
padLeft = 30,
|
||||||
|
padTop = 10,
|
||||||
|
padBottom = 20,
|
||||||
|
valueInterval = 15;
|
||||||
|
maxHeight = chartHeight - padTop - padBottom;
|
||||||
|
|
||||||
var min = 0, max = 0;
|
var max = 0;
|
||||||
points.map(function(point) {
|
points.map(function(point) {
|
||||||
if (max === undefined || point.processed > max) {
|
if (max === undefined || point.processed > max) {
|
||||||
max = point.processed;
|
max = point.processed;
|
||||||
|
@ -203,19 +218,18 @@ var LineChart = React.createClass({
|
||||||
|
|
||||||
var npoints = points.map(function(point, i) {
|
var npoints = points.map(function(point, i) {
|
||||||
var val = point[key];
|
var val = point[key];
|
||||||
var width = 15;
|
var x = i * valueInterval + padLeft;
|
||||||
var x = i * width + padding;
|
var y = maxHeight - Math.round(val/max * maxHeight) + padTop;
|
||||||
var y = maxHeight - Math.round((val-min)/(max-min) * maxHeight) + paddingTop;
|
|
||||||
|
|
||||||
return [x, y];
|
return [x, y];
|
||||||
});
|
});
|
||||||
|
|
||||||
var numMaxPoints = points.map(function(point, i) {
|
var maxPointsRatio = points.map(function(point, i) {
|
||||||
var val = point[key];
|
var val = point[key];
|
||||||
return val === max ? 1 : 0;
|
return val === max ? 1 : 0;
|
||||||
}).reduce(function(sum, val) {
|
}).reduce(function(sum, val) {
|
||||||
return sum + val;
|
return sum + val;
|
||||||
});
|
}) / points.length;
|
||||||
|
|
||||||
var path = npoints.map(function(point, i) {
|
var path = npoints.map(function(point, i) {
|
||||||
var x = point[0], y = point[1];
|
var x = point[0], y = point[1];
|
||||||
|
@ -232,11 +246,11 @@ var LineChart = React.createClass({
|
||||||
|
|
||||||
var r = 2; // Radius
|
var r = 2; // Radius
|
||||||
// Hide leftmost and zero points
|
// Hide leftmost and zero points
|
||||||
if (x === paddingLeft || y === height - paddingBottom) {
|
if (x === padLeft || y === chartHeight - padBottom) {
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
// Highlight max values if less then 50% of values are max
|
// Highlight max values if less then 25% of values are max
|
||||||
if (y == paddingTop && numMaxPoints / points.length < .5) {
|
if (y == padTop && maxPointsRatio <= .25) {
|
||||||
r = 4;
|
r = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,14 +272,12 @@ var LineChart = React.createClass({
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Define magic numbers from below here
|
// TODO: Define magic numbers from below here
|
||||||
var yMaxX = paddingLeft - 3,
|
var yMaxX = padLeft - 3,
|
||||||
yMaxY = paddingTop + 5,
|
yMaxY = padTop + 5;
|
||||||
xLabel1x = paddingLeft,
|
|
||||||
xLabel2x = paddingLeft + 15 * 6;
|
|
||||||
|
|
||||||
var xlabels = Array.apply(null, Array(10)).map(function(_, i){
|
var xlabels = Array.apply(null, Array(10)).map(function(_, i){
|
||||||
return <text key={"x-label-"+ i}
|
return <text key={"x-label-"+ i}
|
||||||
x={paddingLeft + (15 * 6 * i)}
|
x={padLeft + (15 * 6 * i)}
|
||||||
y={110}
|
y={110}
|
||||||
textAnchor="middle"
|
textAnchor="middle"
|
||||||
className="axis-label">
|
className="axis-label">
|
||||||
|
@ -276,9 +288,10 @@ var LineChart = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div className="linechart">
|
<div className="linechart">
|
||||||
<svg>
|
<svg>
|
||||||
|
<text key="title" x={-50} y={10} textAnchor="middle" transform="rotate(270)" className="axis-label">Throughput</text>
|
||||||
{makePath(points, "processed")}
|
{makePath(points, "processed")}
|
||||||
{makePath(points, "errors")}
|
{makePath(points, "errors")}
|
||||||
<line key="y-axis" x1={30} x2={30} y1={0} y2={100} className="axis" />
|
<line key="y-axis" x1={padLeft} x2={padLeft} y1={0} y2={100} className="axis" />
|
||||||
<path key="y-arrow" d="M30,0 32,7 28,7 Z" className="arrow" />
|
<path key="y-arrow" d="M30,0 32,7 28,7 Z" className="arrow" />
|
||||||
<text key="y-max" x={yMaxX} y={yMaxY} textAnchor="end"className="axis-label">{max}</text>
|
<text key="y-max" x={yMaxX} y={yMaxY} textAnchor="end"className="axis-label">{max}</text>
|
||||||
<text key="y-zero" x={27} y={100} textAnchor="end" className="axis-label">0</text>
|
<text key="y-zero" x={27} y={100} textAnchor="end" className="axis-label">0</text>
|
||||||
|
|
Loading…
Reference in New Issue