arty-charty/util.js
function makeLineOrAreaChartPath(chart, width, t, maxValue, chartHeight, chartHeightOffset, markerRadius, pointsOnScreen, makeArea, isRange) {
    let heightScaler = (chartHeight-markerRadius)/maxValue;
    let xSpacing = width / pointsOnScreen;
    let centeriser = xSpacing / 2 - markerRadius;
    let fullWidth = xSpacing*(chart.data.length-1) + markerRadius + centeriser;

    let lineStrArray = makeArea && !isRange ? ['M' + markerRadius, chartHeight+chartHeightOffset] : [];
    if (isRange) {
      lineStrArray.push('M');
      lineStrArray.push(makeXcord(chart, fullWidth, t, centeriser, markerRadius));
      lineStrArray.push((chartHeight+chartHeightOffset) - chart.data[0].value * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[0 % chart.timingFunctions.length](t) : 1)); 
    }
    let xCord;
    let lowCords = [];
    chart.data.some((d, idx) => {
    let spacing = idx*xSpacing + centeriser;
        if (spacing > fullWidth * t && chart.drawChart) {
          return true;
        }
        xCord = makeXcord(chart, fullWidth, t, spacing, markerRadius);
        // Move line to to next x-coordinate:
        lineStrArray.push((idx > 0 || makeArea ? 'L' : 'M') + xCord);
        // And y-cordinate:
        let yCord = (chartHeight+chartHeightOffset) - d.value * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[idx % chart.timingFunctions.length](t) : 1);
        lineStrArray.push(yCord);
        if (isRange) {
          let yCordLow = (chartHeight+chartHeightOffset) - d.valueLow * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[idx % chart.timingFunctions.length](t) : 1);
          lowCords.unshift({xCord, yCordLow});
        }
    });
    if (makeArea) {
      if (isRange) {
        lowCords.forEach((d) => {
          lineStrArray.push('L' + d.xCord);
          lineStrArray.push(d.yCordLow);
        });
        // lineStrArray.push('L' + makeXcord(chart, fullWidth, t, xSpacing + centeriser, markerRadius));
        // lineStrArray.push(d.yCordLow);
      } else {
        lineStrArray.push('L' + xCord);
        lineStrArray.push(chartHeight + chartHeightOffset);
      }
      lineStrArray.push('Z');
    }
    return {
      path: lineStrArray.join(' '),
      width: xCord + markerRadius,
      maxScroll: fullWidth - xSpacing + markerRadius
    };
  }
function makeLineOrAreaChartPath(chart, width, t, maxValue, chartHeight, chartHeightOffset, markerRadius, pointsOnScreen, makeArea, isRange) {
    let heightScaler = (chartHeight-markerRadius)/maxValue;
    let xSpacing = width / pointsOnScreen;
    let centeriser = xSpacing / 2 - markerRadius;
    let fullWidth = xSpacing*(chart.data.length-1) + markerRadius + centeriser;

    let lineStrArray = makeArea && !isRange ? ['M' + markerRadius, chartHeight+chartHeightOffset] : [];
    if (isRange) {
      lineStrArray.push('M');
      lineStrArray.push(makeXcord(chart, fullWidth, t, centeriser, markerRadius));
      lineStrArray.push((chartHeight+chartHeightOffset) - chart.data[0].value * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[0 % chart.timingFunctions.length](t) : 1)); 
    }
    let xCord;
    let lowCords = [];
    chart.data.some((d, idx) => {
    let spacing = idx*xSpacing + centeriser;
        if (spacing > fullWidth * t && chart.drawChart) {
          return true;
        }
        xCord = makeXcord(chart, fullWidth, t, spacing, markerRadius);
        // Move line to to next x-coordinate:
        lineStrArray.push((idx > 0 || makeArea ? 'L' : 'M') + xCord);
        // And y-cordinate:
        let yCord = (chartHeight+chartHeightOffset) - d.value * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[idx % chart.timingFunctions.length](t) : 1);
        lineStrArray.push(yCord);
        if (isRange) {
          let yCordLow = (chartHeight+chartHeightOffset) - d.valueLow * heightScaler  * (chart.timingFunctions ? chart.timingFunctions[idx % chart.timingFunctions.length](t) : 1);
          lowCords.unshift({xCord, yCordLow});
        }
    });
    if (makeArea) {
      if (isRange) {
        lowCords.forEach((d) => {
          lineStrArray.push('L' + d.xCord);
          lineStrArray.push(d.yCordLow);
        });
        // lineStrArray.push('L' + makeXcord(chart, fullWidth, t, xSpacing + centeriser, markerRadius));
        // lineStrArray.push(d.yCordLow);
      } else {
        lineStrArray.push('L' + xCord);
        lineStrArray.push(chartHeight + chartHeightOffset);
      }
      lineStrArray.push('Z');
    }
    return {
      path: lineStrArray.join(' '),
      width: xCord + markerRadius,
      maxScroll: fullWidth - xSpacing + markerRadius
    };
  }
