[HTML] 使用anime.js實現Win10 LodingRing 的樣式

預覽

廢話不多說,先來預覽一下效果(windows 原生的 lodingring 在uwp應用中的樣式可以在windows sdk中找到,我將其移植到了WPF中*)

  • WPF中樣式
    在這裏插入圖片描述
  • JS樣式
    在這裏插入圖片描述
    當然了,JS中動畫的參數也是我根據UWP移植過來的(無情的搬運工)
    可以看到,動畫基本如出一轍
實現

作爲一名c#開發者,現在還做WPF桌面應用的應該已經絕無僅有了,但是我最初學這個框架也是被Windows和VisualStudio的扁平UI吸引的。在WPF中可以相對容易的同步應用與Windows的風格,包括一些系統UI的樣式。
好了,廢話不多說,來看今天的主角 —— Win10加載圓環

我給你們看看WPF動畫的源碼吧

   <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1"
                                                                   Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="0">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2"
                                                                       Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="00:00:00.167">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3"
                                                                       Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="00:00:00.334">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4"
                                                                       Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="00:00:00.501">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5"
                                                                       Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="00:00:00.668">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6"
                                                                       Storyboard.TargetProperty="Opacity"
                                                                       BeginTime="00:00:00.835">
                                            <DiscreteDoubleKeyFrame KeyTime="0"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"
                                                                    Value="1" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"
                                                                    Value="0" />
                                            <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"
                                                                    Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1R"
                                                                       BeginTime="0"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-110"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="10"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="93" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="205"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="357"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="439" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="585"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2R"
                                                                       BeginTime="00:00:00.167"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-116"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="4"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="87" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="199"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="351"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="433" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="579"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3R"
                                                                       BeginTime="00:00:00.334"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-122"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="-2"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="81" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="193"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="345"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="427" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="573"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4R"
                                                                       BeginTime="00:00:00.501"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-128"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="-8"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="187"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="339"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="421" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="567"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5R"
                                                                       BeginTime="00:00:00.668"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-134"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="-14"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="69" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="181"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="331"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="415" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="561"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6R"
                                                                       BeginTime="00:00:00.835"
                                                                       Storyboard.TargetProperty="Angle">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                                                  Value="-140"
                                                                  KeySpline="0.13,0.21,0.1,0.7" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.433"
                                                                  Value="-20"
                                                                  KeySpline="0.02,0.33,0.38,0.77" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.2"
                                                                  Value="63" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:1.617"
                                                                  Value="175"
                                                                  KeySpline="0.57,0.17,0.95,0.75" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.017"
                                                                  Value="325"
                                                                  KeySpline="0,0.19,0.07,0.72" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:2.783"
                                                                  Value="409" />
                                            <SplineDoubleKeyFrame KeyTime="0:0:3.217"
                                                                  Value="555"
                                                                  KeySpline="0,0,0.95,0.37" />
                                        </DoubleAnimationUsingKeyFrames>

由於是 xaml 生成的動畫,沒辦法循環設置參數(UWP源碼中也是如此),當時看到的時候就在想,調這個參數的美工真TM是個天才…
可以看到,其中有許多的貝塞爾緩動關鍵幀,要是用原生CSS3實現的話似乎有些麻煩,而且也不知道切換緩動函數的時候潤不潤,不潤的話就很難受了,於是我就找到了anime.js這個動畫庫,剛好發現了其可以實現這個級別的動畫。

/**
 * @param  {} size     : int        the rect clip width of the loding svg
 * @param  {} dotsize  : int        the r of a loading dot
 * @param  {} dotcolor : "#xxxxxx"  the color of the dot
 */
function CreateLodingRing(size, dotsize, dotcolor) {
  //#region Create Element
  var ring = Object();

  let loadingring = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  loadingring.id = "winloding";
  loadingring.setAttribute("viewBox", "0 0" + " " + size + " " + size);
  for (let i = 0; i < 6; i++) {
    let dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    dot.style.transformOrigin = "center center";
    dot.style.opacity = 0;
    dot.setAttribute("class", "d" + (i + 1));
    dot.setAttribute("fill", dotcolor);
    dot.setAttribute("cx", size / 2);
    dot.setAttribute("cy", dotsize + 2);
    dot.setAttribute("r", dotsize);
    loadingring.appendChild(dot);
  }
  document.body.appendChild(loadingring);
  console.log(loadingring);

  //#endregion
  var tl = anime.timeline({
    loop: true
  });
  // #region add animation
  // tl.add({
  //   targets: "#winloding d1",
  //   rotate: [
  //     { value: -110, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //     { value: 10, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //     { value: 93, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //     { value: 205, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //     { value: 357, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //     { value: 439, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //     { value: 585, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //   ]
  // })
  //   .add(
  //     {
  //       targets: "#winloding d2",
  //       rotate: [
  //         { value: -116, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //         { value: 4, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //         { value: 87, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 199, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //         { value: 351, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //         { value: 433, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 579, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //       ]
  //     },
  //     167
  //   )
  //   .add(
  //     {
  //       targets: "#winloding d3",
  //       rotate: [
  //         { value: -122, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //         { value: -2, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //         { value: 81, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 193, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //         { value: 345, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //         { value: 427, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 573, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //       ]
  //     },
  //     334
  //   )
  //   .add(
  //     {
  //       targets: "#winloding d4",
  //       rotate: [
  //         { value: -128, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //         { value: -8, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //         { value: 75, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 187, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //         { value: 339, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //         { value: 421, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 567, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //       ]
  //     },
  //     501
  //   )
  //   .add(
  //     {
  //       targets: "#winloding d5",
  //       rotate: [
  //         { value: -134, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //         { value: -14, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //         { value: 69, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 181, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //         { value: 331, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //         { value: 415, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 561, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //       ]
  //     },
  //     668
  //   )
  //   .add(
  //     {
  //       targets: "#winloding d6",
  //       rotate: [
  //         { value: -140, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
  //         { value: -20, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
  //         { value: 63, duration: 767, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 175, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
  //         { value: 325, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
  //         { value: 409, duration: 766, easing: "cubicBezier(0, 0, 1, 1)" },
  //         { value: 555, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
  //       ]
  //     },
  //     835
  //   );
  // #endregion

  for (let i = 0; i < 6; i++) {
    let basevalue = -110 - 6 * i;

    tl.add(
      {
        targets: "#winloding .d" + (i + 1),
        rotate: [
          { value: basevalue, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
          { value: basevalue + 120, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
          { value: basevalue + 203, duration: 767, easing: "linear" },
          { value: basevalue + 315, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
          { value: basevalue + 467, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
          { value: basevalue + 549, duration: 766, easing: "linear" },
          { value: basevalue + 695, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
        ],
        opacity: [
          { value: 1, duration: 1, easing: "linear" },
          { value: 1, duration: 3210, easing: "linear" },
          { value: 0, duration: 10, easing: "linear" },
          { value: 0, duration: 260, easing: "linear" }
        ]
      },
      167 * i
    );
  }

  ring.timeline = tl;
  ring.svgitem = loadingring;

  return ring;
}

JS中的參數與WPF一模一樣,這應該是最貼近Win10原版的動畫樣式了[狗頭](不常用JS,寫的不好請見諒)。

解釋一下 (*)標註的問題,由於WPF動畫不能將動畫參數作爲動態綁定源,因此和UWP中的實現是稍微有區別的,不是複製粘貼就行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章