D3.js 比例函數(shù)

比例函數(shù)(Scale functions)

Scale 函數(shù)是 JavaScript 函數(shù)毫捣,它們:接受輸入(通常是數(shù)字详拙、日期或類別)并返回一個值(例如坐標(biāo)帝际、顏色、長度或半徑)饶辙。它們通常用于將(或“映射”)數(shù)據(jù)值轉(zhuǎn)換為視覺變量(例如位置蹲诀、長度和顏色)。

  • 構(gòu)建尺度

要創(chuàng)建線性比例弃揽,您可以使用:

let myScale = d3.scaleLinear();

myScale
  .domain([0, 100])
  .range([0, 800]);

myScale(0);    // returns 0
myScale(50);   // returns 400
myScale(100);  // returns 800
  • 縮放類型

D3 有大約 12 種不同的比例類型(scaleLinear脯爪、scalePow、scaleQuantise矿微、scaleOrdinal 等)痕慢,廣義上講它們可以分為 3 組:

  1. 具有連續(xù)輸入和連續(xù)輸出

  2. 具有連續(xù)輸入和離散輸出

  3. 具有離散輸入和離散輸出

    • 具有連續(xù)輸入和連續(xù)輸出

      • scaleLinear:使用線性函數(shù)y=mx+c在域和范圍內(nèi)進(jìn)行插值。
        let linearScale = d3.scaleLinear()
        .domain([0, 10])
        .range([0, 600]);
      
        linearScale(0);   // returns 0
        linearScale(5);   // returns 300
        linearScale(10);  // returns 600
      

      通常用于將數(shù)據(jù)值轉(zhuǎn)換為位置和長度涌矢。它們在創(chuàng)建條形圖掖举、折線圖和許多其他圖表類型時很有用。

      輸出范圍也可以指定為顏色:

          let linearScale = d3.scaleLinear()
          .domain([0, 10])
          .range(['yellow', 'red']);
      
          linearScale(0);   // returns "rgb(255, 255, 0)"
          linearScale(5);   // returns "rgb(255, 128, 0)"
          linearScale(10);  // returns "rgb(255, 0, 0)"
      
      • scaleSqrt:對于按面積(而不是半徑)確定圓的大小很有用娜庇。
          let sqrtScale = d3.scaleSqrt()
            .domain([0, 100])
            .range([0, 30]);
      
            sqrtScale(0);   // returns 0
            sqrtScale(50);  // returns 21.21...
            sqrtScale(100); // returns 30
      
      • scalePow:是更通用的版本scaleSqrt塔次。該比例使用冪函數(shù)y=mxk +c進(jìn)行插值。指數(shù)k使用.exponent()名秀。
        let powerScale = d3.scalePow()
        .exponent(0.5)
        .domain([0, 100])
        .range([0, 30]);
      
        powerScale(0);   // returns 0
        powerScale(50);  // returns 21.21...
        powerScale(100); // returns 30
      
      • scaleLog:使用對數(shù)函數(shù)y=m*log(x)+b進(jìn)行插值励负,當(dāng)數(shù)據(jù)具有指數(shù)性質(zhì)時可能很有用。
          let logScale = d3.scaleLog()
          .domain([10, 100000])
          .range([0, 600]);
      
          logScale(10);     // returns 0
          logScale(100);    // returns 150
          logScale(1000);   // returns 300
          logScale(100000); // returns 600
      
      • scaleTime:類似于匕得,scaleLinear除了域表示為日期數(shù)組熄守。(在處理時間序列數(shù)據(jù)時非常有用。)
          timeScale = d3.scaleTime()
            .domain([new Date(2016, 0, 1), new Date(2017, 0, 1)])
            .range([0, 700]);
      
          timeScale(new Date(2016, 0, 1));   // returns 0
          timeScale(new Date(2016, 6, 1));   // returns 348.00...
          timeScale(new Date(2017, 0, 1));   // returns 700
      
      • scaleSequential:用于將連續(xù)值映射到由預(yù)設(shè)(或自定義)插值器確定的輸出范圍耗跛。(插值器是一個函數(shù)裕照,它接受 0 到 1 之間的輸入并輸出兩個數(shù)字、顏色调塌、字符串等之間的插值晋南。)
         let sequentialScale = d3.scaleSequential()
           .domain([0, 100])
           .interpolator(d3.interpolateRainbow);
      
         sequentialScale(0);   // returns 'rgb(110, 64, 170)'
         sequentialScale(50);  // returns 'rgb(175, 240, 91)'
         sequentialScale(100); // returns 'rgb(110, 64, 170)'
      

      還有一個插件d3-scale-chromatic,它提供了眾所周知的ColorBrewer配色方案羔砾。

      • Clamping:默認(rèn)情況下當(dāng)輸入值超出域時负间,scaleLinearscalePow姜凄、scaleSqrt政溃、scaleLogscaleTimescaleSequential仍會計算态秧。
          let linearScale = d3.scaleLinear()
          .domain([0, 10])
          .range([0, 100]);
      
          linearScale(20);  // returns 200
          linearScale(-10); // returns -100
      

      可以通過使用以下方法限制縮放功能董虱,以便輸入值保持在域內(nèi).clamp

          linearScale.clamp(true);
      
          linearScale(20);  // returns 100
          linearScale(-10); // returns 0
      

      您可以使用 .clamp(false)關(guān)閉。

      • Nice:如果域是根據(jù)實際數(shù)據(jù)自動計算的(例如,通過使用d3.extent)愤诱,則開始值和結(jié)束值可能不是整數(shù)云头。這不一定是個問題,但它可能看起來有點不整潔淫半。因此溃槐,D3.nice()提供了一個刻度函數(shù),它將域四舍五入到“不錯”的舍入值科吭。
          let data = [0.243, 0.584, 0.987, 0.153, 0.433];
          let extent = d3.extent(data);
      
          let linearScale = d3.scaleLinear()
            .domain(extent)
            .range([0, 100])
            .nice();
      

      請注意昏滴,.nice()每次更新域時都必須調(diào)用。

      • Multiple segments:scaleLinear, scalePow, scaleSqrt, scaleLog and scaleTime通常由兩個值組成对人,但如果您提供 3 個或更多值谣殊,則會細(xì)分為多個段
          let linearScale = d3.scaleLinear()
            .domain([-10, 0, 10])
            .range(['red', '#ddd', 'blue']);
      
          linearScale(-10);  // returns "rgb(255, 0, 0)"
          linearScale(0);    // returns "rgb(221, 221, 221)"
          linearScale(5);    // returns "rgb(111, 111, 238)"
      
      • Inversion:

      • 該方法允許您在給定輸出.invert()值的情況下確定縮放函數(shù)的輸入值(假設(shè)縮放函數(shù)具有數(shù)值域):

            let linearScale = d3.scaleLinear()
              .domain([0, 10])
              .range([0, 100]);
        
            linearScale.invert(50);   // returns 5
            linearScale.invert(100);  // returns 10
        
    • 具有連續(xù)輸入和離散輸出

      • scaleQuantize:接受連續(xù)輸入并輸出由范圍定義的多個離散量。
          let quantizeScale = d3.scaleQuantize()
            .domain([0, 100])
            .range(['lightblue', 'orange', 'lightgreen', 'pink']);
      
          quantizeScale(10);  // returns 'lightblue'
          quantizeScale(30);  // returns 'orange'
          quantizeScale(90);  // returns 'pink'
      
      • scaleQuantile:將連續(xù)數(shù)字輸入映射到離散值规伐。域由數(shù)字?jǐn)?shù)組定義
          let myData = [0, 5, 7, 10, 20, 30, 35, 40, 60, 62, 65, 70, 80, 90, 100];
      
          let quantileScale = d3.scaleQuantile()
              .domain(myData)
              .range(['lightblue', 'orange', 'lightgreen']);
      
          quantileScale(0);   // returns 'lightblue'
          quantileScale(20);  // returns 'lightblue'
          quantileScale(30);  // returns 'orange'
          quantileScale(65);  // returns 'lightgreen'
      
      • scaleThreshold:將連續(xù)數(shù)值輸入映射到范圍定義的離散值蟹倾。指定n-1 個域分割點匣缘,其中n是范圍值的數(shù)量(即range的數(shù)量)猖闪。
          let thresholdScale = d3.scaleThreshold()
            .domain([0, 50, 100])
            .range(['#ccc', 'lightblue', 'orange', '#ccc']);
      
          thresholdScale(-10);  // returns '#ccc'
          thresholdScale(20);   // returns 'lightblue'
          thresholdScale(70);   // returns 'orange'
          thresholdScale(110);  // returns '#ccc'
      
    • 具有離散輸入和離散輸出

      • scaleOrdinal:將離散值(由數(shù)組指定)映射到離散值(也由數(shù)組指定)。域數(shù)組指定可能的輸入值肌厨,范圍數(shù)組指定輸出值培慌。如果范圍數(shù)組比域數(shù)組短,則范圍數(shù)組將重復(fù)柑爸。
          let myData = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
      
          let ordinalScale = d3.scaleOrdinal()
            .domain(myData)
            .range(['black', '#ccc', '#ccc']);
      
          ordinalScale('Jan');  // returns 'black';
          ordinalScale('Feb');  // returns '#ccc';
          ordinalScale('Mar');  // returns '#ccc';
          ordinalScale('Apr');  // returns 'black';
      

      默認(rèn)情況下吵护,如果將不在域中的值用作輸入,則比例尺將隱式將該值添加到域中表鳍。

      如果這不是所需的行為馅而,您可以使用以下命令為未知值指定輸出值.unknown()

      • scaleBand:有助于創(chuàng)建條形圖譬圣,同時考慮每個條形之間的間隔瓮恭。域被指定為一組值(每個波段一個值),范圍為波段的最小和最大范圍(例如條形圖的總寬度)厘熟。

        實際上scaleBand會將范圍拆分為n 個帶區(qū)(其中n是域數(shù)組中的值的數(shù)量)屯蹦,并考慮在指定間隔的情況下計算條形圖的位置和寬度。

          let bandScale = d3.scaleBand()
            .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
            .range([0, 200]);
      
          bandScale('Mon'); // returns 0
          bandScale('Tue'); // returns 40
          bandScale('Fri'); // returns 160
      

      可以使用.bandwidth()訪問每個波段的寬度

      可以配置兩種類型的間隔:1.paddingInner它指定(作為帶寬的百分比)每個帶之間的填充量;2.paddingOuter它指定(作為帶寬的百分比)第一個帶之前和最后一個帶之后的填充量

      • scalePoint:創(chuàng)建從一組離散值映射到指定范圍內(nèi)等距的點
          let pointScale = d3.scalePoint()
            .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
            .range([0, 500]);
      
          pointScale('Mon');  // returns 0
          pointScale('Tue');  // returns 125
          pointScale('Fri');  // returns 500
      

      可以使用法.step()訪問點之間的距離

      外部填充(間隔)可以指定為填充與點間距的比率绳姨。例如登澜,要使外部填充為點間距的四分之一,請使用值 0.25

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載飘庄,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者脑蠕。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跪削,隨后出現(xiàn)的幾起案子空郊,更是在濱河造成了極大的恐慌份招,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狞甚,死亡現(xiàn)場離奇詭異锁摔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)哼审,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門谐腰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涩盾,你說我怎么就攤上這事十气。” “怎么了春霍?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵砸西,是天一觀的道長。 經(jīng)常有香客問我址儒,道長芹枷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任莲趣,我火速辦了婚禮鸳慈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喧伞。我一直安慰自己走芋,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布潘鲫。 她就那樣靜靜地躺著翁逞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溉仑。 梳的紋絲不亂的頭發(fā)上挖函,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機(jī)與錄音彼念,去河邊找鬼挪圾。 笑死,一個胖子當(dāng)著我的面吹牛逐沙,可吹牛的內(nèi)容都是我干的哲思。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吩案,長吁一口氣:“原來是場噩夢啊……” “哼棚赔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤靠益,失蹤者是張志新(化名)和其女友劉穎丧肴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胧后,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芋浮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了壳快。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纸巷。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖眶痰,靈堂內(nèi)的尸體忽然破棺而出瘤旨,到底是詐尸還是另有隱情,我是刑警寧澤竖伯,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布存哲,位于F島的核電站,受9級特大地震影響七婴,放射性物質(zhì)發(fā)生泄漏祟偷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一本姥、第九天 我趴在偏房一處隱蔽的房頂上張望肩袍。 院中可真熱鬧杭棵,春花似錦婚惫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滓侍,卻和暖如春蒋川,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撩笆。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工捺球, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夕冲。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓氮兵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親歹鱼。 傳聞我的和親對象是個殘疾皇子泣栈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

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