javascript - 在d3.js中使用.filter()返回多个图表上对应x轴点的数据

标签 javascript d3.js dc.js

此问题构建 on this question .

使用 d3.js/dc.js,我有三个(或更多)图表。所有图表都具有相同的 x 轴(日期系列),因此任何图表上的第 n 个数据点都将与其他图表的 x 轴上的第 n 个数据点完全对应。

当用户单击一个图表中的点时,我需要从其他 2 个以上图表上的同一点获取“y”数据,并返回带有图表 ID/y 数据的数组、对象或字符串其他图表,如下所示:

{"chart1":"30","chart2":"50","chart3":"10"}

以下示例借自 Gerardo Furtado 对上述问题的回答。我如何修改 Gerardo 的示例以返回每个图表中的数据点?

var data = [{x:20, y:30},
{x:30, y:60},
{x:40, y:40},
{x:50, y:90},
{x:60, y:20},
{x:70, y:90},
{x:80, y:90},
{x:90, y:10}];

draw("#svg1");
draw("#svg2");
draw("#svg3");


function draw(selector){

var width = 250,
    height = 250;

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

var xScale = d3.scaleLinear()
    .domain([0, 100])
    .range([30, width - 10]);

var yScale = d3.scaleLinear()
    .domain([0,100])
    .range([height - 30, 10]);
	
var circles = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("circle");
	
circles.attr("r", 10)
	.attr("fill", "teal")
	.attr("cx", d=>xScale(d.x))
	.attr("cy", d=>yScale(d.y));

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

svg.append("g").attr("transform", "translate(0,220)")
    .attr("class", "xAxis")
    .call(xAxis);

svg.append("g")
    .attr("transform", "translate(30,0)")
    .attr("class", "yAxis")
    .call(yAxis);

}

d3.selectAll("circle").on("mouseover", function(){
var thisDatum = d3.select(this).datum();
  d3.selectAll("circle").filter(d=>d.x == thisDatum.x && d.y == thisDatum.y).attr("fill", "firebrick");
}).on("mouseout", function(){
	d3.selectAll("circle").attr("fill", "teal")
})
#svg1 {
  float: left;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="svg1"></div>
<div id="svg2"></div>
<div id="svg3"></div>

最佳答案

由于您有几个不同的数据集,我将修改我在您的 previous question 中写的答案所以我们可以有不同的 y 值。

首先,不要将所有数据放入一个对象中。这样,我们以后就可以访问不同的数据集:

var dataObject = {
    data1: [{
        x: 10,
        y: 30
    }, ...
    }],
    data2: [{
        x: 10,
        y: 70
    }, ...
    }],
    data3: [{
        x: 10,
        y: 10
    }, ...
    }]
};

然后,我们调用绘制函数:

draw("#svg1", dataObject.data1);
draw("#svg2", dataObject.data2);
draw("#svg3", dataObject.data3);

因此,要获得您想要的内容,请在鼠标悬停时...

d3.selectAll("circle").on("mouseover", function() {
    var thisDatum = d3.select(this).datum();
    findPoints(thisDatum);
})

我们称这个函数为:

function findPoints(datum) {
    var myObject = {};
    for (var i = 1; i < 4; i++) {
        myObject["chart" + i] = dataObject["data" + i].filter(e => e.x === datum.x)[0].y;
    }
    console.log(myObject)//use return instead of console.log
}

这是演示:

var dataObject = {
    data1: [{
        x: 10,
        y: 30
    }, {
        x: 20,
        y: 60
    }, {
        x: 30,
        y: 40
    }, {
        x: 40,
        y: 90
    }, {
        x: 50,
        y: 20
    }, {
        x: 60,
        y: 90
    }, {
        x: 70,
        y: 90
    }, {
        x: 80,
        y: 10
    }],
    data2: [{
        x: 10,
        y: 70
    }, {
        x: 20,
        y: 60
    }, {
        x: 30,
        y: 80
    }, {
        x: 40,
        y: 10
    }, {
        x: 50,
        y: 10
    }, {
        x: 60,
        y: 20
    }, {
        x: 70,
        y: 10
    }, {
        x: 80,
        y: 90
    }],
    data3: [{
        x: 10,
        y: 10
    }, {
        x: 20,
        y: 20
    }, {
        x: 30,
        y: 40
    }, {
        x: 40,
        y: 90
    }, {
        x: 50,
        y: 80
    }, {
        x: 60,
        y: 70
    }, {
        x: 70,
        y: 50
    }, {
        x: 80,
        y: 50
    }]
};


draw("#svg1", dataObject.data1);
draw("#svg2", dataObject.data2);
draw("#svg3", dataObject.data3);


function draw(selector, data) {

    var width = 200,
        height = 100;

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

    var xScale = d3.scaleLinear()
        .domain([0, 100])
        .range([30, width - 10]);

    var yScale = d3.scaleLinear()
        .domain([0, 100])
        .range([height - 30, 10]);

    var circles = svg.selectAll("foo")
        .data(data)
        .enter()
        .append("circle");

    circles.attr("r", 5)
        .attr("fill", "palegreen")
        .attr("cx", d => xScale(d.x))
        .attr("cy", d => yScale(d.y));

    var xAxis = d3.axisBottom(xScale);
    var yAxis = d3.axisLeft(yScale).ticks(2);

    svg.append("g").attr("transform", "translate(0,70)")
        .attr("class", "xAxis")
        .call(xAxis);

    svg.append("g")
        .attr("transform", "translate(30,0)")
        .attr("class", "yAxis")
        .call(yAxis);

}

d3.selectAll("circle").on("mouseover", function() {
    var thisDatum = d3.select(this).datum();
    findPoints(thisDatum);
    d3.selectAll("circle").filter(d => d.x == thisDatum.x).attr("fill", "firebrick");
}).on("mouseout", function() {
    d3.selectAll("circle").attr("fill", "palegreen")
})

function findPoints(datum) {
    var myObject = {};
    for (var i = 1; i < 4; i++) {
        myObject["chart" + i] = dataObject["data" + i].filter(e => e.x === datum.x)[0].y;
    }
    console.log(JSON.stringify(myObject))
}
#svg1, #svg2 {
  float: left;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="svg1"></div>
<div id="svg2"></div>
<div id="svg3"></div>

关于javascript - 在d3.js中使用.filter()返回多个图表上对应x轴点的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42178349/

相关文章:

javascript - D3js v5 是否向后兼容 v4?

javascript - d3.js 使用 ISO-8859-1 编码加载 csv 文件

angularjs - dc.js x轴序数图问题

javascript - 使用两组的 dc.js 箱形图缩减器

javascript - 通过正则表达式分割(孟加拉语)字符串而不使用分隔符,零宽度前向查找不起作用

javascript - 仅加载图像动画一次

javascript - 有没有办法在 google-cloud-firestore 的对象数组中搜索具有特定字段的对象

javascript - 是什么让网格线可见?

javascript - 当 require.js 存在时,如何成功加载 dimple.js?

dc.js - 为 dc.js 散点图分配颜色会干扰图表中的选择