function makeLineOrAreaChartPath ( chart , width , t , maxValue , chartHeight , chartHeightOffset , markerRadius , pointsOnScreen , makeArea , isRange ) { let heightScaler = ( chartHeight - markerRadius ) / maxValue ; let xSpacing = width / pointsOnScreen ; let centeriser = xSpacing / 2 - markerRadius ; let fullWidth = xSpacing * ( chart . data . length - 1 ) + markerRadius + centeriser ; let lineStrArray = makeArea && ! isRange ? [ 'M' + markerRadius , chartHeight + chartHeightOffset ] : [ ] ; if ( isRange ) { lineStrArray . push ( 'M' ) ; lineStrArray . push ( makeXcord ( chart , fullWidth , t , centeriser , markerRadius ) ) ; lineStrArray . push ( ( chartHeight + chartHeightOffset ) - chart . data [ 0 ] . value * heightScaler * ( chart . timingFunctions ? chart . timingFunctions [ 0 % chart . timingFunctions . length ] ( t ) : 1 ) ) ; } let xCord ; let lowCords = [ ] ; chart . data . some ( ( d , idx ) => { let spacing = idx * xSpacing + centeriser ; if ( spacing > fullWidth * t && chart . drawChart ) { return true ; } xCord = makeXcord ( chart , fullWidth , t , spacing , markerRadius ) ; // Move line to to next x-coordinate: lineStrArray . push ( ( idx > 0 || makeArea ? 'L' : 'M' ) + xCord ) ; // And y-cordinate: let yCord = ( chartHeight + chartHeightOffset ) - d . value * heightScaler * ( chart . timingFunctions ? chart . timingFunctions [ idx % chart . timingFunctions . length ] ( t ) : 1 ) ; lineStrArray . push ( yCord ) ; if ( isRange ) { let yCordLow = ( chartHeight + chartHeightOffset ) - d . valueLow * heightScaler * ( chart . timingFunctions ? chart . timingFunctions [ idx % chart . timingFunctions . length ] ( t ) : 1 ) ; lowCords . unshift ( { xCord , yCordLow } ) ; } } ) ; if ( makeArea ) { if ( isRange ) { lowCords . forEach ( ( d ) => { lineStrArray . push ( 'L' + d . xCord ) ; lineStrArray . push ( d . yCordLow ) ; } ) ; // lineStrArray.push('L' + makeXcord(chart, fullWidth, t, xSpacing + centeriser, markerRadius)); // lineStrArray.push(d.yCordLow); } else { lineStrArray . push ( 'L' + xCord ) ; lineStrArray . push ( chartHeight + chartHeightOffset ) ; } lineStrArray . push ( 'Z' ) ; } return { path : lineStrArray . join ( ' ' ) , width : xCord + markerRadius , maxScroll : fullWidth - xSpacing + markerRadius } ; }
Generate the SVG path for a line or area chart.

@param  {object}  chart             The chart object
@param  {number}  width             Width of the chart in pixels
@param  {number}  t                 Scale parameter (range: 0-1), used for
animating the graph
@param  {number}  maxValue          The maximum value of chart data
@param  {number}  chartHeight       Height of the chart in pixels
@param  {number}  chartHeightOffset By how much to offset the chart height.
Note: The negation of this number is as
the marginTop for the component.
This is done so when the graph is
animated, overflow is not cut off.
@param  {number}  markerRadius      Radius of the markers on the line (needed here so we can add it to the width of the chart element, maybe change name to something better such as padding!!!!)
@param  {number}  pointsOnScreen    The number of points to show on the screen
without having to scroll. Used to calculate
the horizontal spacing between points. (maybe find better name????)
@param  {boolean} makeArea          Wether to close the line (make it an
area chart) or not.
Generate the SVG path for a line or area chart .