Digital Deception Digital Deception - 1 year ago 108
AngularJS Question

Dart D3 line using Package JS

We want to call D3 (v4) line functions directly (among others) from Dart, as we're trying to use it with Angular 2. We've tried various things such as

  • Dart D3 library ( but it doesn't expose the SVG Line.

  • Direct JS Interop

    var line = context['d3']['svg'].callMethod('line').callMethod('x', [new JsFunction.withThis((jsThis) {
    return 10;
    })]).callMethod('y', [new JsFunction.withThis((jsThis) {
    return 20;
    line.apply(['{x:10, y:50}']);

But this explodes and is very ugly.

  • Using Js.dart

    library d3;

    import 'dart:html';

    import "package:func/func.dart";
    import "package:js/js.dart";

    class Line {
    external Line();
    external String (var data);
    external Line x(Function func);
    external Line y(Function func);

    This seems to work mostly alright, except D3 requires you to call the original function with the data in order to generate the path. E.g., you need the following:

    var line = d3.line().x(function (d) { return d.x;}).y(function (d) { return d.y;});
    line([{x:10, y:20}]);

So we got to:

Line line = new Line();
line.x(allowInterop((blah) { return 10;}));
line.y(allowInterop((blah) { return 10;}));
line.apply([[10, 20]]); //What goes here?

  • I've also tried this answer: Dart js interop with D3

    var d3 = context['d3'];
    var line = d3.line().x((jsThis) { return 20;}).y((jsThis) { return 20;});
    return line([[10, 20]]);

What is the recommended way of doing this? Also, do you have any guides for using Angular 2 + D3 + Dart? I've only seen type-script, and translating between them is not the easiest thing in the world.

Answer Source

I managed to get this working using Js.dart. The important part is to have a call function. This allows you to call the function directly to get your result, as D3 does.

The Dart wrapper:

library d3;

import 'dart:js';
import "package:js/js.dart";

typedef num D3AccessorFunction(List<num> d, num i, List<List<num>> data);
Function d3AccessorFunction(D3AccessorFunction function) {
  return allowInterop(function);
class Line {
  external Line();
  external String call (List<List<num>> data);
  external Line x(D3AccessorFunction function);
  external Line y(D3AccessorFunction function);

class Arc {
  external innerRadius([num innerRadius]);
  external outerRadius([num outerRadius]);
  external startAngle([num startAngleInRadians]);
  external endAngle([num endAngleInRadians]);
  external Arc();
  external String call ();

The function:

Line line = new Line();
return line([[fromTo.x, fromTo.y], [endTo.x, endTo.y]]);