探祕神奇的運動路徑動畫 Motion Path

CSS 中有一個很是有意思的模塊 -- CSS Motion Path Module Level 1,翻譯過來也就是運動路徑。本文將對 motion path 一探究竟,經過本文,你能夠了解到:前端

  • 什麼是 CSS motion path
  • 使用 CSS motion path 製做簡單路徑動畫
  • 使用 CSS motion path 製做複雜路徑動畫

什麼是 CSS Motion Path 運動路徑?

什麼是 CSS Motion Path 運動路徑?利用這個規範規定的屬性,咱們能夠控制元素按照特定的路徑進行位置變換的動畫。而且,這個路徑能夠是很是複雜的一條路徑。git

在進一步介紹 CSS Motion Path 以前,咱們先看看使用傳統的 CSS 的能力,咱們如何實現路徑動畫。github

CSS 傳統方式實現直線路徑動畫

在以前,咱們但願將一個物體從 A 點直線運動到 B 點,一般而言可使用 transform: translate()top | left | bottom | right 或者 是 margin 之類的能夠改變物體位置的屬性。瀏覽器

簡單的一個 Demo:markdown

<div>
複製代碼
div {
    width: 60px;
    height: 60px;
    background: #000;
    animation: move infinite 1s alternate linear;
}
@keyframes move {
    100% {
        transform: translate(100px, 100px);
    }
}
複製代碼

對於簡單的從 A 點直線運動到 B 點的效果以下:svg

CSS 傳統方式實現曲線路徑動畫

固然,CSS 也能夠實現一些簡單的曲線路徑動畫的。若是咱們但願從 A 點運動到 B 點走的不是一條直線,而是一條曲線,該怎麼作呢?oop

對於一些簡單的圓弧曲線路徑,仍是能夠藉助一些巧妙的辦法實現的,看看下面這個例子。動畫

此次,咱們使用了兩個元素,子元素是但願被曲線運動的小球,可是實際上咱們是經過設定了父元素的 transform-origin,讓父元素進行了一個 transform: rotate() 的運動帶動了子元素的小球:ui

<div class="g-container">
    <div class="g-ball"></div>
