Question

I am writing a Meteor application that will receive new data every 5 minutes or so, and add the new data to a group of charts. I am using dc.js to make the charts because I want users to be able to explore the data. I want to simplify the line using simplify.js before plotting it.

I am having a hard time figuring out where the path gets calculated in the dc.js library. The code can be found here In dc, a lineChart inheirits from coordinateGridChart. coordinateGridChart has a doRender() method (starting on line 1408):

_chart.doRender = function () {
    if (_x == null)
        throw new dc.errors.InvalidStateException("Mandatory attribute chart.x is missing on chart["
            + _chart.anchor() + "]");

    _chart.resetSvg();

    if (_chart.dataSet()) {
        _chart.generateG();

        generateClipPath();
        prepareXAxis(_chart.g());
        prepareYAxis(_chart.g());

        _chart.plotData();

        _chart.renderXAxis(_chart.g());
        _chart.renderYAxis(_chart.g());

        _chart.renderBrush(_chart.g());

        enableMouseZoom();
    }

So the plotData method seems to do the job. plotData is defined for lineChart on line 2548:

_chart.plotData = function() {
    var groups = _chart.allGroups();

    _chart.calculateDataPointMatrixForAll(groups);

    for (var groupIndex = 0; groupIndex < groups.length; ++ groupIndex) {
        var group = groups[groupIndex];
        plotDataByGroup(groupIndex, group);
    }
};

function plotDataByGroup(groupIndex, group) {
    var stackedCssClass = getStackedCssClass(groupIndex);

    var g = createGrouping(stackedCssClass, group);

    var line = drawLine(g, stackedCssClass, groupIndex);

    if (_renderArea)
        drawArea(g, stackedCssClass, groupIndex, line);

    if (_chart.renderTitle())
        drawDots(g, groupIndex);
}

function getStackedCssClass(groupIndex) {
    return dc.constants.STACK_CLASS + groupIndex;
}

function createGrouping(stackedCssClass, group) {
    var g = _chart.chartBodyG().select("g." + stackedCssClass);

    if (g.empty())
        g = _chart.chartBodyG().append("g").attr("class", stackedCssClass);

    g.datum(group.all());

    return g;
}

function drawLine(g, stackedCssClass, groupIndex) {
    var linePath = g.select("path.line");

    if (linePath.empty())
        linePath = g.append("path")
            .attr("class", "line " + stackedCssClass);

    linePath[0][0][dc.constants.GROUP_INDEX_NAME] = groupIndex;

    var line = d3.svg.line()
        .x(lineX)
        .y(function(d, dataIndex) {
            var groupIndex = this[dc.constants.GROUP_INDEX_NAME];
            return lineY(d, dataIndex, groupIndex);
        });

    dc.transition(linePath, _chart.transitionDuration(),
        function(t) {
            t.ease("linear");
        }).attr("d", line);

    return line;
}

var lineX = function(d) {
    return _chart.margins().left + _chart.x()(_chart.keyAccessor()(d));
};

var lineY = function(d, dataIndex, groupIndex) {
    var y = _chart.getChartStack().getDataPoint(groupIndex, dataIndex);
    if(y >= _chart.dataPointBaseline())
        y += _chart.dataPointHeight(d, groupIndex);
    return y;
};

So, is the path getting added where .attr("d", line) appears? When I console.log the line, it is a group of functions. The "d" attribute of the path is the svg line information, so it is a string that looks like "M100,50L100,55,L101,75" and so on. I can't find where this string is being constructed in the source code. I want to intervene at this step to simplify the line before adding the path element to the svg element.

Anyone familiar enough with dc.js to help me out? Thanks in advance.

Was it helpful?

Solution

var line = d3.svg.line()
        .x(lineX)
        .y(function(d, dataIndex) {
            var groupIndex = this[dc.constants.GROUP_INDEX_NAME];
            return lineY(d, dataIndex, groupIndex);
        });

line path is generated by this standard d3 line generator function. Though the difficulty of using simplify.js is that d3 line generator generates svg:path d attribute directly instead of point vector so you probably will have to implement a custom line generator in order to use simplify.js in this case. However d3.svg.line does generate point vector as an intermediat

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top