綁定 DOM 元素跟資料的方法

selection.data( [data[,key]] )
1. 綁定單個元素跟數值

程式碼

          
            // html
            <p class="bindData"></p>
          
        
          
              //JS
              const bindData = d3.select('.bindData')
                                  .data(['綁定資料'])
                                  .text(d => d);
              
              // 印出綁定資料的 selection 來看看
              console.log('bindData', bindData)
              // 印出綁定的 data 來看看
              console.log(bindData['_groups'][0][0]['__data__'])
          
        
2.綁定多個元素跟數值

程式碼

          
            // html
            <p class="bindMultiData"></p>
            <p class="bindMultiData"></p>
            <p class="bindMultiData"></p>
            <p class="bindMultiData"></p>
          
        
          
              //JS
              const multiData = ['綁', '定', '資', '料']
              const bindMultiData = d3.selectAll('.bindMultiData')
                                          .data(multiData)
                                          .text(d => d);
                      
              // 印出綁定資料的 selection 來看看
              console.log('bindMultiData', bindMultiData)
          
        
3.綁定的元素與 data 數量不匹配

程式碼

          
            // html
            <p class="bindUnmatchData"></p>
            <p class="bindUnmatchData"></p>
          
        
          
              //JS
              const UnmatchData = ['綁', '定', '資', '料']
              const bindUnmatchData = d3.selectAll('.bindUnmatchData')
                                          .data(UnmatchData)
                                          .text(d => d);
                      
              // 印出綁定資料的 selection 來看看
              console.log('bindUnmatchData', bindUnmatchData)
          
        

selection.datum()

程式碼

            
              // html
              <p class="datum"></p>
            
          
            
              //JS
              const datumObj = [{name:'jin'}, {name:'JIN'}]
              const bindDatum = d3.select('.datum')
                                  .datum(datumObj)
              console.log('bindDatum',bindDatum)
            
          
selection.data( ) 與 selection.datum( ) 比較

程式碼

            
              // html
              <p class="join"></p>
            
          
            
              //JS
              const data = [{ name: "金金" }, { name: "JINJIN" }];
              const dataBinding = d3.select(".join").data(data);

              const dataArrayBinding = d3.select(".join").data([data]);

              const datumBinding = d3.select(".join").datum(data);
            
          
Rect: selection.data( ) & selection.datum( )

程式碼

            
              // html
              <svg class="rectContainer">
                <rect></rect>
                <rect></rect>
                <rect></rect>
                <rect></rect>
                <rect></rect>
              </svg>
            
          
            
              //JS
              const rectData = [10, 20, 30, 40];

              // data()
              const d3Data = d3.select(".rectContainer").selectAll("rect").data(rectData);
              console.log("d3Data", d3Data);

              // datum()
              const d3Datum = d3.select(".rectContainer").selectAll("rect").datum(rectData);
              console.log("d3Datum", d3Datum)
            
          

增減資料數量與DOM元素不匹配的方法

Update

程式碼

            
              // html
              <div class="updateData">
                <p></p>
                <p></p>
                <p></p>
                <p></p>
              </div>
            
          
            
              //JS
              const updateData = ["資", "料", "剛", "好"];
              const updateSelection = d3.select(".updateData")
                                        .selectAll("p")
                                        .data(updateData);
            
          
Enter

程式碼

              
                // html
                <div class="enterData">
                  <p></p>
                  <p></p>
                </div>
              
            
              
                //JS
                const enterData = ["資", "料", "比", "較", "多"];
                const enterSelection = d3.select(".enterData")
                                         .selectAll("p")
                                         .data(enterData)
                                         .text((d) => d);
              
            
Exit

程式碼

            
              // html
              <div class="exitData">
                <p></p>
                <p></p>
                <p></p>
                <p></p>
                <p></p>
                <p></p>
              </div>
            
          
            
              //JS
              const exitData = ["資", "料", "少"];
              const exitSelection = d3.select(".exitData")
                                      .selectAll("p")
                                      .data(exitData)
                                      .text((d) => d);
            
          
三種API
selection.enter()

程式碼

            
              // html
              <div class="enterData">
                <p></p>
                <p></p>
              </div>
            
          
            
                //JS
                const enterData = ["資", "料", "比", "較", "多"];
                const enterSelection = d3
                  .select(".enterData")
                  .selectAll("p")
                  .data(enterData)
                  .text((d) => d) 
                  .enter() ← 抓出缺少幾個DOM元素
                  .append("p") ← 把缺少的DOM元素加上去
                  .text((d) => d)
                  .classed("fw-bold", true)
                  .classed("text-danger", true);
            
          

selection.exit()

程式碼

            
              // html
              <div class="exitData">
                <p></p>
                <p></p>
                <p></p>
                <p></p>
                <p></p>
                <p></p>
              </div>
            
          
            
              //JS
              const exitData = ["資", "料", "少"];
              const exitSelection = d3.select(".exitData")
                                      .selectAll("p")
                                      .data(exitData)
                                      .text((d) => d)
                                      .exit() ← 抓出多餘的 DOM 元素
                                      .remove() ← 移除多餘的 DOM 元素
            
          

