2016-10-05 2 views
1

В минимальном примере ниже кисть используется для выбора кругов (присвоение им класса selected), а затем опустошение в конце. Без события start выбор увеличивается с каждым действием кисти, как ожидалось. Однако добавляется функция brushstart(), чтобы очистить в начале каждого действия кисти, если не нажата клавиша ctrl. Так или иначе, это заканчивается тем, что уничтожает выбор, который происходит позже во время события brush. Вы можете видеть, что круги выбираются с изменением цвета во время чистки, но когда мышь отпущена, все они становятся недоступными.Почему событие запуска кисти D3 мешает более поздним событиям кисти?

Как это исправить? Что действительно меня озадачивает, так это то, как brushstart() может отменить выбор, сделанный brushmove().

'use strict' 
 
var random = d3.randomUniform(0.1, 0.9), 
 
    points = d3.range(50).map(function() { 
 
    return [random(), random()] 
 
    }); 
 

 
var svg = d3.select("svg"), 
 
    width = +svg.attr("width"), 
 
    height = +svg.attr("height"); 
 

 
var x = d3.scaleLinear() 
 
    .domain([0, 1]) 
 
    .range([0, width]), 
 
    y = d3.scaleLinear() 
 
    .domain([0, 1]) 
 
    .range([height, 0]); 
 

 
var brush = d3.brush() 
 
    .on('start', brushstart) 
 
    .on('brush', brushmove) 
 
    .on("end", brushended); 
 

 
var circles = svg.selectAll("circle") 
 
    .data(points) 
 
    .enter().append("circle") 
 
    .attr("cx", function(d) { 
 
    return x(d[0]); 
 
    }) 
 
    .attr("cy", function(d) { 
 
    return y(d[1]); 
 
    }) 
 
    .attr("r", 2.5) 
 
    .attr("fill", 'steelblue'); 
 

 
svg.append("g") 
 
    .attr("class", "brush") 
 
    .call(brush); 
 

 
function brushstart() { 
 
    // works as expected w/o the following line 
 
    if (!d3.event.ctrlKey) { 
 
    circles.classed('selected', false) 
 
    } 
 
} 
 

 
function brushmove() { 
 
    var s = d3.event.selection; 
 
    if (s) { 
 
    var newlySelected = circles.filter(function(d) { 
 
     return s[0][0] <= x(d[0]) && x(d[0]) <= s[1][0] && 
 
     s[0][1] <= y(d[1]) && y(d[1]) <= s[1][1]; 
 
    }); 
 
    newlySelected.classed('selected', true); 
 
    } 
 
} 
 

 
function brushended() { 
 
    var s = d3.event.selection; 
 
    if (s) { 
 
    svg.select(".brush").call(brush.move, null); 
 
    } 
 
}
.selected { 
 
    fill: crimson 
 
}
<svg width="300" height="300"></svg> 
 
<script src="https://d3js.org/d3.v4.min.js"></script>

ответ

1

brushstart вызывается из brushend:

if (s) { 
    svg.select(".brush").call(brush.move, null); 
    } 

Может быть, вы могли бы проверить выбор в brushstart:

function brushstart() { 
    // works as expected w/o the following line 
    if (!d3.event.ctrlKey && d3.event.selection) { 
    circles.classed('selected', false) 
    } 
} 
+0

Большое спасибо. Ваше предложение решает указанную проблему, но проверка ключа также должна быть изменена на '! D3.event.sourceEvent.ctrlKey', чтобы это работало по назначению. Последняя была моей ошибкой. – bongbang

Смежные вопросы