Чтобы уточнить это, скажем, у нас типичный случай использования кистей d3, что-то вроде примера здесь Майка Бостока. Кисть очищается, когда я нажимаю где-нибудь за пределами кисти. Поэтому я хочу выполнить функцию, когда это событие будет запущено. Соответствующий код довольно похож на пример Майка.
В приведенном выше примере кисть очищается как поведение по умолчанию, вызванное "end"
прослушивателем.
Идиоматическое решение D3 устанавливает "end"
прослушиватель, который проверяет, является ли d3.event.selection
null
:
brush.on("end", function() {
if(!d3.event.selection){
//your function here;
}
});
Вот демонстрационный пример с использованием кода Bostock, нажмите за пределами кисти и проверьте сообщение консоли:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--grid .domain {
fill: #ddd;
stroke: none;
}
.axis--x .domain,
.axis--grid .tick line {
stroke: #fff;
}
.axis--grid .tick--minor line {
stroke-opacity: .5;
}
</style>
<body>
<script src="/d3.v5.min.js"></script>
<script>
var margin = {
top: 50,
right: 40,
bottom: 200,
left: 40
},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scaleTime()
.domain([new Date(2013, 7, 1), new Date(2013, 7, 15) - 1])
.rangeRound([0, width]);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "axis axis--grid")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.ticks(d3.timeHour, 12)
.tickSize(-height)
.tickFormat(function() {
return null;
}))
.selectAll(".tick")
.classed("tick--minor", function(d) {
return d.getHours();
});
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.ticks(d3.timeDay)
.tickPadding(0))
.attr("text-anchor", null)
.selectAll("text")
.attr("x", 6);
svg.append("g")
.attr("class", "brush")
.call(d3.brushX()
.extent([
[0, 0],
[width, height]
])
.on("brush", brushed)
.on("end", function() {
if (!d3.event.selection) console.log("you clicked ouside the brush")
}));
function brushed() {
if (d3.event.sourceEvent.type === "brush") return;
var d0 = d3.event.selection.map(x.invert),
d1 = d0.map(d3.timeDay.round);
// If empty when rounded, use floor instead.
if (d1[0] >= d1[1]) {
d1[0] = d3.timeDay.floor(d0[0]);
d1[1] = d3.timeDay.offset(d1[0]);
}
d3.select(this).call(d3.event.target.move, d1.map(x));
}
</script>
Используя пример, который вы упомянули, вам нужно добавить обработчик кликов в оверлейный rect
и отслеживать, если есть набор кистей
svg.append("g")
.attr("class", "brush")
.call(d3.brushX()
.extent([[0, 0], [width, height]])
.on("brush", brushed))
.selectAll(".overlay")
.on("mousedown touchstart", brushOverlay);
var brushSet = false;
function brushed() {
if (d3.event.sourceEvent.type === "brush") return;
var d0 = d3.event.selection.map(x.invert),
d1 = d0.map(d3.timeDay.round);
// If empty when rounded, use floor instead.
if (d1[0] >= d1[1]) {
d1[0] = d3.timeDay.floor(d0[0]);
d1[1] = d3.timeDay.offset(d1[0]);
}
d3.select(this).call(d3.event.target.move, d1.map(x));
brushSet = true;
}
function brushOverlay() {
if (!brushSet) return; // create a new brush region
console.log('brush Clear');
}
Адаптация от https://bl.ocks.org/mbostock/6498580