selection.join()

程式碼

            
              // html
              <div class="joinData"></div>
            
          
            
              //JS
              const joinData = ["j", "o", "i", "n"];

              d3.select(".joinData")
              .selectAll("p")
              .data(joinData)
              .join("p") ← 把 enter、update、exit 一併處理
              .attr("class", "text-danger")
              .text(d=>d)

              // 或帶入參數function
              d3.select(".joinData")
                .selectAll("p")
                .data(joinData)
                .join( ←  分別設定 enter、update、exit function
                    enter => enter.append("p")
                      .attr("class", "text-danger")
                      .text(d=>d),
                    update => update,
                    exit => exit.remove()
                );

            
          
selection.merge()
selection.merge API 主要是用在selection.join API內部,當資料綁定後處理 enter 與 update selection, 並依據 index 去填補原本是 null 的位置。 以下範例是將奇數資料與偶數資料合併,並呈現在右方框框內

原始資料

1
2
3
4
5

奇數資料

1
3
5

偶數資料

2
4
6

奇數資料與偶數資料合併後

程式碼

             
                //html
                <div class="text-center mergedData">
                  <p>原始資料</p>
                  <h6>1</h6>
                  <h6>2</h6>
                  <h6>3</h6>
                  <h6>4</h6>
                  <h6>5</h6>
                </div>

                <div class="border border-dark right text-center py-2 px-4 w-50 mergedContainer">
                  <p>奇數資料與偶數資料合併後
                  </p>
                </div>
             
            
              
                //JS
                const even = d3.select('.mergedData').selectAll("h6")
                                .select(function (d, i) {
                                    return i & 1 ? this : null
                                  });

                const odd = d3.select('.mergedData').selectAll("h6")
                              .select(function (d, i) {
                                  return i & 1 ? null : this
                              });
                    
                const merged = odd.merge(even);
                const mergedContainer = d3.select('.mergedContainer')
                for(const element of merged._groups[0]){
                  mergedContainer.append('p').text(element.innerText)
                }
              
            

範例圖表

data資料集:

程式碼

            
              // html
              <div>
                <label>資料數量</label>
                <input type="number" class="dataLength" />
                <button type="button" class="getRandomData">
                  點擊產生隨機資料
                </button>
              </div>
              <div>data資料集:<span class="showData"></span></div>
              <div class="chartWrap"></div>
            
          
            
              const getRandomData = document.querySelector(".getRandomData");
              const dataLength = document.querySelector("input");
              const showData = document.querySelector(".showData");
              let randomData = [];
        
              // 增加陣列
              getRandomData.addEventListener("click", (e) => {
                randomData.length = 0;
                for (i = 0; i < dataLength.value; i++) {
                  // 產生並塞入隨機亂數資料
                  let random = Math.floor(Math.random() * 5);
                  randomData.push(random);
                }
                // 畫面呈現目前資料集
                showData.innerHTML = randomData;
        
                // 繪製圖表
                drawDiagram();
              });
        
              // 建立 svg 畫布
              const rangeSelect = d3
                .select(".chartWrap")
                .append("svg")
                .attr("width", 400)
                .attr("height", 300)
                .style("border", "1px solid rgb(96, 96, 96)");
        
              // 製作圖表
              const drawDiagram = () => {
                // 綁定 update 資料
                let rects = rangeSelect.selectAll("rect").data(randomData);
        
                // 用 enter 加上少的DOM元素
                rects
                  .enter()
                  .append("rect")
                  .attr("width", (d) => d * 60)
                  .attr("height", 40)
                  .style("fill", "blue")
                  .attr("x", (d, index) => 0) // 設定x位置
                  .attr("y", (d, index) => index * 60); // 設定y位置

                // 更新 width 寬度
                rects.attr("width", (d) => d * 60);
        
                // 用 exit 移除多的 DOM 元素
                rects.exit().remove();
              };

              // 使用 join()
              const drawDiagram = () => {
                // 綁定 update 資料
                let rects = rangeSelect
                  .selectAll("rect")
                  .data(randomData)
                  .join(
                    (enter) =>
                      enter
                        .append("rect")
                        .attr("width", (d) => d * 60)
                        .attr("height", 40)
                        .style("fill", "blue")
                        .attr("x", (d, index) => 0) 
                        .attr("y", (d, index) => index * 60),
                    (update) => update.attr("width", (d) => d * 60),
                    (exit) => exit.remove()
                  );
              };

            
          
selection.on()
HiHi
            
              //html 
              <div class="selectionOn">HiHi</div>
              
              //JS
              const textToRed = (e) => {
                e.target.classList.add("fw-bold");
                e.target.style.color = "red";
              };
              d3.select(".selectionOn").on("click", textToRed);
            
          
selection.call()
金金永遠
            
              //html 
              <div>
                金金永遠 <span class="fw-bold selectionCall"></span> 歲
              </div>
              
              //JS
              const setAge = (selection, age) => {
                selection.text(age);
              };
              d3.select(".selectionCall").call(setAge, "19");