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));
    };

}
4

4 に答える 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

私はまだより良い解決策を読むことに興味があります。

于 2012-09-17T08:53:51.397 に答える
3

ES6 で d3.v4 を使用する別の戦略を次に示します。

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場合に無限ループを引き起こす可能性がある浮動小数点/丸めエラーを防ぐために必要です。move()

于 2016-08-03T07:07:54.637 に答える
-1

素敵なコードですが、小さなバグを見つけました。いつでもブラシをロックしますs[1]-s[0] < 0.5が、サイズ変更を押し続けてすべてのブラシを反対方向に持ってくると、アクションなしでブラシを「移動」し始めます(つまり、本来の動作をしません)。

合理的な解決策を思いつくことができると確信しています。もしそうなら、私はそれをここに再投稿します。

(回答としてここに投稿して申し訳ありませんが、すでに一度回答しているため、コメントとして投稿することはできません)。

于 2013-05-29T21:55:49.450 に答える