block by shimizu 8889e0fa5a9598dd3468813817a705de

D3 v4 - SlopeChart

Full Screen

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>D3 v4 - SlopeChart</title>
</head>

<style>
html, body {
    width: 100%;
    height: 100%;
}
#wrapper {
    width: 100%;
}
    
svg {
    display: block;
    width: 50%;
    height: 900px;
    background-color: #e2e2e2;
    margin: auto;
}
text {
    font-size: 12px;
}
.slopeAxis {
    stroke-dasharray: 3;
}

.Japan {
    fill:green;
    fill-opacity:1;
}
.valueLine.Japan {
    stroke:green;
}
</style>

<body>
<div id="wrapper">
    <svg></svg>    
</div>    
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>    
<script>
function cast(d){
    Object.keys(d).forEach(function(key){
        if (!isNaN(+d[key])) d[key] = +d[key]
    })
    
    return d 
}


    
d3.tsv("gdp.tsv", cast, main)    
    
function main(data) {
    
    var slopeColumns = ["GDP_2000", "GDP_2015"]
    
    var domain = [500, 20000]
    var margin = {top:60, left:100, bottom:30, right:100}
    
    
    
    
    var width,height
    var plotWidth, plotHeight
    
    var svg = d3.select("svg")
    var plotLayer = svg.append("g").attr("class", "plotLayer")
    var slopeLeft = plotLayer.append("g").attr("class", "slopeLeft")
    var slopeRight = plotLayer.append("g").attr("class", "slopeRight")
    
    var xScale = d3.scalePoint().domain(slopeColumns)
    var yScale = d3.scaleLog().domain(domain)
    
    setSize()
    rendring(data)
    setReSizeEvent()    
        
    function rendring(data){
        renderAxis(data)
        renderSlope(data)
        renderLabel(data)
    }

    function setSize() {
        width = svg.node().clientWidth
        height = svg.node().clientHeight
        
        plotWidth = width - (margin.left + margin.right)
        plotHeight = height - (margin.top + margin.bottom)
        
        plotLayer.attr("transform", "translate("+[margin.left, margin.top]+")")
            .attr("width", plotWidth)
            .attr("height", plotHeight)
                
        xScale.range([0, plotWidth])
        yScale.range([plotHeight, 0])

        slopeLeft.attr("transform", "translate("+[xScale(slopeColumns[0]), 0]+")")
        slopeRight.attr("transform", "translate("+[xScale(slopeColumns[1]), 0]+")")


    }
    
    function renderAxis(data) {
        //draw slopeAxis
        var selectedSlopeAxis = plotLayer.selectAll(".slopeAxis").data(slopeColumns)
        
        var newSlopeAxis = selectedSlopeAxis.enter().append("line")
            .attr("class", "slopeAxis")
            
        var slopeAxis = selectedSlopeAxis.merge(newSlopeAxis)
        
        slopeAxis
            .attr("x1", function(d){ return xScale(d)})
            .attr("y1", 0)
            .attr("x2", function(d){ return xScale(d)})
            .attr("y2", plotHeight)
            .attr("stroke", "black")
            
        //draw axisLable
        var selectedAxisLabel = plotLayer.selectAll(".AxisLabel").data(slopeColumns)
        
        var newAxisLabel = selectedAxisLabel.enter().append("text")
            .attr("class", "AxisLabel")
            .attr("text-anchor", "middle")
            .attr("dominant-baseline", "middle")
            
        var axisLabel = selectedAxisLabel.merge(newAxisLabel)
        
        axisLabel
            .attr("x", function(d){ return xScale(d)})
            .attr("y", "-2em")
            .text(function(d){ return d })
        
    }
        
    function renderSlope(data) {
        //draw valueLine
        var selectedValueLine = plotLayer.selectAll(".valueLine").data(data)
        
        var newValueLine = selectedValueLine.enter().append("line")
            .attr("class", function(d){ return "valueLine " + d["Country"]})
        
        var valueLine = selectedValueLine.merge(newValueLine)
        
        valueLine
            .attr("x1", xScale(slopeColumns[0]))
            .attr("y1", function(d){ return yScale(d[slopeColumns[0]])})
            .attr("x2", xScale(slopeColumns[1]))
            .attr("y2", function(d){ return yScale(d[slopeColumns[1]])})
            .attr("stroke", "black")
        
        
        //draw circle
        var selectedLeftCircle = slopeLeft.selectAll(".leftCircle").data(data)
        var selectedRightCircle = slopeRight.selectAll(".rightCircle").data(data)
        var newLeftCircle = selectedLeftCircle.enter().append("circle").attr("class",  function(d){ return "leftCircle " + d["Country"]})
        var newRigthCircle = selectedRightCircle.enter().append("circle").attr("class",  function(d){ return "rightCircle " + d["Country"]})
        var leftCircle = selectedLeftCircle.merge(newLeftCircle)
        var rightCircle = selectedRightCircle.merge(newRigthCircle)
        
        leftCircle.attr("cy", function(d){ return yScale(d[slopeColumns[0]]) }).attr("r", 4)
        rightCircle.attr("cy", function(d){ return yScale(d[slopeColumns[1]]) }).attr("r", 4)
        
        
    }
    
    function renderLabel(data) {
        //draw label
        var selectedLeftLabel = slopeLeft.selectAll(".leftLabel").data(data)
        var selectedRightLabel = slopeRight.selectAll(".rightLabel").data(data)
        
        var newLeftLabel = selectedLeftLabel.enter().append("text").attr("class", function(d){ return "leftLabel " + d["Country"] })
            .attr("text-anchor", "end")
            .attr("dominant-baseline", "middle")
        var newRigthLabel = selectedRightLabel.enter().append("text").attr("class", function(d){ return "rightLabel " + d["Country"] })
            .attr("text-anchor", "start")
            .attr("dominant-baseline", "middle")
        
        var leftLable = selectedLeftLabel.merge(newLeftLabel)
        var rightLable = selectedRightLabel.merge(newRigthLabel)
        
        leftLable.text(function(d){ return d["Country"] })
            .attr("x", "-0.5em")
            .attr("y", function(d){
                var y = yScale(d[slopeColumns[0]])
                if (d["Country"] === "China" || d["Country"] === "Mexico") y -= 6
                if (d["Country"] === "Italy" || d["Country"] === "Brazil") y += 6
                return  y})
        rightLable.text(function(d){ return d["Country"] })
            .attr("x", "0.5em")
            .attr("y", function(d){
                var y = yScale(d[slopeColumns[1]])
                if (d["Country"] === "Italy") y -= 6
                if (d["Country"] === "Brazil") y += 6
                return  y})
        
    }

    function setReSizeEvent() {
        var resizeTimer;
        var interval = Math.floor(1000 / 60 * 10);
         
        window.addEventListener('resize', function (event) {
            if (resizeTimer !== false) {
                clearTimeout(resizeTimer);
            }
            resizeTimer = setTimeout(function () {
                setSize()
                rendring(data)
            }, interval);
        });
    }
}


</script>    
</body>
</html>

gdp.tsv

Country	GDP_2000	GDP_2015
America	10284.75 	17947.00 
England	1551.75 	2849.34 
Italy	1145.56 	1815.75 
India	476.64	2090.70 
Canada	739.45 	1552.38 
Germany	1952.92 	3357.61 
Brazil	657.24 	1772.58 
France	1372.45 	2421.56 
Mexico	683.65 	1143.80 
China	1192.85 	10982.82 
Japan	4731.20 	4123.25