D3.js-柱形图

来源:互联网 发布:九极会员登录软件 编辑:程序博客网 时间:2024/05/24 06:14
柱形图,是使用柱形的长短来表示数据变化的图表,也是最简单的图表之一。一般情况下,柱形图包括:矩形、坐标轴和文字。

一、矩形和文字
定义一个数组,每个数据项表示矩形的长短:

var dataset = [50, 43, 120, 87, 99, 167, 142];  // 数据集

定义一个SVG,表示绘制区域:

var width = 400;    // svg可视区域宽度var height = 400;   // svg可视区域高度var svg = d3.select("body")        .append("svg")      // 在body中添加SVG        .attr("width", width)        .attr("height", height);

添加SVG后,定义几个变量:

var padding = {top: 20, right: 20, bottom: 20, left: 20};   // 边距var rectStep = 35;  // 矩形所占宽度(包括空格)var rectWidth = 30; // 矩形所占宽度(不包括空格)

示例
data()的工作过程:
data()能将数组各项分别绑定到选择集的各元素上,并且能指定绑定的规则。当数组长度与元素数量不一致时,data()也能够处理。当数组长度大于元素数量时,为多余数据预留元素位置,以便将来插入新元素;当数组长度小于元素数量时,能够获取多余元素的位置,以便将来删除。
在D3中,根据数组长度和元素数量的关系,分别把各种情况归纳如下:
update:数组长度 = 元素数量;
enter:数组长度 > 元素数量;
exit:数组长度 < 元素数量。
绘制矩形:

/* rect */var rect = svg.selectAll("rect")        .data(dataset)          // 绑定数据        .enter()                // 获取enter部分        .append("rect")         // 添加rect元素,使其与绑定数组的长度一致        .attr("fill", "steelblue")        .attr("x", function(d, i){            return padding.left + i * rectStep;        })        .attr("y", function(d){            return height - padding.bottom - d;        })        .attr("width", rectWidth)        .attr("height", function(d){            return d;        });

绘制文字:

/* text */var text = svg.selectAll("text")        .data(dataset)          // 绑定数据        .enter()                // 获取enter部分        .append("text")         // 添加text元素,使其与绑定数组的长度一致        .attr("fill", "white")        .attr("font-size", "14px").attr("text-anchor", "middle")        .attr("x", function(d, i){            return padding.left + i * rectStep;        })        .attr("y", function(d){            return height - padding.bottom - d;        })        .attr("dx", rectWidth/2).attr("dy", "1em")        .text(function(d){            return d;        });

二、更新数据
更新数据后,柱形图也得跟着变化。
update部分的处理方法是更新属性,enter部分的处理方法是添加元素后再赋予其相应的属性,exit部分的处理方法则是删除掉多余的元素。
矩形:

var updateRect = svg.selectAll("rect").data(dataset);   // 错误 d3.selectAll() 出了svg范围var enterRect = updateRect.enter();var exitRect = updateRect.exit();// update处理方法updateRect.attr("fill", "steelblue")    .attr("x", function(d, i){        return padding.left + i * rectStep;    })    .attr("y", function(d){        return height - padding.bottom - d;    })    .attr("width", rectWidth)    .attr("height", function(d){        return d;    });// enter处理方法enterRect.append("rect").attr("fill", "steelblue")    .attr("x", function(d, i){        return padding.left + i * rectStep;    })    .attr("y", function(d){        return height - padding.bottom - d;    })    .attr("width", rectWidth)    .attr("height", function(d){        return d;    });// exit处理方法exitRect.remove();

文字:

var updateText = svg.selectAll("text").data(dataset);var enterText = updateText.enter();var exitText = updateText.exit();// update处理方法updateText.attr("fill", "white")    .attr("font-size", "14px").attr("text-anchor", "middle")    .attr("x", function(d, i){        return padding.left + i * rectStep;    })    .attr("y", function(d){        return height - padding.bottom - d;    })    .attr("dx", rectWidth/2).attr("dy", "1em")    .text(function(d){        return d;    });// enter处理方法enterText.append("text").attr("fill", "white")    .attr("font-size", "14px").attr("text-anchor", "middle")    .attr("x", function(d, i){        return padding.left + i * rectStep;    })    .attr("y", function(d){        return height - padding.bottom - d;    })    .attr("dx", rectWidth/2).attr("dy", "1em")    .text(function(d){        return d;    });// exit处理方法exitText.remove();

