d3

//4 选择集与数据
//4.1 选择元素
//select:返回选择器的第一个元素
//selectAll:返回选择器的所有元素
d3.select('body');
d3.select('#footer');
d3.select('.content');//选择类为content的第一个元素
d3.selectAll('p');
d3.selectAll('.content');
d3.selectAll('ul li');
d3.select('body').selectAll('p');

//4.2 选择集
//d3.select和d3.selectAll返回的对象称为选择集(selection),添加/删除/设定网页中的元素,都要使用选择集
selection.empty();//如果选择集为空,返回true,否则返回false
selection.node();//返回第一个非空元素,如果选择集为空,返回null
selecttion.size();//返回选择集中的元素个数

selection.attr(name[, value]);//设定或获取属性
svg.append('circle').attr('cx','50px').attr('cy','50px').attr('r','50px').attr('fill','red');

selection.classed(name[,value]);//设定或获取选择集的CSS类,name为类名,value为布尔值,表示该类是否开启
d3.select('p').attr('class', 'red bigsize');
d3.select('p').classed('red', true).attr('classed', false);
d3.select('p').classed({'red':true, 'bigsize':true});
d3.select('p').classed('red bigsize', true);
console.log(d3.select('p').classed('bigsize'));//返回该类是否开启

selection.style(name[, value[, priority]]);//设定或获取选择集的样式
d3.select('p').style('color', 'red').style('font-size', '30px');
d3.select('p').style({'color':'red', 'font-size':'30px'});

selection.property(name[, value]);//设定或获取选择集的属性
//返回不能用attr()来处理的属性,都可用property()。例如文本框的value属性,复选框等
d3.select('input').property('value');
d3.select('input').property('value', 'aaa');

d3.text([value]);//设定或获取选择集的文本内容,相当于innerText
d3.html([value]);//设定或获取选择集内部html内容,相当于innerHTML

//4.3 添加/插入/删除
selection.append(name);//在选择集的末尾添加一个元素,name为元素名称
selection.insert(name[, before]);//在选择集中指定元素之前插入一个元素,name为被插入的元素名称,before为CSS选择器名称
selection.remove();//删除选择集中的元素
d3.select('body').append('p').text('bike');
d3.select('body').insert('p', '#plane').text('bike');
d3.select('body').select('#plane').remove();

//4.4 数据邦定
//数据邦定,就是使被选择元素里"含有"数据
selection.datum([value]);//选择集中每一个元素都邦定相同的数据value
selection.data([values[, key]]);//选择集中每一个元素分别邦定数组values的每一项。key是一个键函数,用于指定邦定数组时对应规则
var p = d3.select('body').selectAll('p');
p.datum(7);
console.log(p.datum());
//问题?数据被邦定在选择集上后,该如何使用?
d3.select('body').selectAll('p').datum("mmm").text(function(d,i){return d + " " + i;});
//无名函数的参数d为被邦定的字符串,i为索引号
//在被邦定数据的选择集中添加元素后,新元素会继承该数据
d3.select('body').selectAll('p').datum("mmm").append('span').text(function(d,i){return d + " " + i;});

//data()的工作过程
//data()能够将数组各项分别邦定到选择集的各元素上,并且能制定邦定规则。当数组长度与元素数量不一致时,data()也能够处理。
//当数组长度大于元素数量时,为多余数据预留元素位置,以便将来插入新元素;当数组长度小于元素数量时,能够取多余元素的位置,以便将来删除。
var dataset = [3,6,9];
var p = d3.select('body').selectAll('p');
var update = p.data(dataset);
console.log(update);
console.log(update.enter());
console.log(update.exit());
//update: 数组长度 = 元素数量。则邦定数据的元素"即将被更新(update)"
//enter: 数组长度 > 元素数量。则部分还不存在的元素"即将进入可视化(enter)"
//exit: 数组长度 < 元素数量。则多余的元素"即将退出可视化(exit)"

//邦定的顺序
//默认情况下,data()是按照索引号顺序邦定的:第0个元素邦定数组的第0项。也可不按此顺序,需要用到data()的第二个参数,是一个函数,称为键函数(key function).
//注意:只有在选择集已经邦定有数据的情况下,使用键函数才有效果。
var persons = [{id:3, name:"jack"}, {id:9, name:"rose"}, {id:6, name:"vita"}];
var p = d3.select('body').selectAll('p');
p.data(persons).text(function(d){ return d.id + ":" + d.name; });
p.data(persons, function(d){ return d.id; }).text(function(d){ return d.id + ":" + d.name; });//表示使用数组项的id作为键

