#javascript #d3.js
Вопрос:
Я пытаюсь создать диаграмму фокуса контекста с диаграммой рассеяния, используя самую последнюю версию D3 (версия 7). Мне также нужно решение в ванильном javascript, а не импортировать наблюдаемые библиотеки.
Этот пример делает то, что я хочу, за исключением участка области, а функции экспорта не предоставляют простой javascript.
Я пытаюсь собрать код из многих прошлых вопросов SO с диаграммами рассеяния и контекстом focus , но все они из очень старых версий и используют устаревшие функции.
Я могу отобразить данные на обеих диаграммах, изменить домен на верхней диаграмме и даже заставить верхнюю ось вести себя соответствующим образом при изменении xBrush на нижней диаграмме. Но я не могу сделать точки данных на верхней диаграмме реактивными. Они остаются неподвижными независимо от того, куда движется кисть!
Что я упускаю? Как обновить точки данных на верхней диаграмме?
Вот мой код:
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
#zoom-map{
width: 100%;
height: 100px;
}
.tag1{
stroke: royalblue;
}
.tatag2{
stroke: seagreen;
stroke-width: 2;
}
</style>
<body>
<section id="zoom-map">
</section>
<section id="brush-map">
</section>
</body>
<!-- Load in the d3 library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.4/d3.min.js"></script>
<script>
// 2. Use the margin convention practice
var margin = {top: 10, right: 0, bottom: 20, left: 5}
const map_width = 1000
const map_height = 100
const width = map_width - margin.left - margin.right // - (strokeWidth * 2);
const height = map_height - margin.top - margin.bottom;
// The number of minutes
var n = 20;
// 5. X scale will use the index of our data
var xZoom = d3.scaleLinear()
.domain([0, 4]) // input
.range([0, width]); // output
var xZoomAxis = d3.axisBottom(xZoom)
// Add the zoom-map SVG to the page
var svg_zoom = d3.select("#zoom-map").append("svg")
.attr("width", '100%') // margin.left margin.right)
.attr("height", '100%') // margin.top margin.bottom)
// .attr('viewbox', `0 0 ${map_width} ${map_height}`)
// .attr('preserveAspectRatio','xMinYMin')
.append("g")
.attr("transform", `translate( ${margin.left}, ${margin.top})`)
// Call the x axis in a group tag
svg_zoom.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,${height})`)
.call(xZoomAxis); // Create an axis component with d3.axisBottom
var event_data = [{frame: 1, time: 1, type: 'tag1'}, {frame: 5, time: 5, type: 'tag1'}, {frame: 7, time: 7, type: 'tag2'}, {frame: 10.4, time: 10.4, type: 'tag1'}, {frame: 14, time: 14, type: 'tag1'}, {frame: 17, time: 17, type: 'tag2'}, ]
svg_zoom.selectAll('.event')
.data(event_data)
.enter()
.append('rect')
.attr('x', function(tag){return xZoom(tag.time)})
.attr('y', 5)
.attr('width', 1)
.attr('height', 70)
.attr('class', 'event')
.attr('class', function(tag){return tag.type} )
// Create brush on x-axis
var xBrush = d3.scaleLinear()
.domain([0, n]) // input
.range([0, width]); // output
// Add the brush-map SVG to the page
var svg_brush = d3.select("#brush-map").append("svg")
.attr("width", '100%') // margin.left margin.right)
.attr("height", '100%') // margin.top margin.bottom)
// .attr('viewbox', `0 0 ${map_width} ${map_height}`)
// .attr('preserveAspectRatio','xMinYMin')
.append("g")
.attr("transform", `translate( ${margin.left}, ${margin.top})`)
// Call the x axis in a group tag
svg_brush.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(xBrush)); // Create an axis component with d3.axisBottom
// Add rectangles to the brush-map
svg_brush.selectAll('.event')
.data(event_data)
.join('rect')
.attr('x', function(tag){return xBrush(tag.time)})
.attr('y', 5)
.attr('width', 1)
.attr('height', 70)
.attr('class', 'event')
.attr('class', function(tag){return tag.type} )
function brushed({selection}) {
if (selection) {
coords = selection.map(xBrush.invert, xBrush)
xZoom.domain( coords)
svg_brush.property("value", selection.map(xBrush.invert, xBrush))
svg_brush.dispatch("input")
svg_zoom.selectAll('.event')
// .join()
.data(event_data)
.attr('x', (tag) => xZoom(tag.time))
.call(xZoom)
// .attr('x', function(event){return xZoom(event.time)})
// svg_zoom.dispatch("input")
svg_zoom.select(".x.axis") // change the x axis
.call(xZoomAxis);
}
}
const brush = d3.brushX()
.extent([[0, 0], [width, height]])
.on("brush", brushed)
const defaultSelection = [100,200] // this is pixels
const gb = svg_brush.append("g")
.call(brush)
.call(brush.move, defaultSelection);
</script>