标签(空格分隔): 未分类css
[x] 定义:经过循环的方式将数据绑定在dom元素上,每一个数据对应一个元素,因此这个数据的值就能来设定dom元素的width,height,x,y坐标等,这就表现了数据驱动的思想,同时也是d3的精华所在。html
[x] 咱们绑定的数据经过匿名函数function(d,i)来调用,数据的值就能设置dom元素的属性。前端
全部的标签均可以进行绑定,对rect,circle,text,咱们想要数据来驱动任何元素,那么就用数据绑定该元素,经过attr()设置x,y,width,height,fill,等属性,on()来绑定鼠标事件。jquery
svg.selectAll("rect") .data(dataset) data方法后的语句都会循环,循环次数为数据个数 .enter() .append("rect") .attr("x",function(d,i){ return xscale(i); }) .attr("y",function(d){ return (h-yscale(d)); }) .attr("height",function(d){ return yscale(d); }) .attr("width",xscale.rangeBand()) .attr("fill",function(d){ return "rgb(0, 0, " + Math.round(d * 10) + ")"; }) .on("click",function(d){ 经过on来事件绑定,记住事件绑定种类就能够了 console.log(d); }) .on("mouseover",function(){ d3.select(this) .attr("fill","orange") }) .on("mouseout",function(d){ d3.select(this) .transition() .duration(250) .attr("fill","rgb(0,0,"+d*10+")") }) .on("click",function(){ sortBar(); })
/*坐标轴声生成*/ var xaxis=d3.svg.axis() .scale(xscale) .orient("buttom") .ticks(10) // .tickFormat(formator); var yaxis=d3.svg.axis() .scale(yscale) .orient("left") .ticks(10); /*g是group的意思,跟html中div做用同样*/ svg.append("g") .attr("class","x axis") .attr("transform", "translate(0," + (h - padding) + ")") .call(xaxis); svg.append("g") .attr("class","y axis") .attr("transform","translate("+(padding)+",0)") .call(yaxis);
<style type="text/css"> .axis path, .axis line{ fill: none; stroke: blue; stroke-width:2; shape-rendering: crispEdges; } .axis text{ font-size: 11px; fill: grey; } </style>
var formatAsPersontage=d3.format(".1%") xaxis.ticketFormat(formatAsPersontage)
attr()设置svg标签元素的属性 如fill stroke stroke-width等 与一般 的js中css属性并不同 style()方法来设置css属性。 至关于在css类上添加一行 .classed("bar",true) d3中快速的添加删除类 .classed("bar",false)
二者的区别在于数组
<div class="rec" style="color:"red";"> </div>
很明显,属性与style是一个级别的,style是做用在二级变量上的。
d3中常常在svg操做,有些属性只能是svg的,与html有些不同。app
svg是可缩放矢量图语言,因此在svg上绘制的几何图形咱们能够任意缩放,而不会致使像素模糊,固然也能够body上直接绘制空div,填充的方式,间接表现条形图,不过在一般来说对前端人员来说是不可能干的,因此咱们通常在svg这个画布上绘制,先append一个div设置width,height,而后再添加rect,circle,svg上的几何图形有,rect,circle,还支持路径自由绘制,何乐而不为呢?dom
在绑定数据的过程当中,大量的数据会有大量的循环,attr()会写好屡次,因此多值映射的目的就是整理代码,能够将attr中的,写到一个attr()中。这就是多值映射,名字高大上,其实不就是简写嘛!!!svg
咱们的数据量随时有可能改变,那么当数据量改变的时候难道要从新设置每一个bar的width及x,y坐标吗?显然是不可能的
解决方法就是函数
.attr("x“,function(d,i){ return i*(w/dataset.length); }) .attr("width",function(){ return w/dataset.length-padding; })
出发点就是将svg画布的宽度与i关联起来动画
其实很简单,既然数据能绑定在rect,circle上,那么数据也能绑定在text元素上了,再向svg中append()text元素就行,并设定text元素坐标,而后用text()方法打印出来。
svg.selectAll("text") .data(dataset) .enter() .append("text") .text(function(d){ return d; }) .attr("x",function(d,i){ return xscale(i); }) .attr("y",function(d){ return (h-yscale(d)+12); }) .attr("font-size","10px") .attr("fill","white") .style("pointer-events","none")
其实比例尺就是从一个定义域映射到另外一个值域而已,这个值域就是咱们本身所设定的范围.由于是范围,因此参数是[]中括号形式。
//ordinal是一个序数比例尺,会根据数据集数量来平均分段,且保存了每段的宽度, var xscale=d3.scale.ordinal() .domain(d3.range(dataset.length)) .rangeRoundBands([0,w],0.1); //eg. .nice() /*将y值映射到0-100*/ //当数据类型不是点集的形式,max()下不用嵌套匿名函数 var yscale=d3.scale.linear() .domain([0,d3.max(dataset,function(d){ return d; })]) .range([5,h]);
在linear比例尺中,有几个简便方法。
.nice() 将值域取整 .rangeRound() 取整 .clamp() 将值域压缩,当定义域超出范围 用法,直接连接在比例尺后边,如上边标注eg
其余比例尺,
sqrt 平方根 pow 幂函数 log 对数 quantize 对数据分类状况 ordinal 序数比例尺 意思就是离散的值 d3.scale.category10() 预设好的输出10到20中颜色比例尺 d3.time.scale() 日期比例尺
//在咱们映射到值域的时候 //既能够用range,也可rangBands,会自动分档,还可rangeRoundBands()分档加取整 var xScale = d3.scale.ordinal() .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05);
这样在bar中求宽度时,能够直接调用比例尺下求出来的。
.attr("width", xScale.rangeBand())
d3.select("button") .on("click",function(){ })
svg.selectAll("circle") .data(dataset) .transition() 过渡函数 .duration(1000) 持续事件 .ease("linear") 缓动函数 .each("start",function(){ d3.select(this) // .transition() // .duration(200) //在on方法中不能再有新的过分效果,只能执行当即变换的,不然会覆盖掉前边的 .attr("fill","magenta") .attr("r",3) }) //同时也能够有延迟函数 .delay(function(d,i){ return i*100; })
几种缓动效果:cubic-in -out 默认效果
linear
circle
elatic
bounce
在该方法中能够在开始或者结束时设定新的效果,可是若是是start不能再使用过渡函数transition(),由于d3的设计中新的过渡会覆盖掉就的过渡,在外层已经有了一层transition,若是在each内部,再设定一个transition那么就会覆盖外部的transition,外部的一切attr所设定的都会失效。d3是有意这样作的,不想jquery咱们必需要等到一个动画结束才能够操做,很烦人。因此只能在start内部使用变换,不能过渡。
参数是end那么就能够,为何?由于这个元素上一层的过渡已经完成了,咱们即便在内部再有transition也无所谓。
//只接受两个参数 each("start",function(){}) each("end",function(){}) .each("start",function(){ d3.select(this) // .transition() // .duration(200) //在on方法中不能再有新的过分效果,只能执行当即变换的,不然会覆盖掉前边的 .attr("fill","magenta") .attr("r",3) })
剪切蒙版至关于ps中的蒙版,只有落在蒙版内部的元素才会显示出来,ClipPath与g元素同样也是没有元素,咱们在内部定义可见元素做为蒙版的画布大小。
//在html效果 <ClipPath id="chartarea"> <rect x="30" y="30" width="200" height="300"></rect> </ClipPath>
/*定义蒙版*/ svg.append("clipPath") .attr("id","chartarea") .append("rect") .attr("x",padding) .attr("y",0) .attr("width",w-padding) .attr("height",h-padding); svg.append("g") //将全部的circle添加到g元素中,并设置id之后方便引用 .attr("id","circles") .attr("clip-path","url(#chartarea)")//引用蒙版 注意引用属性名 .selectAll("circle") .data(dataset) .enter() .append("circle") ...
增长元素状况:当咱们经过data方法对空占位进行绑定后,
var bars=svg.selectAll("rect") .data(dataset,function(d){ return d.key; }) 返回一个更新元素集,在内部保存着加入和退出子元素集的引用
bars.enter()会一一比较数据的个数与dom元素的个数,由于enter对应的是添加状况,因此会发现数据的个数比dom元素的个数多,咱们就会拿到加入元素集的引用,而后再.append("rect")
//每次enter只会有一个占位符 bars.enter() .append("rect") .attr("x",w)//放到最后 .attr("y",function(d){ return h-yscale(d); }) .attr("width",function(d){ return xscale.rangeBand(); }) .attr("height",function(d){ return yscale(d); }) bars.transition() //在从新更新位置 // .delay(function(d,i){//每一个加载数据延迟 // return i/dataset.length*1000; // }) .duration(500) // .ease("linear") .attr("x",function(d,i){ return xscale(i); })
bars.exit()一样也是会比较,以后咱们拿到退出元素集的dom元素的引用
bars.transition() //没有退出元素的引用 // .delay(function(d,i){//每一个加载数据延迟 // return i/dataset.length*1000; // }) .duration(500) // .ease("linear") .attr("x",function(d,i){ return xscale(i); }) .attr("y",function(d){ return (h-yscale(d.value)); }) .attr("height",function(d){ return yscale(d.value); }) .attr("width",xscale.rangeBand()) .attr("fill",function(d){ return "rgb(0, 0, " + Math.round(d.value * 10) + ")"; }); bars.exit() //退出元素的引用 .transition() .duration(500) .attr("x",-xscale.rangeBand()) .remove();
data.shit()删除的是第一个数据,当咱们更新dom元素会发现第一个
rect变成了第二个数值,咱们明明想把第一个连同dom元素一块删除掉的,这也就是dom元素的顺序并无和数据的顺序实现一一绑定,这也就是键绑定存在的缘由。
怎么操做?
其实很简单,绑定数据的时候将key也绑定上去
//dataset is now an array of objects. //Each object has a 'key' and a 'value'. var dataset = [ { key: 0, value: 5 }, { key: 1, value: 10 }, { key: 2, value: 13 }, { key: 3, value: 19 }, { key: 4, value: 21 }, { key: 5, value: 25 }, { key: 6, value: 22 }, { key: 7, value: 18 }] var key = function(d) { return d.key; }; //Bind data with custom key function svg.selectAll("rect") .data(dataset, key) .enter() ... //Bind data with custom key function svg.selectAll("text") .data(dataset, key) .enter() ...
事件监听器种类有:click mouseover mouseout
pointer-events:none 令监听器失效
通常有两种策略
on("hover",function(d,i){ 肯定事件 d3.select(this) 选择元素 .attr("fill","orange") 要作哪些改变 .transiton() })
sort函数会将元素绑定的值进行排序成一个新数组。
sort(function(a,b){return d3.ascending(a,b)})
策略:body中设置好一个div,不可见,当鼠标hover则改成可见,移走再不可见。classed()方法 添加删除class属性
.on("click",function(d){ console.log(d); }) .on("mouseover",function(d){ var xposition=parseFloat(d3.select(this).attr("x")+xscale.rangeBand/2); var yposition=parseFloat(d3.select(this).attr("y")/2+h/2); d3.select("#tooltip") .transition() .duration(500) .style("left",xposition+"px") .style("top",yposition+"px") .select("#value") .text(d) d3.select("#tooltip").classed("hidden",false); }) .on("mouseout",function(){ d3.select("#tooltip").classed("hidden",true); }) .on("click",function(){ sortBar(); })