//4.5 选择集的处理
//当数组长度与元素数量不一致时,有enter部分和exit部分,前者表示存在多余的数据,后者表示存在多余的元素。
//问题:那么如果处理这些多余的东西呢?
//4.5.1 enter的处理方法
//如果没有足够的元素,那么处理方法就是添加元素。
var dataset = [3,6,9];
var p = d3.select('body').selectAll('p');
var update = p.data(dataset);
var enter = update.enter();
update.text(function(d){ return d;});//update部分的处理方法是直接修改内容
enter.append('p').text(function(d){ return d;});//enter部分的处理方法是添加元素后再修改内容

//通常冲服务器读取数据后,网页中没有与之对应的元素。因此,有一个常见的用法:选择一个空集,然后使用enter().append()形式来添加足够的元素。
var dataset = [10,20,30,40,50];
var body = d3.select('body');
body.selectAll('p').data(dataset).enter().append('p').text(function(d){ return d;});//假设body中没有p元素

//4.5.1 exit的处理方法
//如果存在多余的元素,没有与之对应的数据,那么就删除元素。使用remove()即可删除元素
var dataset = [3,6,9];
var p = d3.select('body').selectAll('p');
var update = p.data(dataset);
var exit = update.exit();
update.text(function(d){ return d;});
exit.remove();

//4.5.3 处理模板
//有时不知道数据多还是元素多,但是处理方法都是类似的。因此,可归纳为一个模板,用户不必理会数组长度和元素数量之间的关系
var dataset = [3,6,9];
var p = d3.select('body').selectAll('p');
var update = p.data(dataset);
var enter = update.enter();
var exit = update.exit();
update.text(function(d){ return d;});
enter.append('p').text(function(d){ return d;});
exit.remove();

//4.5.4 过滤器
//根据条件选择选择集中的一部分子集,该方法称为过滤器
selection.filter(function(d,i){ if(d>20){return true;}else{return false;}});

//4.5.5 选择集的顺序
//sort()可以根据 被邦定数据 重新排序选择集中的元素。sort()的参数是一个无名函数,该函数成为比较器。如果不指定比较函数,则默认为d3.ascending
selection.sort(function(a,b){return b - a; });

//4.5.6 each()的应用
//each()允许对选择集的各个元素跟别处理
var persons = [{id:1001, name:'zhangsan'}, {id:1002, name:'lisi'}];
var p = d3.select('body').selectAll('p');
p.data(persons).each(function(d,i){d.age=20;}).text(function(d){ return d.id + " " + d.name + " " + d.age;});

//4.5.7 call()的应用
//call()允许将选择集自身作为参数,传递给某一函数。拖拽/缩放等操作,会用到call()
d3.selectAll('div').call(myfun);
function myfun(selection){
selection.attr('name', 'value');
}
myfun(d3.selectAll('div'));

//4.6 数组的处理


//4.7 柱状图的制作
//柱状图(Bar Chart)是使用柱形的长短来表示数据变化的图标。包含:矩形/坐标轴和文字。
var dataset = [50, 43, 120, 87, 99, 167, 142];//数组长度为矩形的个数,数组项为矩形的高度
var width = 400;
var height = 400;
var svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
var padding = {top:20, right:20, bottom:20, left:20};//定义上下左右的边框
var rectStep = 35;//矩形所占的宽度(包括空白)
var rectWidth = 35;//矩形所占的宽度(不包括空白)

//padding表示svg绘制区域内一段空白的高度,这样做可以防止某些图形元素绘制到svg区域的外部。
var rect = svg.selectAll('rect').data(dataset).enter().append('rect')
.attr('fill', 'steelbule')
.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>元素正好显示在每个矩形的正中心,设置了元素的text-anchor/x/y/dx/dy五个属性
//dy/dy表示相对(x,y)平移大小,文本会在(x+dx, y+dy)开始显示
//text-anchor:start(文字第一个字读位于起始位置的右方), middle(文字的中心位于起始位置), end(文字最后一个字符靠近起始位置)
var text = svg.selectAll('text').data(dataset).enter().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;});

//4.7.2 更新数据
//有时需要更新数据,更新后柱状图也跟着变化。例如将数据排序/增加新数据等,都需要柱状图跟着变化
function draw(){
var udapteRect = svg.selectAll('rect').data(dataset);
var enterRect = udapteRect.enter();
var exitRect = udapteRect.exit();

var updateText =svg.selectAll('text').data(dataset);
var enterText = updateText.enter();
var exitText = updateText.exit();

//将绘制图形的代码写在一个函数draw(),当数据发生更新时,再次调用此函数即可
updateRect.attr('fill', 'steelbule')
.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;});

