[Framer] 添加 SVG 圖層,讓工程師追著打的效果成為現實

Framer 框架給出的基礎動效多數情況下是足夠用的,但總歸未免太過乏味,你一定希望有更「炫」的效果來支撐你的設計腦洞。這篇文章幫助你在自己的 Framer 原型中添加 SVG 圖層,實現更多意想不到的視覺效果。並且理直氣壯的和工程師同學說「我都寫出來了,你也寫出來吧!」

一、讓圖層支持 SVG

layer.classList.add("svgBox")n

從加上這行開始,目標圖層就已經支持 SVG 了,因為 Web 本身支持 SVG,所以我們並不需要載入其他的輔助模塊,只要讓我們的圖層添加相關的類就可以了。

當然,這時候,我們的 Preview 區域不會有任何的反應,因為我們只是讓圖層支持 SVG 的顯示,但是沒有規定任何 SVG 圖形。

二、 SVG 容器和圖形

layer.html = """n <svg viewBox = 0 0 750 750 version = "1.1">n </svg>n"""n

上面這段代碼,建立了一個位置在圖層左上角,寬度高度都是 750 的 SVG 圖形的容器。我們可以看到,聲明 SVG 容器的描述內容被我們放在了 layer.html 中,通常情況下給 Framer 中的對象添加 html 的內容都會通過這種方式。

這時,我們就可以在容器中任意添加自己需要的元素,例如:

layer.html = """n <svg viewBox = 0 0 750 750 version = "1.1">n <rect x="0" y="0" width_="250" height="250" fill = "blue" />n <circle cx="300" cy="400" r="40" fill="red"/>n </svg>n"""n

這時,我們的 Preview 區域將會看到一個矩形和一個圓形,如下圖:

至此,大家應該已經了解了 SVG 圖形在 Framer 中使用的相關套路,更多的 SVG 內容描述方法和規範,可以移步這裡:SVG 教程

三、 做一個會被工程師追著打的範例

講過了相關技術基礎,可以進入和原型相關的實例環節 —— 通過 SVG 中貝塞爾曲線的特性,製作一個「粘糊糊」的 OverDrag 區域。

首先,先快速的建立一個可以 OverDrag 的典型 TableView。觀察圖層列表,你一定發現了,我預留了一個叫 dragEffect 的圖層用作顯示 SVG 圖形,同時有個叫 xAnimation 的迷圖層被設置成了 Visiable = false,之後我們會把它作為一個 Trick 用到。

接下來,我們將會在 SVG 容器中構造一條路徑,應用了 id 為 grad1 的漸變填充,並且對他的 id 進行了定義——"curve"。因為在沒有 OverDrag 時,應該為初始狀態,所以他的控制點位置為 (375, 0) ,也就是屏幕的頂端中央,因此目前我們並不能看到效果——它還是一條直線。

dragEffect.html = """n <svg viewBox=0 0 750 750 version = "1.1">n <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">n <stop offset="0%" stylex="stop-color:rgb(255,255,255);stop-opacity:1" />n <stop offset="100%" stylex="stop-color:rgb(255,255,255);stop-opacity:0.4" />n </linearGradient>nt<path id ="curve" d ="M 0 0 q 375 0 750 0" fill="url(#grad1)"/>n </svg>n"""n

進而,我們希望在 OverDrag 時根據手指和列表的位置對曲線的控制點進行控制。因此,我們對 Drag 事件進行監聽。在 Drag 事件發生時,通過 querySelector 查找器根據剛才設置的 id 選中修改相關語句,把控制點的目標 x 值、 y 值同步到 SVG 容器中。

feedList.on Events.Drag, (event) ->n # 取手指的 x 位置,並設置範圍n xVal = Math.max(Math.min(event.point.x, maxX), minX)n # 取 TableView 的 y 位置,並設置範圍n yVal = Math.min(feedList.y - 44, maxHeight)n document.querySelector(.svgBox #curve).setAttribute(d,M 0 0 q +xVal+ +yVal+ 750 0)n

加入上方代碼後,我們在拖拽列表的時候,就已經可以看到拖拽時的理想效果了。不過在鬆開手後,我們缺少一個合理的過渡。現在我們需要讓控制點的 x 位置緩慢居中,y 位置跟隨 TableView 回彈。因此加入下方代碼:

feedList.on Events.DragEnd, (event) ->n xAnimation.x = Math.max(Math.min(event.point.x, maxX), minX)n xAnimation.animaten x: 375n options:n time: 1.5n curve: Spring(damping: 0.90)nnxAnimation.on "change:x", ->n if feedList.draggable.isAnimating == truen yValAfter = Math.min(feedList.y - 44, maxHeight)n xValAfter = xAnimation.xn document.querySelector(.svgBox #curve).setAttribute(d,M 0 0 q +xValAfter+ +yValAfter+ 750 0)n

至此,整個效果已經達到了我們的預期,值得注意的是,這裡 x 的歸位動畫所需的值,通過傳導一個隱藏圖層的普通移動動畫來實現,這是一個還算常用的 Trick。

在線預覽 & 源碼地址:粘粘的 OverDrag

推薦閱讀:

動效乾貨——貝塞爾曲線插值器原理(進階準備)
那些創意十足的Loading動效原型合集(一鍵復用!)
站在產品設計的角度,我們應該如何思考動效設計?
用PS十倍無損壓縮GIF動效圖

TAG:Framer | 交互动效 | 用户界面设计 |