javascript - Can't add nice shading to highcharts -


i have 2 lines, a , b , try paint in different colors area between them: green a > b , red a < b. i've implemented shading area via arearange series type. can see work here: http://jsfiddle.net/ksnst/

the problem is: when data grouping occurs (i.e. single point in chart corresponds more 1 day in case), shading goes crazy. if narrow down chart interval range selector in bottom, shading perfect. when widen goes out of line bounds.

i tried write own handler arearange.datagrouping.approximation didn't much. ideas?

there similar question here solution won't work grouping.

as sebastian bochan states in answer it's simpler if create areas on / under shading directly data -- don't think need work you're doing build shaded areas. however does't solve data grouping problem.

i can close -- not quite perfect. @ first thought issue using same aggregate function on data sets, doesn't work goes wrong whenever aggregates on crossing point.

what did create 2 sets of range data go b:

for (i = 0; < data1.length; ++) {      var vala = data1[i][1];     var valb = data2[i][2];            under[i] = [data1[i][0], vala, valb ];       over[i] = [data1[i][0], valb, vala ];   } 

then gave each set of range data it's aggregate function changes shape of graph show over/under applicable.

function shadeapproxunder(low,high) {     low = average_(low);     high = average_(high);     if (low > high) return [ high, high ];     return [ low, high ]; }  function shadeapproxover(low,high) {     low = average_(low);     high = average_(high);     if (low > high) return [ low, low ];     return [ low, high ];         } 

and 1 lines know aggregate values same:

function lineapprox(values) {      var avg = average_(values);     return avg; } 

that gets close can see in fiddle, can see doesn't work perfectly. that's because there points 2 lines cross there's no data-point. since assume system drawing things in chunks between 2 data points there's no way work.

you can try returning [ null, null ] instead of [ high, high ] or [ low, low ] in aggregate functions , see more gaps.

it looks need somehow datapoints added @ crossover junctions, , i'm not sure how that. can't edit data because data grouping change -- can't in aggregate function can't add datapoints.

you attempt save aggregate data point values generated when draw lines, , use insert area graph data points extrapolated -- i'm not clear on how that'll work when refresh graph (i suspect not).

edit

i had bash @ better solution, still doesn't work -- maybe or else can spot flaw.

basically, said above, want add datapoints line intersections on our shading curve, attempt @ -- done using data chart stored in 'datagrouping' data after it's grouped:

function updatechart(chart, refresh) {     var dir = 0;     var on = array(), under = array();     var dataa = chart.series[2].groupeddata;     var datab = chart.series[3].groupeddata;      j = 0; // index over/under     (i=0;i < dataa.length; i++) {                     if (dataa[i].y < datab[i].y) {                                        if (dir == -1) {                  over[j] = under[j] = getintersection(dataa[i-1], dataa[i],                                                       datab[i-i], datab[i]);                          j++;             }             dir = 1;             over[j] = [ dataa[i].x, dataa[i].y, datab[i].y ];             under[j] = [ dataa[i].x, datab[i].y, datab[i].y ];         } else if (dataa[i].y == datab[i].y) {              dir = 0;             over[j] = [ dataa[i].x, dataa[i].y, dataa[i].y ];             under[j] = [ dataa[i].x, dataa[i].y, dataa[i].y ];         } else {              if (dir == 1) {              over[j] = under[j] = getintersection(dataa[i-1], dataa[i],                                                   datab[i-i], datab[i]);                              j++;             }             dir = -1;             over[j] = [ dataa[i].x, datab[i].y, datab[i].y ];             under[j] = [ dataa[i].x, datab[i].y, dataa[i].y ];         }             j++;     }     chart.series[0].setdata(over, refresh);     chart.series[1].setdata(under, refresh); } 

fiddle.

note seems stuck in loop, i'm not sure why.

you can see line intersect function in fiddle, it's lifted wikipedia. there 2 problems this, first there's no sensible event attach function -- in fiddle it's attached load , redraw. can't start redraw inside redraw event (which makes sense) shading shown 1 set of data behind plot lines -- obvious if switch zoom settings example. but, should reasonably easy fix if you're prepared edit highchart source code , put hook in allow attach update function after grouping before final rendering.

why shading still not right? either i've got line-intersection logic wrong, or it's accuracy when working small (accurate) numbers , big ones. or it's high chart limitation.

the other option, not going right use redraw , renderer class , directly draw shaded areas svg path onto graph.

if come else i'll edit again -- think i'm out of ideas how this.

edit 2

ok, think 'correct' way modify highcharts , create new chart type it's own renderer (so it'd extended area chart knew change colors on cross-over , draw lines in different colors). i've no idea how easy is.

however, hack draw svg paths directly on graph works ok , have logic other examples on page, update chart function might like:

var over_path = null; var under_path = null; function updatechart(chart) {      // create paths on first call ...     if (!over_path) {         over_path = chart.renderer.path();         over_path.attr({fill: '#bbeebb'}).add();     }     if (!under_path) {                 under_path = chart.renderer.path();         under_path.attr({fill: '#eebbbb'}).add();          }      // data chart     apts = chart.series[0].points;     bpts = chart.series[1].points;      var i;      var overpts = array();    // svg path instructions     var underpts = array();        var mx = chart.plotleft;  // offset each point     var = chart.plottop;     var ipt;                  // intersection points      // draw path along line b, along a/b      // complete closed space. first go along b      overpts[0] = underpts[0] = 'm'; // move start     overpts[1] = underpts[1] = bpts[0].plotx + mx;     overpts[2] = underpts[2] = bpts[0].ploty + my;     overpts[3] = underpts[3] = 'l'; // draw here     (i=1; i<apts.length; i++) {          overpts[overpts.length] = underpts[underpts.length] = bpts[i].plotx + mx;         overpts[overpts.length] = underpts[underpts.length] = bpts[i].ploty + my;     }      // go backwards along looking cross-overs ...         var dir = 0;         var newdir = 0;     (i=(apts.length - 1); i>=0; i--) {          var = apts[i].ploty + my;         var b = bpts[i].ploty + my;          newdir = (a>b)?1:((a<b)?-1:0);         if (dir && (dir != newdir)) {             // change direction, add intersect point             ipt = getintersection(apts[i], apts[i+1], bpts[i], bpts[i+1]);             overpts[overpts.length] = underpts[underpts.length] =ipt.plotx + mx;             overpts[overpts.length] = underpts[underpts.length] = ipt.ploty +          }         dir = newdir;          // add matching data point          overpts[overpts.length] = apts[i].plotx + mx;         underpts[underpts.length] = apts[i].plotx + mx;         if (a > b) {              overpts[overpts.length] = b;             underpts[underpts.length] = a;         } else {              overpts[overpts.length] = a;             underpts[underpts.length] = b;         }             }              // update new path     over_path.attr({'d': overpts});     under_path.attr({'d': underpts});  } 

fiddle

note: here i'm reading undocumented contents of chart object work out points are, since isn't in official api may change in future versions of highcharts (although, not -- it's aware of possibility).

the main problem area appears before initial graph draw animation, can find way round (you fade in first time might cool). since further redraws aren't animated it's not problem. there's 'fuzziness' in views think due anti-aliasing, might want tweak that.

unless there's different chart package data grouping can take account of line intersections think above best solution doesn't involve delving source of charting package.

anyway, interesting problem occupy mind week. :)


Comments

Popular posts from this blog

c# - How Configure Devart dotConnect for SQLite Code First? -

java - Copying object fields -

c++ - Clear the memory after returning a vector in a function -