CSS使用SVG實現(xiàn)動態(tài)分布的圓環(huán)發(fā)散路徑動畫

開篇
這個需求也是最近的 大屏項目 里面需要用到的一個效果,大致需求是實現(xiàn)一個圓形范圍內(nèi) 由一個不確定坐標(biāo)的點 向圓周進行曲線發(fā)散 的效果,曲線圓弧向上并伴隨路徑動畫。第一時間看到這個需求想到的就是 SVG 或者 Canvas。但是由于開發(fā)時可能還需要插入其他元素,所以這里還是希望通過 純 DOM + CSS 或者 SVG 的方式來實現(xiàn)。
當(dāng)然這個中心點還是比較確定哈,因為最后的效果是希望左右對稱的,所以中心肯定在 width / 2 的那條縱線上。
于是今天忙活了半天,總算是有了一個 SVG 實現(xiàn)的雛形。最終效果就和封面圖一樣,只是因為錄制的問題動畫顯得有斷層。
先設(shè)計
為了方便顯示,整個 SVG 的默認視口大小設(shè)置為了 600 的一個正方形,并且內(nèi)部固定有一個中心點和圓周,當(dāng)然這個中心點 目前還是固定的。
然后 曲線就通過遍歷數(shù)組來創(chuàng)建 SVG 路徑,路徑動畫與每條曲線進行綁定,然后每條曲線的路徑的話,就通過 Vue 計算屬性返回一個閉包函數(shù),通過元素下標(biāo)來計算曲線的路徑。
并且,為了 方便后面判斷曲線的左右分布,將 圓心的坐標(biāo) 作為了 SVG 的坐標(biāo)中心。
再實現(xiàn)
首先是模擬數(shù)據(jù)
這里是生成一個 10 ~ 20 之間的數(shù)組,再模擬處理每個點的坐標(biāo)的。
export default { name: "ArcAnimation", data() { return { arr: [], width: 600 }; }, created() { this.updateArray(false); }, methods: { updateArray(timing) { const length = Math.floor(Math.random() * 10 + 10); // 這里是因為 svg 的中心點也在圓心,所以就是 0,0 const center = { x: 0, y: 0 }; this.arr = this.calcCircularLayout(length, center, 296); timing && setTimeout(() => this.updateArray(true), 2000); }, /** * 計算N個點均勻排列成圓的各個點坐標(biāo) * @param nodeSize 參與排列成圓的元素個數(shù) * @param center 圓的中心點坐標(biāo) {x:, y:} * @param radius 圓的半徑 * @return 各個元素的坐標(biāo):[{x:, y:}, {x:, y:}, ...] */ calcCircularLayout(nodeSize, center, radius) { let i; let _i; let _layouts = []; for (i = _i = 0; _i < nodeSize; i = ++_i) { let x = center.x + radius * Math.sin((2 * Math.PI * i) / nodeSize); let y = center.y + radius * Math.cos((2 * Math.PI * i) / nodeSize); _layouts.push({ x: x, y: y, k: i }); } return _layouts; } } };
這個 圓周每個點的坐標(biāo)是從網(wǎng)上找的,但是因為當(dāng)時忘記留地址了。要是作者看見了可以聯(lián)系我刪除或者加上您的文章地址。
每個元素的 path 的計算放到了后面說明的。
然后是模板部分
因為最終代碼在 calcCircularLayout 這里會計算好路徑放到數(shù)組元素中,但是因為 path 路徑計算在后面說嘛,所以這里大家就先當(dāng)這個數(shù)組里面已經(jīng)有 path 了。
<template> <div class="ArcAnimation"> <h1>ArcAnimation Page</h1> <p> <el-button @click="updateArray(false)">刷新數(shù)據(jù)</el-button> <el-button @click="updateArray(true)">自動刷新</el-button> </p> <div class="base-content"> <svg :viewBox="`-${width / 2} -${width / 2} ${width} ${width}`"> <g v-for="i in arr" :key="i.k"> <path :d="i.path" fill="none" stroke="#c4605f" stroke-width="4px"></path> <circle r="5" fill="#af4"> <animateMotion dur="4s" repeatCount="indefinite" :path="i.path" /> </circle> </g> <circle r="30" cx="0" cy="-60" fill="#2bc0e4" /> <circle r="296" cx="0" cy="0" fill="none" stroke="#2bc0e4" stroke-width="4px" /> </svg> </div> </div> </template>
這里只有一點:
在 for 循環(huán)中循環(huán)生成的是一個 g 分組標(biāo)簽,里面是一個 path 曲線元素和一個 circle 原點,并且這個原點添加了一個與 曲線一致 的路徑動畫。
最后是曲線路徑計算
方法如下:
computedDotPath({ x, y }) { const centerX = 0; const centerY = -60; let controlX = (centerX + x) / 1.4; let controlY = (centerY + y) / 2; if (y < centerY) { controlX = x / 2; controlY = y / 1.2; } return `M0,-60 C${controlX},${controlY} ${controlX},${controlY} ${x},${y}`; },
這里說明一下幾點
- centerX 與 centerY 代表的是 UI 圖中的中心點,也是每個曲線的起點,可以根據(jù)情況修改
- if 判斷是因為 如果不調(diào)整控制點的話,曲線的方向會與需求方向 相反
- 兩次 除的 除數(shù) 數(shù)值不一樣,也是因為中心點的位置偏上,所以稍微有修改,當(dāng)然后面也可以調(diào)整
后續(xù)
后面可能還會涉及到路徑計算的調(diào)整、路徑動畫配置等其他優(yōu)化的方案,后面也會慢慢完善的。也會試驗使用純CSS結(jié)合DIV來實現(xiàn)。
到此這篇關(guān)于CSS使用SVG實現(xiàn)動態(tài)分布的圓環(huán)發(fā)散路徑動畫的文章就介紹到這了,更多相關(guān)svg路徑動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
- 粒子動畫就是頁面上存在大量的粒子構(gòu)建而成的動畫。傳統(tǒng)的粒子動畫主要由 Canvas、WebGL 實現(xiàn),接下來通過本文給大家介紹使用 CSS 構(gòu)建強大且酷炫的粒子動畫效果,感興趣的2022-08-09
- 本文主要介紹了利用CSS中的conic-gradient()以及box-shadow模擬出光源陰影效果,從而實現(xiàn)一個充滿高級感的背景光動畫,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2021-11-30
能用CSS實現(xiàn)的就不要麻煩JavaScript了
雖然萬物都可以是JavaScript,但某種程度css的運行效率會比JavaScript高,所以筆者認為:能用CSS實現(xiàn)的就不用麻煩JavaScript2021-09-28- 2022卡塔爾世界杯正在如火如荼的進行之中,作為“諸神的黃昏”,本屆世界杯備受矚目,足壇巔峰老將c羅,梅西,內(nèi)馬爾也將隨本次世界杯退役,一代人的青春到此結(jié)束!本篇我2023-01-04