enterRect.append('rect')
.attr('fill', 'steelbule')
.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;});

exitRect.remove();
}

//<button type="button" onclick="mysort()">sort</button>
//<button type="button" onclick="myadd()">add data</button>
function mysort(){
dataset.sort(d3.ascending);
draw();
}
function myadd(){
dataset.push(Math.floor(Math.random()*100));
draw();
}

//5. 比例尺和坐标轴
//5.1 定量比例尺
//线性函数 y=2x+1 , x的范围[0,2]称为该函数的定义域,y的范围为值域
//D3种提供了很多比例尺,适用于各种计算。每个比例尺都需要指定一个domain(定义域)和range(值域)
//D3种的比例尺可当作函数使用,调用时传入参数
var linear = d3.scale.linear()//创建一个线性比例尺,该比例尺相当于数学中的: y=1/5x, 0<=x<=500
.domain([0,500])//定义域
.range([0,100]);//值域
console.log(linear(50));//10
console.log(linear(250));//50
console.log(linear(450));//90

//5.1.1 线性比例尺(Linear Scale)
d3.scale.linear() :创建线性比例尺
linear(x) :输入定义域值x,返回对应值域的值
linear.invert(y) :输入值域值y,返回对应定义域的值
linear.domain([numbers]) :设置或获取定义域
linear.range([values]) :设置或获取值域
linear.rangeRound([values]) :代替range()使用的话,比例尺输出值会进行四舍五入的运算,结果为整数
linear.clamp([values]) :默认false,该比例尺接收一个超出定义域范围内的值是,依然能计算得到值(可能超出值域)。设置true,任何超出值域范围的值,都被收缩到值域范围内
linear.nice([count]) :
linear.ticks([count])
linear.tickFormat(count, [format])

//5.1.2 指数和对数比例尺

//5.1.3 量子和分位比例尺

//5.1.4 阈值比例尺

//5.2 序数比例尺(Ordinal Scale),定义域和值域都是离散的
d3.scale.ordinal() 创建一个序数比例尺
ordinal(x) 输入一个定义域内地俄离散值,返回值域内一个离散值
ordinal.domain([values]) 设定或获取定义域
ordinal.range([values]) 设定或获取值域
ordinal.rangePoints(interval[, padding]) 代替range()设定值域。接收一个连续的区间,然后根据定义域中离散值的数值将其分段,分段值即作为值域的离散值
ordinal.rangeRoundPoints(interval[, padding]) 和rangePoints()一样,但会将结果取整
ordinal.rangeBands(interval[, padding[, outerPadding]]) 代替range()设定值域。和rangePoints()一样,也接收一个连续的区间,然后根据定义域中离散值的数量将其分段,但是其分段方法不同
ordinal.rangeRoundBands(interval[, padding[, outerPadding]]) 和rangeBands()一样,但会将结果取整
ordinal.rangeBand() 返回使用rangeBands()设定后每一段的宽度
ordinal.rangeExtend() 返回一个数组,数组里存有值域的最大值和最小值

var ordinal = d3.scale.ordinal().domain([1,2,3,4,5]).range([10,20,30,40,50]);
console.log(ordinal(1));//10
console.log(ordinal(2));//20
console.log(ordinal(5));//50
console.log(ordinal(8));//输入值不在定义域中,输出10

var rodinal = d3.scale.ordinal().domain([1,2,3,4,5]).rangePoints([0,100]);//inteval:[0,100], padding:0, step:25
console.log(ordinal.range());//[0,25,50,75,100]
console.log(ordinal(1));//0
console.log(ordinal(3));//50
console.log(ordinal(5));//100

rodinal.rangePoints([0,100], 5);//interval:[0,100], padding:5, step:11.11111。则step*padding/2=27.77777,是输出数组的第一个值
console.log(ordinal.range());

rodinal.rangeRoundPoints([0,100], 5);
console.log(ordinal.range());

var bands = d3.scale.rodinal().domain([1,2,3,4,5]).rangeBands([0,100]);
console.log(bands.range());//[0,20,40,60,80]
console.log(bands.rangeBand());//20

