Flot graphing stacks from opposite axies - flot

I'm working a display where I don't know where the end point is (100% is an evolving figure... graph will update via ajax). The data is going to a mix of completed records against an estimated count where it will complete.
As time goes on, the counts go up and the estimated completion point becomes tighter.
not sure that image ^ is working... (most things are blocked here, sorry)
ascii example as a horiz bar:
[///////40%////// ******SPACE*******/////20%//////]
I've tried using data like
var rawData = [
[40, 0],
[-20, 0],
];
to show 40% done and 20% as potential end point range. but that doesn't work. at all
var rawData = [
[40, 0],
[20, 0],
];
shows as 60% in stacked format which is not what I want.
Can I have 2 bars on the same 'row' that are stacked, but not stacked from the same axis?

As far as I know there is no way to stack a single series against itself. With that said here's my 5 min attempt to replicate your image:
As #DNS had suggested, I used a transparent middle series to space the complete/estimated bars. To keep it easier to track where the points belong, I added each bar as it's own series.
Fiddle is here.
var data = [];
// 10 passes
data.push({data:[[40,2]], color: 'green'});
data.push({data:[[40,2]], color: 'transparent'});
data.push({data:[[20,2]], color: 'silver'});
// 100 passes
data.push({data:[[50,1]], color: 'green'});
data.push({data:[[20,1]], color: 'transparent'});
data.push({data:[[30,1]], color: 'silver'});
// 1000 passes
data.push({data:[[70,0]], color: 'green'});
data.push({data:[[20,0]], color: 'transparent'});
data.push({data:[[10,0]], color: 'silver'});
$.plot($("#placeholder"), data, {
series: {
stack: true,
lines: { show:false },
bars: { show: true, horizontal:true, barWidth: 0.6 }
},
xaxis: {min: 0, max: 100, ticks: [[0, '<span style="color: green">Completed<br/>0%</span>'],[100, '<span style="color: gray">Estimated End Point<br/>100%</span>']]},
legend: {show: false},
yaxis: {tickColor: 'transparent',position: 'right',
ticks: [[0.25,'as of 1000 passes'],
[1.25,'as of 100 passes'],
[2.25,'as of 10 passes']]}
});

Create 3 bars instead of 2, with the middle bar filling the remaining space up to 100. Use series objects, so you can assign the middle one an 'empty' color, like white.
So with your example above, where you have 40 and 20, your middle bar would have a value of 100 - 40 - 20 = 40.

Related

How do I improve performance of JointJS with many links?

After profiling the code it looks like bbox function is being called repeatedly. I cannot remove marker-source, marker-target and connection-wrap because I need those features. Is there a way to improve performance?
Try to replace marker-source and marker-target with SVG Markers. It's relatively easy to implement if your application does not require different sizes and colors of markers. For instance:
Define you own marker arrow.
var arrowMarker = V('marker', {
viewBox: "0 0 10 10",
refX: 9,
refY: 5,
markerWidth: 6,
markerHeight: 6,
orient: "auto"
}, [
V('path', {
'd': "M 0 0 L 10 5 L 0 10 z",
'fill': 'green'
})
]);
Add the marker to paper's SVG Defs so it can be reused later for multiple times.
V(paper.defs).append(arrowMarker);
Finally put the marker on a link. Use the marker-end or marker-start property to define the target resp. source marker.
var link = new joint.dia.Link({
markup: '<path class="connection"/><path class="connection-wrap"/>',
attrs: {
'.connection': {
'stroke': 'green',
'stroke-width': 2,
'marker-end': 'url(#' + arrowMarker.attr('id') + ')'
}
}
});
There is a JSFiddle with an example and other useful performance tips.

Draw a path out gradually from the middle

Suppose I have an arbitrary path drawn with d3
var points = [0, 4, 4, 4, 8, 8, 4, 4, 4, 8, 4, 4, 4, 4, 0];
var svg = d3.select('svg');
var line = d3.svg.line()
.y(function(d) { return 10*d})
.x(function(d, t) { return t*20 })
.interpolate('cubic');
svg.append('path')
.attr('d', line(points))
.attr('stroke', 'black')
.attr('stroke-width', 2)
.attr('fill', 'none')
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
<svg style="width: 100%; height: 100%; outline: 1px solid green;"></svg>
I want to animate the path drawing out slowly. I understand how to do it from beginning to end but in my case I want to start at an arbitrary point on the line and draw outward at the same rate in both direction.
I can't quite figure out how to do this.
I can utilize attrTween and take slices of the array varying by time, but if I do that, the line shifts since I don't know how to set the horizontal offset correctly at each step.
Hopefully you're working with the second answer on the page you linked to (the one by #duopixel), because that's a much better way. If so, then you can make the line start drawing from the middle if you slightly modify the attributes:
var points = [0, 4, 4, 4, 8, 8, 4, 4, 4, 8, 4, 4, 4, 4, 0];
var svg = d3.select('svg');
var line = d3.svg.line()
.y(function(d) { return 10*d})
.x(function(d, t) { return t*20 })
.interpolate('cubic');
var path = svg.append('path')
.attr('d', line(points))
.attr('stroke', 'black')
.attr('stroke-width', 2)
.attr('fill', 'none');
totalLength = path.node().getTotalLength();
path
.attr("stroke-dasharray", '0 ' + totalLength)
.attr("stroke-dashoffset", totalLength/2)
.transition()
.duration(2000)
.attr("stroke-dasharray", totalLength + ' 0')
.attr("stroke-dashoffset", totalLength);
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
<svg style="width: 100%; height: 100%; outline: 1px solid green;"></svg>
How it works:
First, consider the original, common scenario of animating the drawing of a path from its start to its end. If l is the length of the path (obtained by path.node().getTotalLength()) then setting the path's stroke-dasharray to l + ' ' + l makes the dash and the gap between it and the next dash both equal to l. Under these conditions, the path would appear solid, because the dash length being l "pushes" the gap past the end of the path. By setting stroke-dashoffset to l, the above scenario is reversed — the path is entirely a gap (hence invisible) and the dash falls off the path. By transitioning between these 2 states (from one with offset to one without offset), we get a gradual drawing of a line.
Now, to animate from the middle, the dash is defined with length 0 and the gap has a length l. So now the line is also completely invisible, due to the 0-length dash and the l-length gap . Setting stroke-dashoffset to l/2 moves this 0-length dash halfway down the path. That's the animation starting state. The end state is the reverse dasharray where gap is 0 and dash-length is l, which renders the line completely solid. To properly transition between these states, we also need to set the end state's stroke-dashoffset to l. That was something I figured out experimentally, and I'm not sure exactly how to explain it in words. But it works....

Can't get susy to use gutter in 'px' while in math:static mode

I want to create a fixed non-flexible very damn static grid of 1200px.
So I figured out, I need 90px for column-width, 12 columnts, 10px of gutter and 1200px of max-width.
Well.. the following are my settings and it gives me an error "invalid null opearation: 11 times null "
$susy: (
flow: ltr,
math: static,
output: float,
gutter-position: after,
container: auto,
container-position: center,
columns: 12,
gutters: 10px,
column-width: 90px,
global-box-sizing: content-box,
last-flow: to,
debug: (
image: show,
color: rgba(#66f, .25),
output: overlay,
toggle: top right,
),
use-custom: (
background-image: true,
background-options: false,
box-sizing: true,
clearfix: false,
rem: true,
)
);
style.scss>
#import "grids";
body{
#include container($susy);
max-width: 1200px;
border: solid thin red;
height:10px;
}
You need to specify gutters proportionally to your columns.
In this case:
gutters: 1/9,
The end result (being your columns 90px) would be gutters 10px wide. You can specify your gutters width in pixels by expressing it as a proportion.
As per the docs, you can speficy gutter width in pixels, by putting the column width as well. E.g.:
gutters: 10px/90px
Alhtough the result is exactly the same. And if you put in a value that doesn't match with your column width, you won't get the pixel width you say, but the appropriate fraction.
So having:
column-width: 100px,
gutters: 10px/50px,
will leave you with 20px wide gutters. Because of math. :)
Pen showing it working here.
And finally, your layout is 1190px wide and not 1200px because:
12 columns * 90px = 1080px
11 gutters * 10px = 110px.
1180px + 110px = 1190px.

How do gutters work in Susy 2?

I am trying to generate gutters which span 1/5 of 4 a column span. The global setup is:
$page-width: 1080px;
$susy: (
columns: 12,
math: fluid,
gutter-position: inside,
gutters: 1/4.5, // will be overriden; I think ...
global-box-sizing: border-box,
use-custom: (rem: true),
container: $page-width
);
Followed by this selector:
.mosaic {
// Setting gutters of 4 * 1/5 single column width,
// to be distributed 2/5 left, 2/5 right
#include gallery(4 of 12 4/5);
}
The generated CSS for .mosaic is:
.mosaic {
width: 33.33333%;
float: left;
padding-left: 1.85185%; // Expected/wanted: 3.333...%
padding-right: 1.85185%; // dito
}
I did expect the padding at each side to be 4/5 / 12 (columns) / 2 (sides) = 1/30 = 3.333...% which would result in a gutter of 1/5 (1/10 on each side) of the column span's total width.
How do I achieve the expected result?
How are the padding values (1.85...%) calculated?
Why do they not match what I expect?
This is how Susy does the math:
Each column is 1 column-unit wide, plus 4/5 column-units of gutter. Total: 1.8
There are 12 columns. Total: 21.6
Each gutter is calculated as .8/21.6 (target/context). Total: .037037037
That gutter is divided in half & converted to a percentage. Final: 1.8518518%
The difference is that gutters are considered part of the total context. They add to the width of each column, rather than being subtracted from it.

Flot time series, too many data points

I've plotted win rate on a Flot chart here: http://jsfiddle.net/xR66k/
The x-axis displays the week number, but I don't want the points between these ticks (for example between week 37 and 38, and between week 41 and 42) – how can I remove these?
I'm creating the ticks with the following code:
var data = [[1382911200000,7.6805],[1382306400000,27.4607],[1381701600000,13.0376],[1381096800000,-26.3855],[1380492000000,-11.9624],[1379887200000,-5.018],[1379282400000,-11.0009],[1378677600000,50.5376],[1378072800000,0],[1377468000000,0]];
var ticks = [];
for (var i = 0; i < data.length; i++) {
ticks.push(data[i][0]);
}
Why does Flot plot extra data points?
As I said in my comment this is a known limitation of the threshold plugin, so, let's work around it. In this fiddle, I've simply created two series one with just points and one with just lines. The "just lines" will get threshold properly without the addition of point markers.
data = [
{ label: 'Win Rate', data: data, points: {show:false} },
{ label: null, data: data, points: {show:true}, lines: {show:false} }
];

Resources