I want to implement multi-brushing functionality using D3 in a Vue3 application. Minimal examples using vanilla JS and D3 are available here and here.
Brushing functionality is correctly implemented by creating a computed variables (newBrush) and calling it in the onMounted() lifecycle hook. A minimal example is available here:
https://stackblitz.com/github/ajmoralesa/multiBrushD3Vue?embed=1
The template contains:
<template>
<div>
<svg :height="height" :width="width">
<g>
<rect :width="width" :height="height" class="rect"></rect>
<g ref="gBrushes"></g>
</g>
</svg>
</div>
</template>
And the script:
<script setup>
import { computed } from "@vue/reactivity";
import { onMounted, reactive, ref } from "vue";
import * as d3 from "d3";
const margin = reactive({
top: 10,
right: 10,
bottom: 10,
left: 10,
});
const width = 960 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
const gBrushes = ref();
// Keep the actual d3-brush functions and their IDs in a list:
const brushes = ref([]);
onMounted(() => {
d3.select(gBrushes.value).call(newBrush.value);
});
const newBrush = computed(() => {
var brush = d3.brush().on("end", brushend);
function brushend() {
brushes.value.push({ id: brushes.value.length, brush: brush });
// // Figure out if our latest brush has a selection
// var lastBrushID = brushes.value[brushes.value.length - 1].id;
// var lastBrush = document.getElementById("brush-" + lastBrushID);
// console.log("lastBrush:", lastBrush);
// var selection = d3.brushSelection(lastBrush);
// // If it does, that means we need another one
// if (selection && selection[0] !== selection[1]) {
// newBrush();
// }
// Always draw brushes
drawBrushes();
}
return brush;
});
function drawBrushes() {
console.log("hey there!");
var brushSelection = d3
.select(gBrushes.value)
.selectAll(".brush")
.data(brushes.value, function (d) {
return d.id;
});
// Set up new brushes
brushSelection
.enter()
.insert("g", ".brush")
.attr("class", "brush")
.attr("id", function (brush) {
return "brush-" + brush.id;
})
.each(function (brushObject) {
//call the brush
d3.select(this).call(d3.brush(brushObject));
});
brushSelection.each(function (brushObject) {
d3.select(this)
.attr("class", "brush")
.selectAll(".overlay")
.style("pointer-events", function () {
var brush = brushObject.brush;
if (
brushObject.id === brushes.value.length - 1 &&
brush !== undefined
) {
return "all";
} else {
return "none";
}
});
});
brushSelection.exit().remove();
}
</script>
What is wrong in the drawBrushes() function ?
Code: https://stackblitz.com/github/ajmoralesa/multiBrushD3Vue