Open dlrandy opened 6 years ago
scaleTime 将时间转换成value scaleTime.invert
映射一个抽象的值到视觉描述正是数据可视化做的,也是D3做的
scaleQuantize从数字数据创建label 但是它对应的是连续的domain scaleQuanize.invertExtent()
使用 scaleOrdinal 从非数字值创建label 它对应的是一组特定的值 scaleOrdinal()
d3.max(data, function(d){ return d.property }) d3.min d3.extent d3.set
d3.csv产生的数据除了对象,还有一个columns
d3的data不指定key方法的时候,是第一个数据对应着对一个元素,第二个对应第二个,以此类推。
key函数控制着数据项分给哪一个元素,他可以返回元素的key,也会返回数据的key。
指定key的数据分配给匹配key的元素。
如果多个元素具有同一个key,重复的元素会被放入exit selection;如果多个数据具有同一个key,重复的数据会被放入enter selection。
selection.data是有一个merge的过程的,
key函数的参数,指的是邦定在元素上的数据
selectAll().nodes() d3.select是整个document selection.select是整个selection
d3.select(').attr().property().style().classed().text().html()
d3.select().append(tag).insert(tag, before).remove() 上面的操作会修改目标tag,就是接下来的操作影响的都是加入的tag
d3里的一个select约定是新的selection缩进两个空格已经存在的selection缩进四个。这个数量都是相对于最一开始的位置。实际就是2个
data默认返回的是update selection,为什么叫做update selection是因为有元素和一些对应的数据了
当你的数据随着时间变化的时候,D3 不会重新创建整个图表,而是一些元素进行更新
data的key方法用于将数据项映射到DOM元素
D3.js使用key方法返回来的key来区分元素存在与否,并进行merge
整个的data区域update.merge(enter)
D3能够创建普通的DOM元素,也能够渲染到canvas,但是最常见的输出类型是svg
在使用svg的时候不需要设置width,y等的像素后缀,因为svg里一切都是像素的
svg有个默认size的,
因为svg没有自动布局,所以margin不好使,元素在没有设置位置的情况下 会彼此堆叠。
svg里的g元素,像DOM里的div,g是graphic的意思,经常备用为基本容器,承载rect或者text等。它没有x, y。需要 使用transform来设置位移。
大多数的D3原生selection API都会返回一个selection,使能够启用链式方法。
因为我们写的code不在selection的prototype上,所以链式我们自己的方法需要一些额外的工作的。可以使用selection.call来调用自己的方法引用,只需要提供selection作为第一个参数,然后调用之后它会返回一个selection。它的具有较好的复用性和可读性,还能支持链式调用。
一个图标如果没有为轴留有空间是不能够添加轴的
D3社区有一个定义margin的约定
var margin = { top: 10, right: 20, bottom: 25, left: 25 };
var width = 425 - margin.left - margin.right;
var height = 625 - margin.top - margin.bottom;
var svg = d3.select('.chart')
.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})`);
svg.append('rect')
.attr('width', width / 2)
.attr('height', height)
.style('fill', 'blue')
.style('stroke', 'green');
svg.append('rect')
.attr('x', width / 2)
.attr('width', width / 2)
.attr('height', height)
.style('fill', 'lightblue')
.style('stroke', 'green');
Y坐标轴的domain是反向设置的,因为svg里Y的尺寸是从上到下运行的。所以最小的值在最底部,最大的值在最顶部。
var yScale = d3.scaleLinear()
.domain([0, 1])
.range([height, 0])
var yAxis = d3.axisLeft(yScale)//default allocate optimal seg
.tricks(n, '.2%'[formatstr])// n seg,如果formatstr是%,那么domain要设置成0-1,这个还适用.1s小数点的情况
selection.call(yAxis)
设置X轴的时候和Y不一样,设置Y轴的时候selection.call就可以了。X轴则需要加一个额外的g,然后通过transform样式translate到底部,在调用call
var xAxis = d3.axisBottom(xScale)
//.ticks(d3.timeMinute.every(45))
.ticks(5)
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
//
var xAxis = d3.axisBottom(xScale).ticks(5)
.tickSizeInner(10)
.tickSizeOuter(20)
.tickPadding(5)
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
使用viewBox属性使得D3的chart响应式
svg的视口就是SVG里可见区
viewbox是把svg绘制到画布的实际坐标系统。它是把crop的区域 重新缩放到当前的整个区间
var margin = { top: 10, right: 20, bottom: 30, left: 30 };
var width = 400 - margin.left - margin.right;
var height = 600 - margin.top - margin.bottom;
var svg = d3.select('.chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.call(responsivefy)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
svg.append('rect')
.attr('width', width)
.attr('height', height)
.style('fill', 'lightblue')
.style('stroke', 'green');
var yScale = d3.scaleLinear()
.domain([0, 100])
.range([height, 0]);
var yAxis = d3.axisLeft(yScale);
svg.call(yAxis);
var xScale = d3.scaleTime()
.domain([new Date(2016, 0, 1, 6), new Date(2016, 0, 1, 9)])
.range([0, width]);
var xAxis = d3.axisBottom(xScale)
.ticks(5)
.tickSize(10)
.tickPadding(5);
svg
.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis);
function responsivefy(svg) {
// get container + svg aspect ratio
var container = d3.select(svg.node().parentNode),
width = parseInt(svg.style("width")),
height = parseInt(svg.style("height")),
aspect = width / height;
// add viewBox and preserveAspectRatio properties,
// and call resize so that svg resizes on inital page load
svg.attr("viewBox", "0 0 " + width + " " + height)
.attr("preserveAspectRatio", "xMinYMid")
.call(resize);
// to register multiple listeners for same event type,
// you need to add namespace, i.e., 'click.foo'
// necessary if you call invoke this function for multiple svgs
// api docs: https://github.com/mbostock/d3/wiki/Selections#on
d3.select(window).on("resize." + container.attr("id"), resize);
// get width of container and resize svg to fit it
function resize() {
var targetWidth = parseInt(container.style("width"));
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));
}
}
创建不同类型的图表需要使用不同scale。
复用transition有两种方式:一种是在函数里声明transition,之后立即多个selection使用(声明在一起是因为transition一旦声明就会执行,一旦结束就没有效果了);第二种就是单独声明transition,每一个selection的transition使用call方法进行调用
data的key方法就是说在做join的时候,查找该属性唯一识别这些对象
d3的on函数 回调函数的第三个参数是elements,一般在这种回调函数里使用selection.call对一些代码
margin 约定就是 svg元素的width、height是marin+ 已经去掉margin的width,然后追加一个g,调整它得到transform到margin 的left和bottom
scaleBand的domain需要持有所有对应轴的值
scaleSqurt用于设置scateer的半径变化
常见的更新模式 update exit.remove() enter update.merge(enter) 别忘了data的key函数
想设置动态的axis,就需要重新设置scale的domain
D3是完全模块的,有很多小的库组成,可以单独使用 ,也可以 一起使用,也可以自定义build
scaleLinear用于将数据转换成值 var scaleLinear = d3.scaleLinear().domain([]).range([]).clamp(true) domain = scaleLinear.invert(range)