Line chart/graph with an irregular threshold field - charts

Looking to create a bar chart with an irregular, colored threshold field in the background, so that each data point has its own individual set of min/max thresholds, which ultimately would look something like this: http://dcalvitti.webs.com/plant/SAMPLE.png
Looked at D3 examples like this one: http://bl.ocks.org/mbostock/4062844
Can the latter example be manipulated to look more like the image I created?
Thanks in advance..

The graph shown in your sample image is actually much easier than the linked example; for that, you don't need to create a clipping path and you don't need to draw the line twice with two different colours.
For drawing the coloured background, use an area-path generator, created with d3.svg.area(). Set the y0 accessor function to be extract your minimum value for each point in your data array, and the y1 accessor function to extract the maximum value.
Then draw the line overtop as a normal line graph with a d3.svg.line() path generator.
Working example, adapted from the fiddles in the comments: http://jsfiddle.net/h45CD/12/
(Note: I commented out half the dataset, since the "year" values were repeated, not sure what that was supposed to represent.)
Key code:
// Define the value line path generator
var line = d3.svg.line()
.x( function(d) { return x(d.year); } )
.y( function(d) { return y(d.temp); } );
// Define the area path generator
var area = d3.svg.area()
.x( function(d) { return x(d.year); } )
.y0( function(d) { return y(d.min); } )
.y1( function(d) { return y(d.max); } );
/* ... */
// Add the background area showing the historic range
svg.append("path")
.datum(data)
.attr("class", "historicRange")
.attr("d", area);
// Add the value line
svg.append("path")
.datum(data)
.attr("class", "dataline")
.attr("d", line);
Edit based on comments
If you do want a line that changes colour depending on historic values, as opposed to a line drawn overtop of a background range, the most straight-forward solution is probably to create a <pattern> element consisting of the different coloured regions, and use this to stroke the value line.
You'll want to familiarize yourself with the different options for the pattern element. This MDN tutorial has a good intro, or you could dive into the full W3 specs.
For this situation, we want the pattern to be sized and positioned relative to the coordinate system used for drawing the line, regardless of the size or shape of the line itself. That means we will be setting both the patternUnits and the patternContentUnits to be userSpaceOnUse. The height and width of the pattern will be the height and width of the plotting area.
Within the pattern we will draw the area that represents the max-min range, but we also need to draw separate areas, with different colours, for values above the max and values below the min. We can use the same area generator for each, but need to change the y0/y1 accessor functions each time.
Key code:
// Add the pattern showing the historic range
var pattern = defs.append("pattern")
.datum(data) //add the data to the <pattern> element
//so it will be inherited by each <path> we append
.attr({
"patternUnits":"userSpaceOnUse",
"patternContentUnits":"userSpaceOnUse",
"width": width,
"height": height
})
.attr("id", "strokePattern");
pattern.append("path")
.attr("class", "historicRange between")
.attr("d", area);
pattern.append("path")
.attr("class", "historicRange above")
.attr("d", area.y1( 0 )
.y0( function(d){return y(d.max);} )
);
pattern.append("path")
.attr("class", "historicRange below")
.attr("d", area.y1( function(d){return y(d.min);} )
.y0( height )
);
// Add the value line
plot.append("path")
.datum(data)
.attr("class", "dataline")
.attr("d", line)
.style("stroke", "url(#strokePattern)");
Working example: http://jsfiddle.net/h45CD/14/

I'm including a web page link with charts authored by myself based on AMCharts and with the help of that web site's founder. Contains several examples of the above question and more..
http://dcalvitti.webs.com/SAMPLE/NEWWEBINDEX.html
The charts provided are still being worked on. For example, AMcharts does have a function that clips the color of a line above/below a certain value which I didn't know about, so there is still work to be done. I spent many weeks on the charts and thought I'd share. I'm sure someone will find something new here down the road...

Related

Is there a way to get the ECharts series symbol to be passed in as the marker in the tooltip

I've got an ECharts chart that has multiple line series and a scatter series that represents events. For the line series, we left the symbol at the default, but for the event scatter series we set the symbol to 'diamond'. These symbols show up on the chart & in the series legend as expected. However, the tooltip always shows a 10 pixel dot for the marker. The color however is picked up from the series (and even from the visualMap config!). My initial assumption had been that the symbol would also be picked up from the series. In our case we wanted to use a function for tooltip.formatter and even in that function we couldn't figure out how to access and swap in the series symbol for the marker. We ended up working around it by just custom styling our own html to plug in for the marker that matched the diamond symbol pretty well.
So the open questions are:
Is there a way to have the tooltip marker pick up the symbol from the series?
If not, is this a bug? I'm happy to put in an issue on the project but I don't want to do that until I understand a bit more.
Here's some code to illustrate what we had to do to get the diamond in there in case it helps the discussion or if others want to leverage this workaround:
formatTooltip(args){
let time = DateTime.fromISO(args[0].data[0], { zone: this.user.timeZone })
let tooltip = `<div><b>${time.toFormat(TOOLTIP_FORMAT)}</b></div>`
args.forEach(({ marker, seriesName, value }) => {
if (seriesName === 'Events'){
let myMarker = `<span style="display:inline-block;margin-right:4px;width:10px;height:10px;background:${value[4]};transform:rotate(45deg);"></span>`
tooltip += `<div>${myMarker} ${value[3] ? value[3]: ''}</div>`
} else {
value = value || [0, 0]
tooltip += `<div>${marker} ${seriesName}: ${value[1]}</div>`
}
})
return tooltip
},

Google Charts offsetting the horizontal axis marker labels

