動畫 Transitions

一般改變位置

程式碼

          
            // html
            <svg class="move" 
                 style="border: 1px solid rgb(103, 102, 102)">
            </svg>
            <button type="button" class="moveBtn">
              移動
            </button>
          
        
          
            // js
            const moveRect = d3
            .select(".move")
            .append("rect")
            .attr("width", 40)
            .attr("height", 40)
            .attr("fill", "#f68b47")
            .attr("stroke", "#f68b47");
    
          document.querySelector(".moveBtn")
              .addEventListener("click", ()=> {
                  moveRect.attr("transform", "translate(140, 60)");
                });
          
        
selection.transition([name])

程式碼

          
            const transitionRect = d3
              .select(".transition")
              .append("rect")
              .attr("width", 40)
              .attr("height", 40)
              .attr("fill", "#f68b47")
              .attr("stroke", "#f68b47");
    
            document
              .querySelector(".transitionBtn")
              .addEventListener("click", ()=> {
                transitionRect.transition()
                            .attr("transform", "translate(140, 60)");
              });
          
        
transition.duration([value])

程式碼

          
          const durationRect = d3
            .select(".duration")
            .append("rect")
            .attr("width", 40)
            .attr("height", 40)
            .attr("fill", "#f68b47")
            .attr("stroke", "#f68b47");
    
          document.querySelector(".moveBtn")
                  .addEventListener("click", () => {
                    moveRect
                      .transition()
                      .duration(5000) // 設定動畫時間持續5秒鐘
                      .attr("transform", "translate(140, 60)");
                  });
          
        
transition 改變顏色、邊框粗細

程式碼

          
            // html
            <svg class="transitionColor"
                 style="border: 1px solid rgb(103, 102, 102)"></svg>
            <button type="button" class="transitionColorBtn">
              改變
            </button>
          
        
          
            // js
          const transitionColor = d3
            .select(".transitionColor")
            .append("rect")
            .attr("width", 40)
            .attr("height", 40)
            .attr("fill", "#f68b47")
            .attr("stroke", "#f68b47")
            .attr("transform", "translate(120, 50)");
    
          document
            .querySelector(".transitionColorBtn")
            .addEventListener("click", () => {
              transitionColor
                .transition()
                .duration(1000)
                .attr("fill", "green")
                .attr("stroke-width", "6px")
                .attr("stroke", "red");
            });
          
        
transition.delay([value])

程式碼

          
            //html 
            <svg class="delay"
                 style="border: 1px solid rgb(103, 102, 102)">
            </svg>
            <button type="button" 
                    class="mt-3 btn d-block btn-primary delayBtn">
              delay
            </button>
          
        
          
            // js
            const dataDelay = [160, 140, 120, 100, 80, 60, 40, 20];
            const delay = d3
              .select(".delay")
              .selectAll("circle")
              .data(dataDelay)
              .enter()
              .append("circle")
              .attr("cx", (d) => d)
              .attr("cy", 30)
              .attr("r", 15)
              .attr("fill", "blue")
              .attr("opacity", "0.5");
      
            document.querySelector(".delayBtn")
                    .addEventListener("click", () => {
                      delay
                        .transition()
                        .delay((d, i) => i * 200) // 分別延遲
                        .attr("cx", (d) => d + 120); // 位移距離
                    });
          
        
transition.ease([value])

程式碼

          
            // html
            <svg class="ease" 
                 style="border: 1px solid rgb(103, 102, 102)"></svg>
            <div class="d-flex align-items-baseline">
              <select name="ease" id="ease" class="m-3">
                <option value=""></option>
              </select>
              <button
                type="button"
                class="mt-3 btn btn-primary easeBtn"
                onClick="updateEast()"
              >
                Ease開始
              </button>
            </div>
          
        
          
            // js
            const easeDot = d3
                  .select(".ease")
                  .append("circle")
                  .attr("cx", 40)
                  .attr("cy", 40)
                  .attr("r", 30)
                  .attr("fill", "#f68b47");
      
            // 抓出 d3.js 所有API中,名稱帶有ease的API
            const easeNames = Object
                    .keys(d3)
                    .filter((d) => d.slice(0, 4) === "ease");
      
            d3.select("#ease")
              .selectAll("option")
              .data(easeNames)
              .join("option")
              .attr("value", (d) => d)
              .text((d) => `d3.${d}`);
      
            const updateEast = () => {
              const easeName = d3.select("#ease").node().value;
              easeDot
                // 回原點
                .attr("cx", 40)
                .transition()
                // 設定動畫效果
                .ease(d3[easeName])
                .attr("cx", 200);
            };
    
          
        
transition.on(typenames[, listener]) 無限循環動畫

程式碼

          
            // html
            <svg
              class="loopAnimation"
              style="border: 1px solid rgb(103, 102, 102)">
            </svg>
          
        
          
            // js
            const loop = d3
              .select(".loopAnimation")
              .append("circle")
              .attr("cx", 50)
              .attr("cy", 50)
              .attr("r", 25)
              .attr("fill", "#f68b47")
              .transition()
              .duration(2000)
              .on("start", goRight);
      
            function goRight() {
              d3.active(this)
                .attr("cx", 200)
                .transition()
                .on("start", goLeft);
            }
      
            function goLeft() {
              d3.active(this)
                .attr("cx", 50)
                .transition()
                .on("start", goRight);
            }
          
        
圖表動畫

程式碼

          
            // html
            <div class="chartAnimation"></div>
            <button type="button" class="chartAnimationBtn">
              動畫開始
            </button>
          
        
          
            // js
            //定義兩個資料,都是Y值,x值就用陣列索引即可
            const data1 = [
              150, 122, 133, 161, 116, 139, 143, 115, 193, 137, 122, 141,
            ];
            const data2 = [
              180, 146, 180, 172, 133, 149, 152, 138, 188, 192, 117, 146,
            ];
      
            // svg
            const svg = d3
              .select(".chartAnimation")
              .append("svg")
              .attr("width", 500)
              .attr("height", 300);
      
            svg
              .selectAll("rect")
              .data(data1)
              .enter()
              .append("rect")
              .attr("x", 0)
              .attr("y", (d, i) => i * 30)
              .attr("width", (d, i) => d)
              .attr("height", 20)
              .attr("fill", "#f68b47");
      
            // 動畫開始
            d3.select(".chartAnimationBtn").on("click", () => {
              svg
                .selectAll("rect")
                .data(data2) // 資料變化
                .transition() // 加上動畫
                .duration(1000) // 點擊之後每條長柱會在1秒內到達更新位置
                // 每條長柱各自delay後開始動畫,
                // delay 時間乘上index,產生從上至下更新的動畫效果
                .delay((d, i) => 200 * i)
                .attr("width", (d, i) => d)
                .attr("fill", "#66f9ff");
            });