d3.js:限制画刷的大小

6
有没有办法限制画笔的大小,即使它的范围更大?
我创建了一个只有x轴可以移动和调整大小的画笔。我想能够限制用户调整大小的范围(基本上只能到一定程度)。
在下面的示例中,当画笔变得比最大范围的一半还要大时,画笔功能停止更新。但是,画笔本身仍然可以扩展。有没有办法防止这种情况发生?或者有没有更好的处理方法?
非常感谢!
在此处查看此代码的演示:http://bl.ocks.org/3691274编辑:此演示现已可用)
bar = function(range) {

      var x_range = d3.scale.linear()
          .domain([0, range.length])
          .range([0, width]); 

      svg.selectAll("rect.items").remove();

      svg.selectAll("rect.items")
          .data(range)
        .enter().append("svg:rect")
          .attr("class", "items")
          .attr("x", function(d, i) {return x_range(i);})
          .attr("y", 0)
          .attr("width",  width/range.length-2)
          .attr("height", 100)
          .attr("fill", function(d) {return d})
          .attr("title", function(d) {return d});
}

var start = 21;
bar(data.slice(0, start), true);

var control_x_range = d3.scale.linear()
    .domain([0, data.length])
    .range([0, width]); 

controlBar = svg.selectAll("rect.itemsControl")
    .data(data)
  .enter().append("svg:rect")
    .attr("class", "itemsControl")
    .attr("x", function(d, i) {return control_x_range(i);})
    .attr("y", 110)
    .attr("width",  width/data.length-2)
    .attr("height", 20)
    .attr("fill", function(d) {return d});

svg.append("g")
    .attr("class", "brush")
    .call(d3.svg.brush().x(d3.scale.linear().range([0, width]))
    .extent([0,1*start/data.length])
    .on("brush", brush))
  .selectAll("rect")
    .attr("y", 110)
    .attr("height", 20);

function brush() {
    var s = d3.event.target.extent();

    if (s[1]-s[0] < 0.5) {
        var start = Math.round((data.length-1)*s[0]);
        var end = Math.round((data.length-1)*s[1]);

        bar(data.slice(start,end));
    };

}

这是Bostock的一个不错的代码块,演示如何强制使用特定的画笔大小:https://bl.ocks.org/mbostock/6232537。他没有强制规定最大尺寸,但可以通过检查画笔域`d1.map(x)`来轻松添加,就像https://dev59.com/1mjWa4cB1Zd3GeqPpEYl#38736673所示。 - F Lekschas
4个回答

5

当笔刷大小超过允许的最大值时,我通过重新设置笔刷大小为其最大允许值来解决了这个问题:

function brush() {
    var s = d3.event.target.extent();
    if (s[1]-s[0] < 0.5) {
        var start = Math.round((data.length-1)*s[0]);
        var end = Math.round((data.length-1)*s[1]);

        bar(data.slice(start,end));
    }
    else {d3.event.target.extent([s[0],s[0]+0.5]); d3.event.target(d3.select(this));}
} 

演示: http://bl.ocks.org/3691274

我仍然对更好的解决方案感兴趣。


3

这里是另一种使用d3.v4和ES6的策略:

brush.on('end', () => {
    if (d3.event.selection[1] - d3.event.selection[0] > maxSelectionSize) {
        // selection is too large; animate back down to a more reasonable size
        let brushCenter = d3.event.selection[0] + 0.5 * (d3.event.selection[1] - d3.event.selection[0]);
        brushSel.transition()
            .duration(400)
        .call(brush.move, [
            brushCenter - 0.49 * maxSelectionSize,
            brushCenter + 0.49 * maxSelectionSize
        ]);
    } else {
        // valid selection, do stuff
    }
});

如果用户在释放时刷选的大小过大,它将动画返回到指定的最大大小 (maxSelectionSize)。此时,'end' 事件将再次触发,并获得可接受的选择大小。
请注意 0.49 标量:这是必需的,以防止浮点数/舍入误差,如果刷子移动到仍然太大的大小,可能会导致无限循环。

0
这是一个限制画笔最小宽度为100像素和最大宽度为200像素的示例。我在d3.v4.js中添加了几行代码,用于设置画笔宽度的限制。
添加brush.limit([min, max])以设置限制:
var _limit = null;
brush.limit = function (l) {
  _limit = l;
}

在move()函数中中断鼠标移动事件:
if (_limit && e1 - w1 < _limit[0]) {
  return;
}

(演示) (源代码)


-1
代码写得不错,但我发现了一个小错误。当s[1]-s[0] < 0.5时,它会锁定你的画笔,但如果你一直按住调整大小并将所有画笔移动到相反的方向,它就会开始“移动”画笔而没有任何操作(即它不会像应该那样行为)。
我相信我可以想出一个合理的解决方案。如果有的话,我会在这里重新发布。
(很抱歉在这里发布回答,但由于您已经回答过一次,我想我不能作为评论发布)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接