2017-06-29 45 views
0

我在同一个网页中制作了散点图和等值线图。数据存储在.CSV.json中,并且元素与“名称”字段链接。D3 - 在不同的选择DIV

我已经提出了两个鼠标悬停的工具提示。我现在想要在它们之间产生一些交互性:当鼠标在散点图上的某个元素上时,该散点图上的这个元素会作出反应,并且当鼠标移过散点图时,散点图会作出反应。

散点图和choropleth在不同div与具体ID我不怎么能从一个到另一个。我试过d3.select("this#scatterplot");,比如this example,但它对我不起作用。

如何选择不同的元素DIV和不同的functions

我想是这样的:

function handleMouseOverMap(d, i) {    
      d3.select('this#choropleth').style('stroke-width', 3); 
      d3.select('this#scatterplot').attr('r', 8); 
} 
function handleMouseOverGraph(d, i) {    
     d3.select('this#scatterplot').attr('r', 8); 
     d3.select('this#choropleth').style('stroke-width', 3); 
} 

代码

<div id="scatterplot"></div> 
<div id="choropleth"></div> 
<script> 
d3.queue() 
.defer(d3.csv, 'data.csv', function (d) { 
    return {  
     name: d.name, 
     sau: +d.sau, 
     uta: +d.uta 
    } 
}) 
.defer(d3.json, 'dept.json') 
.awaitAll(initialize) 

var color = d3.scaleThreshold() 
.domain([150000, 300000, 450000]) 
.range(['#5cc567', '#e7dc2b', '#e59231', '#cb0000']) 

function initialize(error, results) { 
if (error) { throw error } 

var data = results[0] 
var features = results[1].features 

var components = [ 
    choropleth(features), 
    scatterplot(onBrush) 
] 

function update() { 
    components.forEach(function (component) { component(data) }) 
} 

function onBrush(x0, x1, y0, y1) { 
    var clear = x0 === x1 || y0 === y1 
    data.forEach(function (d) { 
     d.filtered = clear ? false 
      : d.uta < x0 || d.uta > x1 || d.sau < y0 || d.sau > y1 
    }) 
    update() 
    } 

update() 
} 

/* Graphique */ 
function scatterplot(onBrush) { 
var margin = { top: 10, right: 15, bottom: 40, left: 75 } 
var width = 680 - margin.left - margin.right 
var height = 550 - margin.top - margin.bottom 

var x = d3.scaleLinear() 
    .range([0, width]) 
var y = d3.scaleLinear() 
    .range([height, 0]) 

// Tooltip 
var xValue = function(d) { return d.sau;}; 
var yValue = function(d) { return d.uta;}; 

var tooltip = d3.select("body").append("div") 
    .attr("class", "tooltip") 
    .style("opacity", 0); 

var xAxis = d3.axisBottom() 
    .scale(x) 
    .tickFormat(d3.format('')) 
var yAxis = d3.axisLeft() 
    .scale(y) 
    .tickFormat(d3.format('')) 

// Selection 
var brush = d3.brush() 
    .extent([[0, 0], [width, height]]) 
    .on('start brush', function() { 
     var selection = d3.event.selection 

     var x0 = x.invert(selection[0][0]) 
     var x1 = x.invert(selection[1][0]) 
     var y0 = y.invert(selection[1][1]) 
     var y1 = y.invert(selection[0][1]) 

     onBrush(x0, x1, y0, y1) 
    }) 

var svg = d3.select('#scatterplot') 
    .append('svg') 
    .attr('width', width + margin.left + margin.right) 
    .attr('height', height + margin.top + margin.bottom) 
    .append('g') 
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 

var bg = svg.append('g') 
var gx = svg.append('g') 
    .attr('class', 'x axis') 
    .attr('transform', 'translate(0,' + height + ')') 
var gy = svg.append('g') 
    .attr('class', 'y axis') 

gx.append('text') 
    .attr('x', width) 
    .attr('y', 35) 
    .style('text-anchor', 'end') 
    .style('fill', '#000') 
    .style('font-weight', 'bold') 
    .text('UTA') 

gy.append('text') 
    .attr('transform', 'rotate(-90)') 
    .attr('x', 0) 
    .attr('y', -55) 
    .style('text-anchor', 'end') 
    .style('fill', '#000') 
    .style('font-weight', 'bold') 
    .text('SAU - ha') 

svg.append('g') 
    .attr('class', 'brush') 
    .call(brush) 

return function update(data) { 
    x.domain(d3.extent(data, function (d) { return d.uta })).nice() 
    y.domain(d3.extent(data, function (d) { return d.sau })).nice() 

    gx.call(xAxis) 
    gy.call(yAxis) 

    var bgRect = bg.selectAll('rect') 
     .data(d3.pairs(d3.merge([[y.domain()[0]], color.domain(), [y.domain()[1]]]))) 
    bgRect.exit().remove() 
    bgRect.enter().append('rect') 
     .attr('x', 0) 
     .attr('width', width) 
     .merge(bgRect) 
     .attr('y', function (d) { return y(d[1]) }) 
     .attr('height', function (d) { return y(d[0]) - y(d[1]) }) 
     .style('fill', function (d) { return color(d[0]) }) 

    var circle = svg.selectAll('circle') 
     .data(data, function (d) { return d.name }) 
    circle.exit().remove() 
    circle.enter().append('circle') 
     .attr('r', 4) 
     .style('stroke', '#fff') 
     .merge(circle) 
     .attr('cx', function (d) { return x(d.uta) }) 
     .attr('cy', function (d) { return y(d.sau) }) 
     .style('fill', function (d) { return color(d.sau) }) 
     .style('opacity', function (d) { return d.filtered ? 0.5 : 1 }) 
     .style('stroke-width', function (d) { return d.filtered ? 1 : 2 }) 
     // Event 
     .on("mouseover", function(d) { 
      tooltipOverGraph.call(this, d);    
      handleMouseOverGraph.call(this, d); 
      }) 
     .on("mouseout", function(d) { 
      tooltipOutGraph.call(this, d); 
      handleMouseOutGraph.call(this, d); 
      }) 
     } 
    // Tooltip 
    function tooltipOverGraph(d) { 
      tooltip.transition() 
       .duration(200) 
       .style("opacity", .9); 
      tooltip.html(d["name"] + "<br>" + xValue(d) 
       + " ha" +", " + yValue(d) + " UTA") 
       .style("left", (d3.event.pageX + 5) + "px") 
       .style("top", (d3.event.pageY - 28) + "px");   
    } 

    function tooltipOutGraph(d) { 
      tooltip.transition() 
      .duration(500) 
      .style("opacity", 0); 
    }  
} 

