深入淺出d3.js數(shù)據(jù)可視化之道(2)

上一節(jié)中式塌,我們對(duì)數(shù)據(jù)可視化進(jìn)行了一些基本的介紹博敬,包括其選擇器選擇,數(shù)據(jù)綁定方式以及屬性的設(shè)置峰尝,和圖表數(shù)據(jù)的更新等一些操作偏窝,今天,我們來(lái)學(xué)習(xí)制作一些柱狀圖武学,并對(duì)其中用到的一些api 進(jìn)行講解祭往。

svg矩形位置設(shè)定

x: 矩形左上角x軸坐標(biāo)
y: 矩形右上角y軸坐標(biāo)
width: 矩形的寬度
height: 矩形的高度
rx: 對(duì)于圓角矩形,指橢圓在x軸方向的半徑
ry: 對(duì)于圓角矩形火窒,指橢圓在y軸方向的半徑

例如:

<svg width="100mm" height="100mm"> <rect x="20" y="20" width="50" height="50" style="stroke: #f36; fill: rgba(123,123,23,.5);"/> </svg>
坐標(biāo)系統(tǒng)
比例尺
  • 線性比例尺
    一個(gè)最簡(jiǎn)單的線性關(guān)系: y= 2x +1

在d3 的v4版本中链沼,運(yùn)行可得下列結(jié)果:

let yScale = d3.scaleLinear()
         .domain([0, 500])
         .range([0, 100]);

console.log( yScale(50) )  //10
console.log( yScale(250) )  // 50
console.log( yScale(450) )  //90
  • 序數(shù)比例尺
    定量比例尺的定義域和值域都是連續(xù)的,在實(shí)際的使用中沛鸵,很多時(shí)候定義域和值域都是是非連續(xù)的括勺,這時(shí)候我們就要用到序數(shù)比例尺了缆八。
let xScale = d3.scaleBand()
                .domain(["a", "b", "c", "d", "e"])
                .rangeRound([0, 100])

console.log(xScale("a"))  //0
console.log(xScale("d"))   //60
console.log(xScale("e"))    //80

好了,學(xué)習(xí)上面兩個(gè)知識(shí)點(diǎn)之后疾捍,我們開(kāi)始我們的柱狀圖繪制奈辰!

準(zhǔn)備的數(shù)據(jù)

const data =[
    {x:"上海", y:100},
    {x:"北京", y:200},
    {x:"天津", y:280},
    {x:"西安", y:100},
    {x:"武漢", y:240},
    {x:"長(zhǎng)沙", y:210},
    {x:"深圳", y:100},
    {x:"鄭州", y:220},
    {x:"駐馬店", y:410},
    {x:"信陽(yáng)", y:100},
    {x:"漯河", y:220},
    {x:"商丘", y:210},
    {x:"南陽(yáng)", y:100},
    {x:"紐約", y:220},
    {x:"南昌", y:210}
]

樣式

svg {
  box-sizing: content-box
}

界面初始化

在進(jìn)行渲染之前,我們會(huì)先在svg 各側(cè)預(yù)留padding乱豆,這里做的主要目的是為了坐標(biāo)軸數(shù)值部分超出的可以正常顯示奖恰。

   var initWidth = 340
    var initHeight = 500

    var padding = { left:40, top:20, right:10, bottom: 20}

    var height = initWidth - padding.top - padding.bottom
    var width  = initHeight - padding.left - padding.right


    var svg = d3.select("body")
                .append("svg")
                .attr("width", width)
                .attr("height", height)
                .style("padding-left", padding.left)
                .style("padding-right", padding.right)
                .style("padding-top", padding.top)
                .style("padding-bottom", padding.bottom)

此時(shí)效果如下:


初始效果

定義坐標(biāo)軸

         // y比例尺
        let ydata = data.map(function(e, i){ return e.y})  //拿到y(tǒng)軸所有數(shù)據(jù)
        let yScale = d3.scaleLinear()   //定義線性比例尺(數(shù)值型,等比縮放)
         .domain([0, d3.max(ydata)])    // 定義域
         .range([height , 0]);          //值域
         
        let _yScale = d3.scaleLinear()
         .domain([0, d3.max(ydata)])
         .range([0, height]); 

        ***上述yScale與 _yScale的差別就在于range恰恰相反宛裕,
        因此同樣的數(shù)值在運(yùn)算時(shí)拿到的正好是相反的數(shù)據(jù)瑟啃,
        而這在待會(huì)的坐標(biāo)軸數(shù)值計(jì)算和直方位置的計(jì)算中我們會(huì)用到***

        //定義y軸
        let yAxis = d3.axisLeft(yScale);   //這句話的意思是添加左側(cè)坐標(biāo)軸,比例尺使用yScale

        //添加y軸
        svg.append("g")
        .attr("class","axis")
        .attr("transform","translate(" + 0 + "," + 0 + ")")
        .call(yAxis);

     //添加x軸坐標(biāo)軸

         //x軸比例尺
         let xData = data.map(function(e, i){ return e.x})
         let xScale = d3.scaleBand()  //定義序數(shù)比例尺
                        .domain(xData)
                        .rangeRound([0, width])
                        .padding(0.1)
        //定義x軸
        let xAxis = d3.axisBottom(xScale)
        
        //添加x軸
         svg.append("g")
            .attr("class","axis--x")
            .attr("transform","translate(" + "0 ," + height + ")")
            .call(xAxis);

