gonewandering / angles

An angular.js wrapper for Chart.js
MIT License
632 stars 87 forks source link

Guidelines to add new charts #71

Open sebastialonso opened 9 years ago

sebastialonso commented 9 years ago

I have a couple of custom charts I'd like to use with the wrapper. I think is also easier adding the custom charts to the wrapper than the original Chart.js library. As seen on #55 and #61, there's a need for guidelines for the community for adding new types of chart and their correspondent directives. @gonewandering, if you have no problem with adding charts to the wrapper, would like to hear what you think about coding styles or anything related. I'd be glad to send PR with some new directives.

sebastialonso commented 9 years ago

As an example for everyone looking to extend angles as I was, I'm using an horizontal line to denote today in the chart

selection_013

I borrowed potatopeelings' code for this.

All I did was to create an extra-charts.js file in my components folder with the definition of the extended chart

# Notice now we're extending the particular Line chart type, rather than the base class.
Chart.types.Line.extend
  name: 'LineAlt'
  initialize: (data) ->
    Chart.types.Line::initialize.apply this, arguments
    return
  draw: ->
    Chart.types.Line::draw.apply this, arguments
    if @options.lineAtIndex != undefined or @options.lineAtIndex < 0
      point = @datasets[0].points[@options.lineAtIndex]
      scale = @scale
      # draw line
      @chart.ctx.beginPath()
      @chart.ctx.moveTo point.x, scale.startPoint + 24
      @chart.ctx.strokeStyle = @options.lineColor
      @chart.ctx.lineTo point.x, scale.endPoint
      @chart.ctx.stroke()
      # write TODAY
      @chart.ctx.textAlign = 'center'  
      @chart.ctx.fillText @options.text, point.x, scale.startPoint + 12
      return

Notice how @options.text, @options.lineColor and @options.lineAtIndex are custom variables for the line I defined in my controller. This extension just draws a regular Line Chart if you fail to supply lineAtIndex the option or if it's a negative number (return of indexOf if fails to find something ;) )

Then I monkey-patched angles.js to add an extra directive

/* Aliases for various chart types */
angles.directive("chart", function () { return angles.chart(); });
angles.directive("linechart", function () { return angles.chart("Line"); });
// New one
angles.directive("extendedchart", function () { return angles.chart("LineAlt"); }); 
angles.directive("barchart", function () { return angles.chart("Bar"); });
angles.directive("radarchart", function () { return angles.chart("Radar"); });
//...

And that's it. In the view you go

<canvas extendedchart options="myChartOptions" data="global_views" width="900" height="300"></canvas>

and you get the image above.

Good news

Monkey-patching was minimal, merely to add a directive. Nothing of the original code was changed. That's always good.

Bad news

It feet dirty monkey-patching angles.js and this time I was lucky since it wasn't minified. If at some point in the future it's decided to minify the source, this solution becomes obsolete.

So I'd propose a different file for extensions and new charts and also the custom directive for it, community_extensions.jsor something like that.