// Create Event Handlers for mouse 
    function handleMouseOverGraph(d, i) {    
     d3.select(this).attr('r', 8);   
    } 

    function handleMouseOutGraph(d, i) {    
     d3.select(this).attr('r', 4); 
    } 


/* Carte */ 
function choropleth(features) { 
var width = 680 
var height = 550 

// Tooltip 
var xValue = function(d) { return d.sau;}; 
var yValue = function(d) { return d.uta;}; 

var tooltip = d3.select("body").append("div") 
    .attr("class", "tooltip") 
    .style("opacity", 0); 

// Projection et centrage de la carte 
var projection = d3.geoMercator() 
    .center([ 3, 46.5 ]) 
    .scale([width * 3.1]) 
    .translate([width/2, height/2]) 

var path = d3.geoPath().projection(projection) 

var svg = d3.select('#choropleth') 
    .append('svg') 
    .attr('width', width) 
    .attr('height', height) 

svg.selectAll('path') 
    .data(features) 
    .enter() 
    .append('path') 
    .attr('d', path) 
    .style('stroke', '#fff') 
    .style('stroke-width', 1)  
    // Event 
    .on("mouseover", function(d) { 
     tooltipOverMap.call(this, d); 
     handleMouseOverMap.call(this, d);   
    }) 
    .on("mouseout", function(d) { 
     tooltipOutMap.call(this, d); 
     handleMouseOutMap.call(this, d);    
    }) 

    // Tooltip 
    function tooltipOverMap(d) { 
     tooltip.transition() 
      .duration(200) 
      .style("opacity", .9); 
     tooltip.html(d["name"] + "<br>" + xValue(d) 
       + " ha" +", " + yValue(d) + " UTA") 
       .style("left", (d3.event.pageX + 5) + "px") 
       .style("top", (d3.event.pageY - 28) + "px");    
    } 

    function tooltipOutMap(d) { 
     tooltip.transition() 
      .duration(500) 
      .style("opacity", 0); 
    } 


return function update(data) { 
    svg.selectAll('path') 
     .data(data, function (d) { return d.name || d.properties.name }) 
     .style('fill', function (d) { return d.filtered ? '#ddd' : color(d.sau) }) 
    } 
} 

// Create Event Handlers for mouse 
    function handleMouseOverMap(d, i) {    
     d3.select(this).style('stroke-width', 3);   
    } 

    function handleMouseOutMap(d, i) {    
     d3.select(this).style('stroke-width', 1);   
    } 
</script> 

Example

回答

0

首先,添加不同的class属性为rectcircle项目,当你进入+追加他们:

bgRect.enter().append('rect') 
    .attr('class', function(d,i) { return 'classRect' + i; }) 


circle.enter().append('circle') 
    .attr('class', function(d,i) { return 'classCircle' + i; }) 

然后,更新你的鼠标功能:

function handleMouseOverMap(d) { 

     // update the choropleth // 
     d3.select(d).style('stroke-width', 3); 

     // update the scatterplot // 
     // capture the number contained in class (e.g. "1" for "classRect1") 
     var i = d3.select(d).class.substr(-1); 

     // select corresponding circle in scatter and update 
     d3.select('circle.classCircle'+i).attr('r', 8); 
} 


function handleMouseOverGraph(d) { 

     // update the scatter //   
     d3.select(d).attr('r', 8); 

     // update the choropleth // 
     // capture the number contained in class (e.g. "1" for "classCircle1") 
     var i = d3.select(d).class.substr(-1); 

     // select corresponding rect in the choropleth and update 
     d3.select('rect.classRect'+i).style('stroke-width', 3); 
} 
+0

它返回我一个错误:'d3.select(...)类是在这一行undefined''变种I = D3。选择(d).class.substr(-1);'可能程度的变量和函数的原因是什么?因为'scatterplot'和'choropleth'是独特的功能。 – GeoGyro