此時(shí)效果如下


預(yù)覽

繪制直方

    var rect = svg.selectAll("rect")
                  .data(data)
                  .enter()
                  .append("rect")
                  .attr("x", function(d, i){
                      return xScale(d.x)
                  })
                  .attr("y", function(d){
                      return height -  _yScale(d.y)
                  })
                  .attr("width", xScale.bandwidth())
                  .attr("height", function(d){
                      return _yScale(d.y)
                  })
                  .attr("fill", "steelBlue")

效果


預(yù)覽

接下來(lái)揩尸,我們可以在柱上添加文字


    var text = svg.append("g")
                .selectAll("text")
                .data(data)
                .enter()
                .append("text")
                .attr("x", function(d, i){
                      return xScale(d.x)
                  })
                .attr("y", function(d){
                      return height -  _yScale(d.y)
                })
                .attr("dy", "1em")
                .attr("dx", xScale.bandwidth() / 2)
                .attr("text-anchor", "middle")
                .attr("font-size", '14px')
                .attr("fill", "#fff")
                .text(function(d){
                    return d.y
                })

效果如下


預(yù)覽

我們可以給坐標(biāo)軸添加一些樣式讓他看起來(lái)活潑一些

 .axis--x path {
    display: none;
  }

鼠標(biāo)在上面移動(dòng)時(shí)我們可以給他添加一些樣式

var rect = svg.selectAll("rect")
        .........
                  .attr("fill", "steelBlue")
                  .on("mouseover",function(){
                      d3.select(this).attr("fill", "yellow")
                  })
                  .on("mouseout", function(){
                      d3.select(this).attr("fill","steelBlue")
                  })

預(yù)覽


預(yù)覽

接下來(lái)我們給它添加一些交互效果

點(diǎn)擊事件

這個(gè)很簡(jiǎn)單只需這樣一句

var rect = svg.selectAll("rect")
        .........
                  .on("click",function(d){
                       console.log(d.x+":"+d.y)
                  })

(框選和點(diǎn)擊不能同時(shí)存在)

框選
         var brush = svg.append("g")
             .attr("class", "brush")
            .call(d3.brushX()
                    .on("start", function(){     })  
                    .on("brush", function(){     } )
                    .on("end", function(e) {
                        var selection = d3.event.selection;
                        console.log(selection)  //可以拿到框選的x軸坐標(biāo)范圍蛹屿,我們通過(guò)這個(gè)數(shù)值拿到框選到的目標(biāo)就很簡(jiǎn)單啦
                    })
            )

最終效果


預(yù)覽
一個(gè)小案例: 使用柱狀圖動(dòng)態(tài)展示冒泡排序

冒泡排序可視化動(dòng)態(tài)展現(xiàn)

本文所有圖表源碼

好了,今天我們先學(xué)到這里岩榆,明天更新餅圖制作 错负!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市勇边,隨后出現(xiàn)的幾起案子犹撒,更是在濱河造成了極大的恐慌,老刑警劉巖粒褒,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件识颊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡奕坟,警方通過(guò)查閱死者的電腦和手機(jī)谊囚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)执赡,“玉大人镰踏,你說(shuō)我怎么就攤上這事∩澈希” “怎么了奠伪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)首懈。 經(jīng)常有香客問(wèn)我绊率,道長(zhǎng),這世上最難降的妖魔是什么究履? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任滤否,我火速辦了婚禮,結(jié)果婚禮上最仑,老公的妹妹穿的比我還像新娘藐俺。我一直安慰自己炊甲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布欲芹。 她就那樣靜靜地躺著卿啡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪菱父。 梳的紋絲不亂的頭發(fā)上颈娜,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音浙宜,去河邊找鬼官辽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛粟瞬,可吹牛的內(nèi)容都是我干的同仆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼亩钟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼乓梨!你這毒婦竟也來(lái)了鳖轰?” 一聲冷哼從身側(cè)響起清酥,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕴侣,沒(méi)想到半個(gè)月后焰轻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昆雀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年辱志,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狞膘。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡揩懒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挽封,到底是詐尸還是另有隱情已球,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布辅愿,位于F島的核電站智亮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏点待。R本人自食惡果不足惜阔蛉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望癞埠。 院中可真熱鬧状原,春花似錦聋呢、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至瓦呼,卻和暖如春喂窟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背央串。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工磨澡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人质和。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓稳摄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饲宿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子厦酬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容