</div>
複製代碼
.g-container {
    position: relative;
    width: 10vmin;
    height: 70vmin;
    transform-origin: center 0;
    animation: rotate 1.5s infinite alternate;
}
.g-ball {
    position: absolute;
    width: 10vmin;
    height: 10vmin;
    border-radius: 50%;
    background: radial-gradient(circle, #fff, #000);
    bottom: 0;
    left: 0;
}
@keyframes rotate {
    100% {
        transform: rotate(90deg);
    }
}
複製代碼

爲了方便理解,在運動的過程當中,我讓父元素的輪廓顯現出來:spa

這樣,咱們算是勉強獲得了一個非直線路徑運動動畫,它的實際運動軌跡是一條曲線。

然而,這基本上是以前 CSS 能作到的極限了,使用純 CSS 的方法,沒辦法實現更復雜的路徑動畫,譬以下面這樣一條路徑動畫:

直到如今,咱們有了一種更爲強大的專門作這個事情的規範,也就是本文的主角 -- CSS Motion Path

CSS Motion Path 實現直線路徑動畫

CSS Motion Path 規範主要包含如下幾個屬性:

  • offset-path:接收一個 SVG 路徑(與 SVG 的path、CSS 中的 clip-path 相似),指定運動的幾何路徑
  • offset-distance:控制當前元素基於 offset-path 運動的距離
  • offset-position:指定 offset-path 的初始位置
  • offset-anchor:定義沿 offset-path 定位的元素的錨點。 這個也算好理解,運動的元素可能不是一個點,那麼就須要指定元素中的哪一個點附着在路徑上進行運動
  • offset-rotate:定義沿 offset-path 定位時元素的方向,說人話就是運動過程當中元素的角度朝向

下面,咱們使用 Motion Path 實現一個簡單的直線位移動畫。

<div>
複製代碼
div {
    width: 60px;
    height: 60px;
    background: linear-gradient(#fc0, #f0c);
    offset-path: path("M 0 0 L 100 100");
    offset-rotate: 0deg;
    animation: move 2000ms infinite alternate ease-in-out;
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}
複製代碼

offset-path 接收一個 SVG 的 path 路徑,這裏咱們的路徑內容是一條自定義路徑 path("M 0 0 L 100 100"),翻譯過來就是從 0 0 點運動到 100px 100px 點。

offset-path 接收一個 SVG 路徑,指定運動的幾何路徑。與 SVG 的path、CSS 中的 clip-path 相似,對於這個 SVG Path 還不太瞭解的能夠戳這裏先了解下 SVG 路徑內容:SVG 路徑

咱們會獲得以下結果:

經過控制元素的 offset-distance0% 變化到 100% 進行元素的路徑動畫。

固然,上述的動畫是最基本的,我能夠充分利用 path 的特性,增長多箇中間關鍵幀,稍微改造下上述代碼:

div {
    // 只改變運動路徑,其餘保持一致
    offset-path: path("M 0 0 L 100 0 L 200 0 L 300 100 L 400 0 L 500 100 L 600 0 L 700 100 L 800 0");
    animation: move 2000ms infinite alternate linear;
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}
複製代碼

這裏最主要仍是運用了 path 中的 L 指令,獲得了以下圖這樣一條直線路徑:

image

最終的效果以下,與利用 transform: translate() 添加多個關鍵幀相似:

完整的 Demo 你能夠戳這裏:CodePen Demo -- CSS Motion Path Demo

CSS Motion Path 實現曲線路徑動畫

上面的運動軌跡都是由直線構成,下面咱們看看如何使用 CSS Motion Path 實現曲線路徑動畫。

其實原理仍是如出一轍,只須要在 offset-path: path() 中添加曲線相關的路徑便可。

在 SVG 的 Path 中,咱們取其中一種繪製曲線的方法 -- 貝塞爾曲線,譬以下述這條 path,其中的 path 爲 d="M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80"

<svg width="400" height="160" xmlns="http://www.w3.org/2000/svg">
  <path d="M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80" stroke="black" fill="transparent"/>
</svg>
複製代碼

對應這樣一條連續的貝塞爾曲線:

將對應的路徑應用在 offset-path: path 中:

<div>
複製代碼
div:nth-child(2) {
    width: 40px;
    height: 40px;
    background: linear-gradient(#fc0, #f0c);
    offset-path: path('M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80');
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}
複製代碼

能夠獲得以下運動效果:

能夠看到,元素是沿着貝塞爾曲線的路徑進行運動的,而且,因爲此次沒有限制死 offset-rotate,元素的朝向也是跟隨路徑的朝向一直變化的。(能夠聯想成開車的時候,車頭一直跟隨道路會進行變化的,帶動整個車身的角度變化)

完整的 Demo 你能夠戳這裏:CodePen Demo -- CSS Motion Path Demo

理解 offset-anchor 運動錨點

OK,那麼接下來,咱們再看看 offset-anchor 如何理解。

仍是上述的 DEMO,咱們把小正方形替換成一個三角形,而且把運動的曲線給畫到頁面上,像是這樣:

其中,三角形是經過 clip-path 實現的:

width: 40px;
    height: 40px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    background: linear-gradient(#fc0, #f0c);
複製代碼

一般而言,沿着曲線運動的是物體的中心點(類比 transform-origin),在這裏,咱們能夠經過 offset-anchor 改變運動的錨點,譬如,咱們但願三角形的最下方沿着曲線運動:

.ball {
    width: 40px;
    height: 40px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    offset-path: path('M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80');
    offset-anchor: 0 100%;
    background: linear-gradient(#fc0, #f0c);
    animation: move 3000ms infinite alternate linear;
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}
複製代碼

通過實測,Can i use 上寫着 offset-anchor 屬性的兼容性在爲 Chrome 79+、Firefox 72+,可是實際只有 Firefox 支持,Chrome 下暫時沒法生效~

完整的 Demo 你能夠戳這裏:CodePen Demo -- CSS Motion Path offset-anthor Demo

運用 Motion Path 製做動畫效果

OK,上面咱們基本把原理給過了一遍,下面咱們就看看,運用 Motion Path,能夠在實踐中如何運用。

利用 Motion Path 製做按鈕效果

利用運動路徑,咱們能夠製做一些簡單的按鈕點擊效果。在以前,我在 CodePen 上見到過這樣一種按鈕點擊效果:

其原理是運用了 background-radial 去生成每個小圓點,經過控制 background-position 控制小圓點的位移,詳細的 Demo 代碼你能夠戳這裏:

CodePen Demo -- Bubbly button (Design by Gal Shir)

可是小圓點的運動路徑基本上都是直線,運用本文的 Motion Path,咱們也能夠實現一些相似的效果,核心代碼以下,HTML 這裏咱們使用了 Pug 模板,CSS 使用了 SASS

.btn
  -for(var i=0; i<60; i++)
    span.dot
複製代碼
.btn {
  position: relative;
  padding: 1.5rem 4.5rem;
}
.btn .dot {
  position: absolute;
  width: 4px;
  height: 4px;
  
  @for $i from 1 through $count { 
    &:nth-child(#{$i}) {
        top: 50%;
        left: 50%;
        transform: translate3d(-50%, -50%, 0) rotate(#{360 / $count * $i}deg);
      }
  }
  
  &::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    offset-path: path("M0 1c7.1 0 10.7 2 14.3 4s7.1 4 14.3 4 10.7-2 14.3-4 7.2-4 14.3-4 10.7 2 14.3 4 7.1 4 14.3 4 10.7-2 14.3-4 7.1-4 14.3-4 10.7 2 14.3 4 7.1 4 14.3 4 10.7-2 14.3-4 7.1-4 14.3-4 10.7 2 14.3 4 7.1 4 14.3 4");
    offset-distance: 0;
  }
}

.btn.is-animating:active .dot:nth-child(4n+1)::before {
  animation: dot var(--animation-time) var(--animation-timging-function);
}
.btn.is-animating:active .dot:nth-child(4n+2)::before {
  border: 1px solid var(--color-primary);
  background: transparent;
  animation: dot var(--animation-time) var(--animation-timging-function) 0.1s;
}
.btn.is-animating:active .dot:nth-child(4n+3)::before {
  animation: dot var(--animation-time) var(--animation-timging-function) 0.2s;
}
.btn.is-animating:active .dot:nth-child(4n)::before {
  border: 1px solid var(--color-primary);
  background: transparent;
  animation: dot var(--animation-time) var(--animation-timging-function) 0.3s;
}

@keyframes dot {
  0% {
    offset-distance: 0%;
    opacity: 1;
  }
  90% {
    offset-distance: 60%;
    opacity: .5;
  }
  100% {
    offset-distance: 100%;
    opacity: 0;
  }
}
複製代碼

別看代碼多有一點點複雜,可是不難理解,本質就是給每一個子元素小點點設置一樣的 offset-path: path(),給不一樣分組下的子元素設定不一樣的旋轉角度,而且利用了動畫延遲 animation-delay 設定了 4 組同時出發的動畫。

這裏咱們的軌跡 path 不是直線,效果以下:

完整的代碼你能夠戳這裏:

CodePen Demo -- Button Animation with CSS Offset Paths

利用 Motion-Path 繪製地圖路徑尋路動畫

這個也是很是實用的,如今咱們能夠徹底利用 CSS Motion-Path 實現地圖上的尋路動畫:

該 Demo 源自 Ahmad Emran,完整的代碼你能夠戳這裏:

CodePen Demo -- CodePen Home Animation with offset-path | Only Using CSS & HTML

利用 Motion-Path 繪製路徑動畫

又或者,咱們利用 Path 能繪製任意路徑的特性,實現各類咱們想要的路徑,譬如加入購物車的拋物線,或者各種運動軌跡,都不在話下,這裏再提供一個 Demo:

CodePen Demo -- CSS Motion Path offset-path animation

Can i Use - Motion-Path

來看看 Motion-Path 目前的兼容性如何?截止至 2021-04-27。

Can i Use - Motion-Path

目前而言,除去 IE 瀏覽器,就等待 Safari 什麼時候可以兼容了,具體是否使用,還須要根據目標羣體瀏覽器使用狀況進行取捨。

最後

好了,本文到此結束,介紹了運動路徑動畫 Motion Path,而且利用它實現了一些以往沒法簡單實現的路徑動畫效果,但願對你有幫助 :)

想 Get 到最有意思的 CSS 資訊,千萬不要錯過個人公衆號 -- iCSS前端趣聞 😄

更多精彩 CSS 技術文章彙總在個人 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。

相關文章
相關標籤/搜索