d3.js使用.filter()从多个图表上的相应x轴点返回数据

时间:2017-02-11 16:34:20

标签: javascript d3.js dc.js

在此问题的基础上:Access subkeys in multi-dimensional javascript object

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

当用户点击一个图表中的点点时,我需要从其他2个图表上的同一点获取“y”数据,并返回一个数组或对象或字符串,其中包含来自的图表ID / y-datum其他图表,如下:

<p>Andrew Anglin<br/>
<strong>Daily Stormer</strong><br/>
February 11, 2017</p>

这是一个借鉴Gerardo Furtado对上述问题的回答的例子。我如何修改Gerardo的示例以从每个图表返回数据点?

February 11, 2017
{"chart1":"30","chart2":"50","chart3":"10"}
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")
})

1 个答案:

答案 0 :(得分:3)

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

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

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

然后,我们调用draw函数:

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
}

以下是演示:

&#13;
&#13;
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))
}
&#13;
#svg1, #svg2 {
  float: left;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="svg1"></div>
<div id="svg2"></div>
<div id="svg3"></div>
&#13;
&#13;
&#13;