dc.js disable brush resizing

喜你入骨 提交于 2020-03-03 10:06:05

问题


I am trying to disable brush extent on a line chart and set a fixed width.

I am aware this subject has been discussed several times. I have tried without success to work on this answer: Disable brush resize (DC.js, D3.js) but I couldn't find a solution matching my situation.

If it makes any difference, I am expanding on the brushable ordinal chart discussed in this question: DC.js - Custom ordering of ordinal scale line chart

Here is the chart initialization code:

    line
        .width(950)
        .height(350)
        .margins({top: 10, right: 50, bottom: 35, left: 30})
        .dimension(graphDim)            
        .keyAccessor(function(kv) { return  graphGroup.ord2int(kv.key); })
        .group(graphGroup)
        .x(d3.scaleLinear().domain(linear_domain))
        .xAxisLabel("Chronologie")
        .yAxisLabel("Effectif")
        .brushOn(true)
        .renderArea(true)
        .renderHorizontalGridLines(true)
        .renderVerticalGridLines(true)
        .elasticY(true)
        .filter(dc.filters.RangedFilter(0,0.9));

    line.yAxis().ticks(4);

    line.xAxis()
        .tickValues(d3.range(data.length))
        .tickFormat(function(d) { return graphGroup.int2ord(d); });

    line.filterHandler(function(dimension, filters) {
        if(!filters || !filters.length) {
            dimension.filter(null);
            return filters;
        }
        console.assert(filters.length === 1);
        console.assert(filters[0].filterType === 'RangedFilter');
        var inside = graphGroup.all().filter(function(kv) {
            var i = graphGroup.ord2int(kv.key);
            return filters[0][0] <= i && i < filters[0][1];
        }).map(function(kv) { return kv.key; });
        dimension.filterFunction(function(d) {
            return inside.indexOf(d) >= 0;
        });
        return filters;
    })

And the fiddle: https://jsfiddle.net/bob_magnus_1/sr7hmnvf/9/`

Is there a simple way to override coordinateGridMixin.extendBrush function in such a chart?


回答1:


The previous question was for DCv2. Fixed-width brushes are even easier in DCv3+ (because of improvements to d3-brush in D3v4).

It's the same technique as before: look at how extendBrush is implemented, and then replace it. Here's how it looks in DCv3:

_chart.extendBrush = function (brushSelection) {
    if (brushSelection && _chart.round()) {
        brushSelection[0] = _chart.round()(brushSelection[0]);
        brushSelection[1] = _chart.round()(brushSelection[1]);
    }
    return brushSelection;
};

(source)

It takes a selection – an array of two elements – and returns a new selection.

In your case, your data is ordinal but the scale is linear in order to enable brushing. The brush should match the scale.

To keep it at 0.9 width:

line.extendBrush = function(brushSelection) {
  brushSelection[1] = brushSelection[0] + 0.9;
  return brushSelection;
};

Hiding the brush handles (which have weird behavior) with CSS:

.brush .custom-brush-handle {
  display: none;
} 

Fork of your fiddle.

Ordinal brush with snapping

I realized (looking at your 0.9 width brush) that you probably want proper ordinal brushing where it snaps to the region around the one selected point.

You can do this by setting the begin and end of the selection:

line.extendBrush = function(brushSelection) {
  brushSelection[0] = Math.round(brushSelection[0]) - 0.5;
  brushSelection[1] = brushSelection[0] + 1;
  return brushSelection;
};

We find the the currently hovered point by rounding, and then set the begin to 0.5 before it, and the end to 0.5 after it.

Initialize the filter to surround the zero point:

line
  .filter(dc.filters.RangedFilter(-0.5,0.5));

Revised fiddle.

Floating point bug fix

I noticed that if you select 20/30 above (linear value 3), brushSelection[0] will have changed from 2.5 to 2.49999999, causing the brush to jump back by one. Some numbers don't represent correctly in floating point.

It's safer to use the average of begin and end:

    line.extendBrush = function(brushSelection) {
      const point = Math.round((brushSelection[0] + brushSelection[1])/2);
      return [
        point - 0.5,
        point + 0.5
      ];
    };

Fiddle version with 20/30 selectable.



来源:https://stackoverflow.com/questions/59499903/dc-js-disable-brush-resizing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!