三、坐标轴
比例尺分为:定量比例尺(定义域是连续的)和序数比例尺(定义域是不连续的)。

// 定义柱形图比例尺var xAxisWidth = 300; // x轴宽度var yAxisWidth = 300; // y轴宽度/* x轴比例尺(序数比例尺) */var xScale = d3.scale.ordinal()        .domain(d3.range(dataset.length))        .rangeRoundBands([0, xAxisWidth], 0.2);/* y轴比例尺(线性比例尺) */var yScale = d3.scale.linear()        .domain([0, d3.max(dataset)])        .range([0, yAxisWidth]);

有了比例尺后,矩形的位置、长度都要用比例尺来计算。这么做之后,数据和绘制就能完全分开,而且只需要修改比例尺,即可将图表自由伸缩

selection.attr("fill", "steelblue")    .attr("x", function(d, i){        return padding.left + xScale(i);    })    .attr("y", function(d){        return height - padding.bottom - yScale(d);    })    .attr("width", xScale.rangeBand())    .attr("height", function(d){        return yScale(d);    });    /* 添加坐标轴 */var xAxis = d3.svg.axis().scale(xScale).orient("bottom");yScale.range([yAxisWidth, 0]);  // 重新设置y轴比例尺的值域,与原来的相反var yAxis = d3.svg.axis().scale(yScale).orient("left");svg.append("g").attr("class", "axis")        .attr("transform", "translate("+ padding.left +","+ (height - padding.bottom) +")")        .call(xAxis);svg.append("g").attr("class", "axis")        .attr("transform", "translate("+ padding.left +","+ (height - padding.bottom - yAxisWidth) +")")        .call(yAxis);

四、使用call减少冗余
call允许将选择集自身作为参数,传递给某一函数。

d3.selectAll("div").call(myfun);

等价于

function myfun(selection){    // 这里进行相关操作    selection.attr("name", "value");}myfun(d3.selectAll("div"));

使用call的完整示例
示例图

var dataset = [50, 43, 120, 87, 99, 167, 142];  // 数据集var width = 400;    // svg可视区域宽度var height = 400;   // svg可视区域高度var svg = d3.select("body")        .append("svg")        .attr("width", width).attr("height", height);var padding = {top: 20, right: 20, bottom: 20, left: 50};   // 边距var xAxisWidth = 300; // x轴宽度var yAxisWidth = 300; // y轴宽度/* x轴比例尺(序数比例尺) */var xScale = d3.scale.ordinal()        .domain(d3.range(dataset.length))        .rangeRoundBands([0, xAxisWidth], 0.2);/* y轴比例尺(线性比例尺) */var yScale = d3.scale.linear()        .domain([0, d3.max(dataset)])        .range([0, yAxisWidth]);/* rect */var rect = svg.selectAll("rect")        .data(dataset)        .enter()        .append("rect")        .call(rectFun);/* text */var text = svg.selectAll("text")        .data(dataset)        .enter()        .append("text")        .call(textFun);/* 添加坐标轴 */var xAxis = d3.svg.axis().scale(xScale).orient("bottom");yScale.range([yAxisWidth, 0]);  // 重新设置y轴比例尺的值域,与原来的相反var yAxis = d3.svg.axis().scale(yScale).orient("left");svg.append("g").attr("class", "axis")        .attr("transform", "translate("+ padding.left +","+ (height - padding.bottom) +")")        .call(xAxis);svg.append("g").attr("class", "axis")        .attr("transform", "translate("+ padding.left +","+ (height - padding.bottom - yAxisWidth) +")")        .call(yAxis);/* rect处理函数 */function rectFun(selection) {    selection.attr("fill", "steelblue")            .attr("x", function(d, i){                return padding.left + xScale(i);            })            .attr("y", function(d){                return height - padding.bottom - yScale(d);            })            .attr("width", xScale.rangeBand())            .attr("height", function(d){                return yScale(d);            });}/* text处理函数 */function textFun(selection){    selection.attr("fill", "white")            .attr("font-size", "14px").attr("text-anchor", "middle")            .attr("x", function(d, i){                return padding.left + xScale(i);            })            .attr("y", function(d){                return height - padding.bottom - yScale(d);            })            .attr("dx", xScale.rangeBand()/2).attr("dy", "1em")            .text(function(d){                return d;            });}
0 0
原创粉丝点击