深入浅出d3.js数据可视化之道(2)

上一节中,我们对数据可视化进行了一些基本的介绍,包括其选择器选择,数据绑定方式以及属性的设置,和图表数据的更新等一些操作,今天,我们来学习制作一些柱状图,并对其中用到的一些api 进行讲解。

svg矩形位置设定

x: 矩形左上角x轴坐标
y: 矩形右上角y轴坐标
width: 矩形的宽度
height: 矩形的高度
rx: 对于圆角矩形,指椭圆在x轴方向的半径
ry: 对于圆角矩形,指椭圆在y轴方向的半径

例如:

  
深入浅出d3.js数据可视化之道(2)_第1张图片
坐标系统
比例尺
  • 线性比例尺
    一个最简单的线性关系: y= 2x +1

在d3 的v4版本中,运行可得下列结果:

let yScale = d3.scaleLinear()
         .domain([0, 500])
         .range([0, 100]);

console.log( yScale(50) )  //10
console.log( yScale(250) )  // 50
console.log( yScale(450) )  //90
  • 序数比例尺
    定量比例尺的定义域和值域都是连续的,在实际的使用中,很多时候定义域和值域都是是非连续的,这时候我们就要用到序数比例尺了。
let xScale = d3.scaleBand()
                .domain(["a", "b", "c", "d", "e"])
                .rangeRound([0, 100])

console.log(xScale("a"))  //0
console.log(xScale("d"))   //60
console.log(xScale("e"))    //80

好了,学习上面两个知识点之后,我们开始我们的柱状图绘制!

准备的数据

const data =[
    {x:"上海", y:100},
    {x:"北京", y:200},
    {x:"天津", y:280},
    {x:"西安", y:100},
    {x:"武汉", y:240},
    {x:"长沙", y:210},
    {x:"深圳", y:100},
    {x:"郑州", y:220},
    {x:"驻马店", y:410},
    {x:"信阳", y:100},
    {x:"漯河", y:220},
    {x:"商丘", y:210},
    {x:"南阳", y:100},
    {x:"纽约", y:220},
    {x:"南昌", y:210}
]

样式

svg {
  box-sizing: content-box
}

界面初始化

在进行渲染之前,我们会先在svg 各侧预留padding,这里做的主要目的是为了坐标轴数值部分超出的可以正常显示。

   var initWidth = 340
    var initHeight = 500

    var padding = { left:40, top:20, right:10, bottom: 20}

    var height = initWidth - padding.top - padding.bottom
    var width  = initHeight - padding.left - padding.right


    var svg = d3.select("body")
                .append("svg")
                .attr("width", width)
                .attr("height", height)
                .style("padding-left", padding.left)
                .style("padding-right", padding.right)
                .style("padding-top", padding.top)
                .style("padding-bottom", padding.bottom)

此时效果如下:


深入浅出d3.js数据可视化之道(2)_第2张图片
初始效果

定义坐标轴

         // y比例尺
        let ydata = data.map(function(e, i){ return e.y})  //拿到y轴所有数据
        let yScale = d3.scaleLinear()   //定义线性比例尺(数值型,等比缩放)
         .domain([0, d3.max(ydata)])    // 定义域
         .range([height , 0]);          //值域
         
        let _yScale = d3.scaleLinear()
         .domain([0, d3.max(ydata)])
         .range([0, height]); 

        ***上述yScale与 _yScale的差别就在于range恰恰相反,
        因此同样的数值在运算时拿到的正好是相反的数据,
        而这在待会的坐标轴数值计算和直方位置的计算中我们会用到***

        //定义y轴
        let yAxis = d3.axisLeft(yScale);   //这句话的意思是添加左侧坐标轴,比例尺使用yScale

        //添加y轴
        svg.append("g")
        .attr("class","axis")
        .attr("transform","translate(" + 0 + "," + 0 + ")")
        .call(yAxis);

     //添加x轴坐标轴

         //x轴比例尺
         let xData = data.map(function(e, i){ return e.x})
         let xScale = d3.scaleBand()  //定义序数比例尺
                        .domain(xData)
                        .rangeRound([0, width])
                        .padding(0.1)
        //定义x轴
        let xAxis = d3.axisBottom(xScale)
        
        //添加x轴
         svg.append("g")
            .attr("class","axis--x")
            .attr("transform","translate(" + "0 ," + height + ")")
            .call(xAxis);

此时效果如下


深入浅出d3.js数据可视化之道(2)_第3张图片
预览

绘制直方

    var rect = svg.selectAll("rect")
                  .data(data)
                  .enter()
                  .append("rect")
                  .attr("x", function(d, i){
                      return xScale(d.x)
                  })
                  .attr("y", function(d){
                      return height -  _yScale(d.y)
                  })
                  .attr("width", xScale.bandwidth())
                  .attr("height", function(d){
                      return _yScale(d.y)
                  })
                  .attr("fill", "steelBlue")

效果


深入浅出d3.js数据可视化之道(2)_第4张图片
预览

接下来,我们可以在柱上添加文字


    var text = svg.append("g")
                .selectAll("text")
                .data(data)
                .enter()
                .append("text")
                .attr("x", function(d, i){
                      return xScale(d.x)
                  })
                .attr("y", function(d){
                      return height -  _yScale(d.y)
                })
                .attr("dy", "1em")
                .attr("dx", xScale.bandwidth() / 2)
                .attr("text-anchor", "middle")
                .attr("font-size", '14px')
                .attr("fill", "#fff")
                .text(function(d){
                    return d.y
                })

效果如下


深入浅出d3.js数据可视化之道(2)_第5张图片
预览

我们可以给坐标轴添加一些样式让他看起来活泼一些

 .axis--x path {
    display: none;
  }

鼠标在上面移动时我们可以给他添加一些样式

var rect = svg.selectAll("rect")
        .........
                  .attr("fill", "steelBlue")
                  .on("mouseover",function(){
                      d3.select(this).attr("fill", "yellow")
                  })
                  .on("mouseout", function(){
                      d3.select(this).attr("fill","steelBlue")
                  })

预览


深入浅出d3.js数据可视化之道(2)_第6张图片
预览

接下来我们给它添加一些交互效果

点击事件

这个很简单只需这样一句

var rect = svg.selectAll("rect")
        .........
                  .on("click",function(d){
                       console.log(d.x+":"+d.y)
                  })

(框选和点击不能同时存在)

框选
         var brush = svg.append("g")
             .attr("class", "brush")
            .call(d3.brushX()
                    .on("start", function(){     })  
                    .on("brush", function(){     } )
                    .on("end", function(e) {
                        var selection = d3.event.selection;
                        console.log(selection)  //可以拿到框选的x轴坐标范围,我们通过这个数值拿到框选到的目标就很简单啦
                    })
            )

最终效果


深入浅出d3.js数据可视化之道(2)_第7张图片
预览
一个小案例: 使用柱状图动态展示冒泡排序

深入浅出d3.js数据可视化之道(2)_第8张图片
冒泡排序可视化动态展现

本文所有图表源码

好了,今天我们先学到这里,明天更新饼图制作 !

你可能感兴趣的:(深入浅出d3.js数据可视化之道(2))