網頁前端
互動&動畫的幾種姿勢
Gore Wang , 2020 @ HAPPY CODING
Email:gore.wang.f2e@gmail.com
website: https://gore.wang
Gore Wang
- 設計具沈浸體驗的操作介面
- 編織具角色性的敘事體驗
- 打造能提升生活&工作體驗的產品功能
喜歡打造體驗的UXE
喜歡做動畫的F2E
喜歡做動畫的F2E
享受:
Thinking of Animation as the body language of a product.
(Animation, Interaction) => UX
Functional:功能性
Natural:自然感
Character:傳達人性的風格
- Visual Feedback 給予操作性的反饋
- Show Orientation 給予使用者操作方向的提示
- 讓使用者能對虛擬世界的操作與現實有所連結
- Express a brand's personality
需求情境 => 設計 => 工具
Interaction
微互動:CSS/SVG
- 無 timeline 性的連續動畫
- 適合連帶被整合在樣式層
- 可以實現預載動畫
- 無法做連續性動態
- 當狀態在網頁初始化就被套用無法產成 Transition 效果
.button {
transition: transform 0.3s ease-out;
&:hover{
transform: scale(1.1) translateY(-5%);
}
}
.man{
animation: ani-jump 0.5s cubic-bezier(0,.69,1,.37);
}
@keyframes ani-jump{
from,to {
transform: 0%;
}
50% {
transform: 50%;
}
}
CSS Transition
CSS Animation
- 無法被自然中斷,覆蓋或拔掉都會因為初始化造成閃動
SVG SMIL
<defs>
<pattern id="p1" patternUnits="userSpaceOnUse" width="20" height="20">
<g>
{isAnimate && (
<animateTransform
id="animate-pattern-g-word"
attributeName="transform"
dur="0.6s"
type="translate"
from="0,0"
to="0,20"
repeatCount="indefinite"
additive="sum"
/>
)}
<rect width="20" height="10" fill="#d2a708" x="0" y="-20"></rect>
<rect width="20" height="10" fill="#d2a708" x="0" y="0"></rect>
</g>
</pattern>
<pattern id="p2" xlinkHref="#p1" patternTransform="rotate(43)" />
<pattern id="p3" xlinkHref="#p1" patternTransform="rotate(40)" />
<pattern id="p4" xlinkHref="#p1" patternTransform="rotate(45)" />
</defs>
利用SVG特性來實做動畫
偷跑介紹
問題!
不具有caback的特性做細部交互
操作 SVG 特性的 Library
(可初始化, 狀態機驅動, Callback性) => 進階互動
- 解決 CSS/SVG 的侷限
- Transition 必須在初始值狀態先被初始化。
- Animation 必定有頭尾,所以無法被即時性插拔,會造成閃動。
- Callback 帶來組建間的進階互動性
更進一步
react-spring
bring your components to "life"
with simple spring animation primitives
- mass
- tension
- friction
- velocity
- duration
- easing
durationeasing
useSpring
react-spring
- 創造自然具生命性的動態
- 可以狀態驅動
- 可以做到 timeline 形式動畫,且可被打斷
以 react-transition-group 為例
<Route
...
children={({ match, ...rest }) => (
<Transition
in={match !== null}
addEndListener={(n, done) => {
if (match !== null) { // route match 到這頁
dispatch(actTransitionStart()); // 限制唯有換頁動態結束後才能再次觸發換頁
animateWillEnter(n, () => {
dispatch(actTransitionEnd());
done(); // 告知 Transition 動態已完成,可以將離開的 Page 正式從 DOM 移除
});
} else {
animateWillLeave(n, done);
}
}}
>
<PageComponent ... />
</Transition>
)}
/>
Transition Group
實現物件 Fade In/Out 間的插拔
即時性互動
反饋使用者具連續性的操作
Instant response and constant redirection
- 不是我們讓介面流動,而是我們讓自己的操作可以流動,介面只是反映流動的操作
- 尋找 Delay 的各個細節
將熟悉的物理性投影在虛擬世界
Fluid:流體 => 舒服、自然 => 物理預測性
Prediction Transition
可預期理解的動態
Projection 動量投射
// adapted from Apple's "Designing Fluid Interfaces" talk
// startVelocity = px/ms
const projection = (startVelocity, decelerationRate=0.998) =>
startVelocity * decelerationRate / (1 - decelerationRate)
// example usage
const velocityY = 1.2 // in px/ms
const projectedEndpoint = projection(velocityY) // 679px
react-gesture
const bind = useXXXX(state => {
const {
event, // the source event
xy, // [x,y] values (pointer position or scroll offset)
previous, // previous xy
initial, // xy value when the gesture started
movement, // last gesture offset (xy - initial)
delta, // movement delta (movement - previous movement)
offset, // offset since the first gesture
lastOffset, // offset when the last gesture started
vxvy, // momentum of the gesture per axis
velocity, // absolute velocity of the gesture
distance, // offset distance
direction, // direction per axis
startTime, // gesture start time
elapsedTime, // gesture elapsed time
timeStamp, // timestamp of the event
first, // true when it's the first event
last, // true when it's the last event
active, // true when the gesture is active
memo, // value returned by your handler on its previous run
cancel, // function you can call to interrupt some gestures
canceled, // whether the gesture was canceled (drag and pinch)
down, // true when a mouse button or touch is down
buttons, // number of buttons pressed
touches, // number of fingers touching the screen
args, // arguments you passed to bind
ctrlKey, // true when control key is pressed
altKey, // " " alt " "
shift, // " " shift " "
metaKey, // " " meta " "
dragging, // is the component currently being dragged
moving, // " " " moved
scrolling, // " " " scrolled
wheeling, // " " " wheeled
pinching // " " " pinched
} = state
})
react-gesture + react-spring
放大為互動的效果幅度
賦予使用者滿足感
- Scroll
- Bounce
- Robber Band
```js
const rubberBand = (distance, dimension, constant = 0.55) =>
(distance * dimension * constant) /
(dimension + constant * distance)
const rubberBandClamp = (min, max, delta, constant) =>
delta < min
? -rubberBand(min - delta, max - min, constant) + min
:delta > max
? rubberBand(delta - max, max - min, constant) + max
: delta
```
Performance
- Always Transform
- 盡一切所能確保你線程運算不會將畫面更新率阻斷降低到肉眼所見
Express by Animation
據敘事性的動畫
- Character:人性與風格的投影
- Express a brand's personality
「連續性」的動畫
- GreenSock(GSAP)
- Anime.js
- lotte-web
tl = gsap
.timeline({
onComplete,
})
.add(animateCardEntry(refs))
.add(animateHatFlyUp(refs))
.add(animateQRCodeZoomAndFind(refs), "-=0.3")
.add(animateQRManLeftHand(refs))
.add(animateQRManRightHand(refs, setIsGWordAnimate))
.add(animateQRCodeOk(refs))
.add(animateCardLeave(refs))
export default function animateQRManRightHand(
{
refHandRight,
refRiseHand,
},
setIsGWordAnimate
) {
const initHandPathCache =
refHandRight.getAttribute("d")
const [codeIcon, codeIconUp] =
refIconCodeGroup.childNodes
return (
gsap
.timeline({
onComplete: setIsGWordAnimate
})
// rise hand
.to(refHandRight, {
morphSVG: refRiseHand,
duration: 0.4,
})
...
lotte-web
- 複雜動畫好維護,減少修改成本
- 與前端應用的銜接方式方便
- 即使要做互動形式動畫也沒問題
好維護
與前端銜接交互方便
document
.getElementById("markpen")
.addEventListener("click", () => {
this.anim.playSegments([[105, 522], [328, 522]], true);
});
即時互動
「擴增情境」的動畫
Canvas / WebGL
- 擴張情境傳達的場景
- 突破DOM效能侷限
- 但有SEO問題
選項:
- THREE.js、Babylon.js...
- Aframe、ReactVR...
- PixiJS
- ...
Three.js
Pixi.js
CSS 帶給我們的?
CSS Varialbes!
回過頭來:
怎麼做好選擇?
- 技術追不完,釐清自己真正有感的是什麼
- 釐清目標真正需要被實現&傳達的價值所在
- 找到最適合的合作方式
- 去理解工具被設計的核心動機
- 不要被單一工具&單一特性侷限想像
並不是不用「工具」就無法做到
而是理解自己的需求&目標
找到可以「滿足&解決」其情境的好「設計」
打造體驗
桌遊
人類圖
風格性產品
實現網頁前端互動&動畫的幾種姿勢
By Gore Wang
實現網頁前端互動&動畫的幾種姿勢
- 1,227