2017-02-11 15 views
2

建立在這個問題上:Access subkeys in multi-dimensional javascript objectd3.js使用.filter()從多個圖表上相應的x軸點返回數據

使用d3.js/dc.js,我有三個(或更多)圖表。所有圖表都具有相同的x軸(日期序列),因此任何圖表上的第n個數據點將完全對應於其他圖表的x軸上的第n個數據點。

當用戶點擊一個圖表中的一個點時,我需要從其他兩個圖表上的同一點獲取「y」數據,並返回一個數組或對象或字符串與chartID/y-datum從其他圖表,這樣的事情:

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

下面是赫拉爾多·費塔朵的回答上面提及的問題借一個例子。我將如何修改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]); 
 
\t 
 
var circles = svg.selectAll("foo") 
 
\t .data(data) 
 
\t .enter() 
 
\t .append("circle"); 
 
\t 
 
circles.attr("r", 10) 
 
\t .attr("fill", "teal") 
 
\t .attr("cx", d=>xScale(d.x)) 
 
\t .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(){ 
 
\t 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>

回答

3

當你有幾個不同的數據集,我將修改我在你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>

+0

非常感謝,赫拉爾多。再次感謝一個優秀的演示。 – crashwap

+0

不用擔心。那是你要的嗎?我看到你現在正在爲此掙扎一段時間...... –