//D3提供了几个获取颜色的序数比例尺。如果对颜色没有特殊要求直接使用这些颜色比例尺即可
d3.scale.category10();//10种颜色
d3.scale.category20();//20种颜色
d3.scale.category20b();//20种颜色
d3.scale.category20c();//20种颜色

var color = d3.scale.category10();
console.log(color(1));
console.log(color('zhangsan'));

var width = 600;
var height = 600;
var dataset = d3.range(5);//[0,1,2,3,4,5]
var color = d3.scale.category10();
var svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
var circle = svg.selectAll('circle').data(dataset).enter().append('circle')
.attr('cx', function(d,i){return 30 + i*80;})
.attr('cy', 100)
.attr('r', 30)
.attr('fill', function(d,i){return color(i)});

//5.3 坐标轴(Axis)
d3.svg.axis() 创建一个默认的新坐标轴
axis(selection) 将此坐标轴应用到指定的选择集上,该选择集需要包含有<svg>或<g>元素
axis.scale([scale]) 设定或获取坐标轴的比例尺
axis.orient([orientation]) 设定或获取坐标轴的方向,有四个值: top,bottom,left,right。top表示水平坐标轴的刻度在直线下方,left表示垂直坐标轴的刻度在直线右方
axis.ticks([argument...]) 设定或获取坐标轴的分隔数,默认10。例如,设定5,则坐标轴上刻度数量为6,分段数5。这个函数会调用比例尺的ticks()
axis.tickValues([values]) 设定或获取坐标轴的指定刻度。例如,参数为[1,2,3,6,7,8],则在这几个值上会有刻度
axis.tickSize([inner, outer]) 设定或获取坐标轴的内外刻度的长度。默认6
axis.innerTickSize([size]) 设定或获取坐标轴的内刻度的长度。内刻度指不是两端的刻度
axis.outerTickSize([size]) 设定或获取坐标轴的外刻度的长度。外刻度指两端的刻度
axis.tickFormat([format]) 设定或获取刻度的格式

//5.3.1 绘制方法
//坐标轴的主直线由<path>绘制,刻度由<line>绘制,刻度上的文字由<text>绘制
var width = 600;
var height = 600;
var svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
var xScale = d3.scale.linear().domain([0,10]).range([0,300]);
var axis = d3.svg.axis().scale(xScale).orient('bottom');
var gAxis = svg.append('g')//在svg中添加一个包含坐标轴各元素的g元素
.attr('transform', 'translate(80,80)');//平移到(80,80)
axis(gAxis);//在gAxis中绘制坐标轴
//坐标轴的所有图形元素需放入<svg>或<g>里,建议新建g来控制,而不要直接放在<svg>中,svg中通常还包含其它图形元素。
//绘制后,html的元素结构中,class为tick的<g>元素是刻度,每一个刻度里都包含了<line>和<text>。坐标轴的主直线式最下方的class为domain的<path>

.axis path,
.axis line{
fill:none;
stroke:black;
stroke-rendering:criapEdges;
}
.axis text{
font-family:sans-serif;
font-size:11px;
}

gAxis.attr('class', 'axis');
gAxis.call(axis);//这种方式很常见

//5.3.2 刻度
//刻度的方向,间隔,长度,文字格式等
//如果要设置在什么值上标出刻度,使用ticks()和tickValues()
var axisLeft = d3.svg.axis().scale(scale).orient('left').ticks(5);
var axisRight = d3.svg.axis().scale(scale).orient('right').tickValues([3,4,5,6,7]);

var axisTop = d3.svg.axis().scale(scale).orient('top').ticks(5)
.tickSize(2,4);//设置两端刻度长度大于内部。第一个参数为内部刻度的直线长度,第二个为首尾刻度长度。也可使用innerTickSize()和outerTickSize()

//5.3.2 各种比例尺的坐标轴
var linear = d3.scale.linear().domain([0,1]).range([0,500]);
var pow = d3.scale.pow().exponent(2).domain([0,1]).range([0,500]);
var log = d3.scale.log().domain([0,1]).range([0,500]);

//5.4 柱形图的坐标轴
var xAxisWidth = 300;
var yAxisWidth = 300;
var xScale = d3.scale.oridinal()
.domain(d3.range(dataset.length))//[0,1,2,3...]
.rangeRoundBands([0, xAxisWidth], 0.2);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([0, yAxisWidth]);
.attr('x', function(d,i){ return padding.left + xScale(i)});
.attr('y', function(d){return height - padding.bottom - 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);

//5.5 散点图制作(Scatter Chart)

原文地址:https://www.cnblogs.com/skorzeny/p/6740184.html