標籤(空格分隔): 未分類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(); })