D3 - 在不同的DIV中选择

时间:2017-06-29 15:57:35

标签: d3.js scatter-plot choropleth

我在同一个网页上制作了散点图和等值线图。数据存储在.CSV.json中,元素与"名称"字段。

我已经在鼠标悬停上做了一个工具提示。我现在想要它们之间的一些交互性:当鼠标在散点图上的一个元素上时,这个元素在等值线上会起作用,当鼠标在等值线上时,地图散点图反应。

Scatterplot和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

1 个答案:

答案 0 :(得分:0)

首先,当您输入+追加它们时,为classrect项添加不同的circle属性:

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);
}