Does anyone know if its possible to offset the markers so they appear between the column of a google chart?
So that it appears like this design mockup...
Instead of the markers being directly inline with the columns like below which is the default behaviour of the google.visualization.ColumnChart api.
I have search through the documention, however cannot find any references to options that would allow for this kind of customisation. Does anyone know if perhaps there is a way of manipulating the layout after it has been rendered? Or if in fact there is an option to do this but I've just overlooked it?
Thanks
The chart is rendered in a <svg> structure containing <g>, <rect>, <text> (and other) elements. The structure differs a lot form chart to chart, and the internal ordering can change if basic chart elements are left out. The horizontal axis elements is rendered as something like
<text text-anchor="middle" x="468.46875" y="343.05" font-family="Arial" font-size="13" stroke="none" stroke-width="0" fill="#222222">12</text>
To get an idea of where to look for those <text> elements in the <svg> structure you can copy the rendered code of the chart to a editor capable of styling code, or use a online code beautifier.
Then simply iterate through the <svg> by using DOM methods such as querySelector, querySelectorAll, getElementsByTagName etc.
See this google.visualization.ColumnChart :
By changing the x attribute of each <text> element that belongs to the horizontal axis we can get the labels to appear between the columns :
google.visualization.events.addListener(chart, 'ready', updateAxis);
function updateAxis() {
var x,
svg = document.getElementById('chart').querySelector('svg'),
g = svg.querySelectorAll('g'),
chartArea = g[3].querySelectorAll('g'),
hAxisTexts = chartArea[5].querySelectorAll('text');
//0-15 labels, the rest belongs to the yAxis
for (var i=0;i<16;i++) {
x = parseFloat(hAxisTexts[i].getAttribute('x'));
if (x>9) {
x = x-15;
} else {
x = x-18;
}
hAxisTexts[i].setAttribute('x', x);
}
}
demo -> http://jsfiddle.net/hrrL45oq/
This is only an example. You will perhaps need to target a different <g> element holding the <text>'s, and how you manipulate x or other attributes of <text> depends of the layout of the chart.

google charts annotations show right side of point

I am using google charts for plotting a graph
How can I show annotation of the point at right-hand-side of the point but it showing on the top of point
http://i.stack.imgur.com/UHhQH.png
I want it like as follow
http://i.stack.imgur.com/lUBcq.png
Please any one help me out
You can actually change the position of the annotations, by using css tranform.
You should first get a handle to the anntation text, if you want to change all the text, then you can use the text tag name in css
text {
transform: translate(10px, 30px);
}
I was able to adjust annotations to the right by doing 2 things:
1) Entered some white spaces (\u00A0 is white space) and a long dash (—) on the left side of the desired annotation.
2) Added stem length of -3.
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Model');
dataTable.addColumn('number', 'T');
dataTable.addColumn({type:'string', role:'annotation'});
dataTable.addRows([
['ABC',30,'\u00A0\u00A0\u00A0\u00A0 — X'],
['DEF',20,'\u00A0\u00A0\u00A0\u00A0 — Y'],
['GHI',10,'\u00A0\u00A0\u00A0\u00A0 — Z'],
]);
var options = {
1: {annotations: {stem: {length: -3}}
};

Add rectangle as inline-element with iText

How do I add a rectangle (or other graphical elements) as inline-elements to an iText PDF?
Example code of what I'm trying to achieve:
foreach (Row r in entrylist)
{
p = new Paragraph();
p.IndentationLeft = 10;
p.SpacingBefore = 10;
p.SpacingAfter = 10;
p.Add(new Rectangle(0, 0, 10, 10)); <<<<<<<<< THAT ONE FAILS
p.Add(new Paragraph(r.GetString("caption"), tahoma12b));
p.Add(new Paragraph(r.GetString("description"), tahoma12));
((Paragraph)p[1]).IndentationLeft = 10;
doc.Add(p);
}
It's something like a column of text-blocks, of which each of them have (only a printed) checkbox.
I've tried various things with DirectContent, but it requires me to provide absolute X and Y values. Which I simply don't have. The elements should be printed at the current position, wherever that may be.
Any clues?
You need a Chunk for which you've defined a generic tag. For instance, in this example listing a number of movies, a snippet of pellicule is drawn around the year a movie was produced and an ellipse was drawn in the background of the link to IMDB.
If you look at the MovieYears example, you'll find out how to use the PdfPageEvent interface and its onGenericTag() method. You're right that you can't add a Rectangle to a Paragraph (IMHO that wouldn't make much sense). As you indicate, you need to draw the rectangle to the direct content, and you get the coordinates of a Chunk by using the setGenericTag() method. As soon as the Chunk is drawn on the page, its coordinates will be passed to the onGenericTag() method.

transitioning lines in d3.js

Sorry if this question seems stupid, but it's stumped me for a couple days, so I would really appreciate any simple input from anyone! :)
I'm trying to construct a line graph in d3.js that transitions between different datasets. However, whenever I hit the transition function, it selects the original line on the graph, AND the axes of the graph, and transitions all of it. I tried to do selectAll("svg:path") instead of selectAll("path") but it just returned a DOMException 12, indicating that the selection didn't exist.
//beginning of code to append axis to graph
graph.append("svg:g").attr("class", "x axis")
//draws the original line on the graph
graph.append("svg:path").attr("d", line(dataset1));
//line function
var line = d3.svg.line()
.x(function(d) {return x(d.age);})
.y(function(d) {return y(d.freq);})
.interpolate("basis");
//transition function
function transition(newData) {
graph.selectAll("path")
.data(newData)
.transition()
.duration(2000)
.attr("d", line(newData));
}
Thanks for any responses! :)
Just give the thing you want to change a unique class/identifier, e.g.
graph.append("svg:path").attr("d", line(dataset1)).classed("line", true);
...
graph.selectAll("path.line")
.data(newData)
...