整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          前端高級之路:寫一個高逼格可視化“圓環”

          常生產生活中,我們會經常讀到或使用各種類型的圖表。圓環(圓弧)便是一種較常見的類型,用于直觀展現某一數據指標占整體的比例。本文以 HTML Canvas 的實現為主(當然,SVG 黨可以在了解原理后自行實現),逐層介紹圓環圖表開發的一些主要思路和原理。

          圖1 所示是一些我們平時比較常見的一些圓環(圓弧)效果。雖然圖形的主體構成都是圓弧,但不同效果在信息傳達的功能上卻略有差異。如:

          • 閉合的圓環可以表示流程 “進度” 的概念
          • 非閉合圓環一般用于狀態量(標量)的展示,一般也稱為 “儀表盤” 效果
          • 不同的色相可用于標識狀態量的狀態區間(如:低危-中危-高危 區間的標識可以使用三種顏色的構成的過渡效果進行表達)

          為了更加方便、完善地解決我們在業務開發時的具體需要,可以對這些風格、樣式進行一定分析、抽象,總結出一個通用組件需要具備的能力,如:

          • 顏色、漸變可配(支持傳入單一色值或顏色序列)
          • 圓弧寬度可調(內、外半徑大小可配置)
          • 圓弧夾角可調(開始角度、截止角度可配置)
          • 圓弧端點造型可選(可切換平角/半圓造型
          • 文案效果可調(字號、字體、顏色等)

          下面,我們著手于實現這樣一個功能全面、業務通用性較強的圓環組件。

          1. 圓環的造型

          繪制圓環造型的第一步,需要先繪制圓環圖表構成要素,即一段一段的圓弧。而對于像下圖中這樣的兩種倒角效果(黃色部分圓弧兩端的樣式),既可以是直角,也可以是半圓。

          因此,我們需要實現一個通用的方法來繪制圓弧,提供兩種倒角風格給用戶。

          1.1 前景圓弧的繪制

          圓弧繪制的思路如上圖所示,按先后順序大致分為幾個步驟:

          (1)繪制圓弧起始端的半圓輪廓

          (2)繪制圓弧的外邊緣輪廓

          (3)繪制圓弧終止端的半圓輪廓

          (4)繪制圓弧的內邊緣輪廓

          (5)閉合輪廓并填充色彩

          注:由于 canvas 繪制圓弧的方法默認是順時針方向,因而我們的繪圖步驟也是沿著順時針方向

          以下是一些姿勢要領:

          1.1.1 端點坐標的計算

          在繪制端點半圓之前我們需要端點的位置坐標,以其實端為例,根據圓環的半徑(內外徑的均值,即圓弧中線的半徑)和起始端點的角度如何計算圓上一點的坐標:

          // 計算圓弧上某點的坐標
          // originX, originY - 圓心的坐標
          // radius - 圓環半徑,等于圓環內、外徑的平均值,也即圓弧中線的半徑
          // alpha - 弧度
          function calcPosition(originX, originY, radius, alpha) {
            return [
              radius * Math.cos(alpha) + originX,
              radius * Math.sin(alpha) + originY,
            ];
          }
          

          1.1.2 端點半圓的起止角度

          在 canvas 中繪制一個 arc,需要知道其起始角度和終止角度。由于 canvas 繪制默認方向為屏幕順時針方向(屏幕 Z軸 的左手螺旋方向),從上面的示意圖中可以看出:

          起始端半圓弧度范圍 - [radianStart - Math.PI, radianStart]

          終止端半圓弧度范圍 - [radianEnd, radianEnd + Math.PI]

          1.1.3 繪制半圓

          有了端點坐標和起止角度,便可以繪制端點的半圓:

          // 以起始端的半圓倒角為例
          myCanvas.context.arc(
            x,
            y,
            (radiusOutter - radiusInner) / 2,     // 小圓半徑,等于圓環線寬的一半
            radianStart - Math.PI,
            radianStart
          );
          

          直角倒角風格的繪制與半圓倒角圓弧的繪制步驟基本相同,主要差別在于不用繪制圓弧兩個端點的小半圓,改成繪制直線。背景圓弧的繪制也與前景圓弧方法一致。

          2. Canvas 實現錐形漸變

          上面的步驟可以繪制出圓弧的輪廓,要達到 圖1 那樣的視覺效果,我們需要給前面繪制出來的輪廓填充圖像。

          沿著圓周方向的漸變,因為其圖像形似圓錐體的俯瞰效果,俗稱錐形漸變:

          眾所周知,CSS 中有一個名為 conic-gradient 的屬性直接支持錐形漸變,而 HTML Canvas 的原生 API 目前還沒有類似的能力。那么,我們如何在 canvas 中繪制出這樣的圖像呢?

          下面我們講下大致的原理:

          (1)對用戶傳入的顏色進行插值,得到一個顏色序列。

          這里,我們直接使用 canvas 原生的 createLinearGradient 方法,在離屏 canvas 中繪制一個 1px 的線性漸變效果,圖像寬度正好是我們要插值的數量,漸變插值的結果也就是 canvas 上對應像素位置的色值。

          顏色插值(漸變取色)代碼實現如下:

          // 用于實現顏色插值的工具類
          export default class ColorInterpolate {
            // 參數01: stops - 為要插值的顏色序列,數據格式形如:[[0, 'red'], [0.5, 'green'], [1.0, 'yellow']]
            // 參數02: segment - 插值段落數,即插值結果的顏色值的數量
            constructor(stops = [], segment = 100) {
              // 構建離屏 canvas
              const canvas = document.createElement('canvas');
              canvas.width = segment;
              canvas.height = 1;
              this.ctx = canvas.getContext('2d');
          
              // 繪制線性漸變
              const gradient = this.ctx.createLinearGradient(0, 0, segment, 0);
              for (let [offset, color] of stops) {
                gradient.addColorStop(offset, color);
              }
          
              this.ctx.fillStyle = gradient;
              this.ctx.fillRect(0, 0, segment, 1);
            }
          
            // 根據位置偏移量獲取插值后的色值
            getColor(offset) {
              const imgData = this.ctx.getImageData(offset, 0, 1, 1);
              return `rgba(${imgData.data.slice(0, 3).join(',')}, ${imgData.data[3] / 255})`;
            }
          }
          

          (2)如下圖所示,我們可以把漸變的圖像看成是由足夠多填充了單個色值的小 “扇面” 拼接而成。

          按照這樣的思路,我們只需要遍歷上面色彩插值得到的各個顏色,然后逐個繪制小扇面,便可得到一個錐形漸變圖像。

          為此我們封裝了一個名為 createConicalGradient 的方法,其使用習慣與 canvas 原生的 createLinearGradient 和 createRadialGradient 方法相似。具體代碼見 我的 Github(覺得有用的童鞋可以 star 一下)。

          3. 過渡動畫

          3.1 圓弧的過渡

          在數值發生改變時,我們的圖表需要一個能夠跟隨數據改變的過渡動畫效果,對于 canvas 而言,便是清除舊圖像然后繪制新一幀圖像。這里有一些方法包裝上的技巧:

          // 注:偽代碼,真實場景建議 OOP 方式包裝為工具類
          
          let _animTick = null;
          let _animFrames = null;
          let _frameData = null;
          let _animDiff = null;
          
          // 動畫方法
          function _animate(duration) {
            if (_animTick === null) {
              // 根據動畫時長 duration 計算整個動畫一共需要多少幀(以 60fps 計算)
              _animFrames = Math.round((duration / 1e3) * 60);
          
              // 相鄰兩幀動畫的數據變化
              _animDiff = _calcAnimDiff(_animFrames);
          
              // 動畫幀數標識
              _animTick = 0;
            }
          
            // 當前幀的數據值
            _frameData = _caclCurentData(_animDiff, _animTick);
            _renderFrame(_frameData);
          
            if (_animTick !== null && _animTick < _animFrames) {
              // 繼續執行動畫
              window.requestAnimationFrame(() => {
                _animate();
                _animTick += 1;
              });
            } else {
              // 動畫結束
              _renderFrame(_frameData);
              _animTick = null;
            }
          }
          
          // 繪制當前幀
          function _renderFrame(data) {
            // ...
          }
          
          // 計算動畫相鄰幀的數據差異
          function _calcAnimDiff() {
            // ...
          }
          
          // 根據兩幀數據差計算當前幀
          function _caclCurentData() {
            // ...
          }
          

          3.2 兩種動畫模式

          在過渡動畫執行的過程中,需要考慮兩種不同的模式:一種是漸變圖像不變化,僅是圓弧的輪廓從舊狀態變化到新狀態;一種是漸變圖像的夾角范圍跟隨輪廓的大小改變。

          這兩種模式其實都有一定意義:前者可以使用不同顏色代表數值的不同狀態;后者僅僅是將漸變的顏色看成一種裝飾效果。

          4. 結果演示

          比較關鍵的原理都介紹完了,最后展示一下我們封裝的圖表組件的效果(右側 GUI 部分是我們自研的設計引擎的編輯效果):

          5. 寫在后面

          本文是可視化圖表開發的一個小案例,。篇幅比較短,還有很多細節沒有展開討論。感興趣的童鞋歡迎交流、留言!

          于上傳圖片大小有限制,所以只能制作這樣質量的動圖,實際效果比這流暢很多!下面送上幾張靜態的效果圖。

          這個效果是由330行純css代碼制作,我知道很多小伙伴都覺得css只需要會一點就可以了,不是這樣的哦,css做好了也是非常厲害的,比如不用js就能寫出炫酷的效果,好吧下面給小伙伴們分享源碼。

          如果有正在學習前端的伙伴,不知道怎么學習的可以加一下我的前端群589651705,每天都會分享一些企業級的知識和特效源碼分享。

          七彩圓環旋轉幻影特效源碼:

          源碼以上傳至群589651705群文件,有需要的小伙伴可以進群自行下載。

          源碼以上傳至群589651705群文件,有需要的小伙伴可以進群自行下載。

          更多的炫酷企業級練習特效,學習方法和面試技巧,敬請關注本頭條號!

          天給大家帶來是四種顏色的加載動畫效果。大家可以仔細看到這是四個小點,點進行圓形的環繞,三百六十度的。看一下代碼區域,我用開發工具是hplx開發unif的。

          ·首先看一下威武士圖容器,里面包含svg圖形元素,里面又包含了四個圓形,圓形a、圓形b、圓形c、圓形d等。大家可以看我這注釋就應該看得明白,我很寫的很詳細。看效果去就知道一共是四個圓,大家可以發現沒有,每個點都有自己運動的軌跡。

          ·下面看一下csspro,首先是背景和整體的效果。下面就是縮小svg元素,已經就把它給縮小了,原本是一個圓,進行六六的。大家可以看一下,在停收小圓,看起來是個小圓。

          ·進行所有圓環動畫的類名任a,大家可以看到a圓的關鍵幀過渡的效果,零六百六,負百分之四十到百分之九十等。這個是第一個,a點也是個圓形的動畫。

          ·設置了a的顏色,紅色在跳,下面就是b的顏色、c的顏色、d的顏色。

          前面給大家講了a的動畫的關鍵幀,大家看到這是b的幾乎就是相同的,只是大小和旋轉的軌跡是不一樣的。其實很簡單的,四個圓形分別設置成不同的顏色,每個有一個獨立的運動軌跡就可以完成了。

          喜歡的可以點贊收藏一下,也可以自己動手去寫。如果想要原代碼的可以找我嘮嗑進行獲取。今天的css樣式就講到這了。


          主站蜘蛛池模板: 无码国产精品一区二区免费式芒果| 免费无码VA一区二区三区| 国产一区在线视频观看| 中文字幕一区二区三区精华液 | 日本免费一区二区三区| 无码精品久久一区二区三区| 亚洲AV无码一区东京热久久 | 99国产精品欧美一区二区三区| 另类免费视频一区二区在线观看| 日韩人妻无码免费视频一区二区三区| 久久一区二区三区免费播放| 国产福利一区二区在线视频| 精品人妻无码一区二区三区蜜桃一 | 99久久精品午夜一区二区| a级午夜毛片免费一区二区| 在线免费视频一区| 精品亚洲AV无码一区二区三区 | 无码人妻一区二区三区免费n鬼沢| 精品91一区二区三区| 日韩免费无码一区二区视频| 午夜福利无码一区二区| 国产成人精品久久一区二区三区| 国产精品视频一区二区三区无码| 国产午夜精品一区二区三区小说 | 午夜无码视频一区二区三区| 国产未成女一区二区三区| 亚洲午夜精品一区二区麻豆| 国产手机精品一区二区| 午夜影院一区二区| 精品无人区一区二区三区在线| 无码人妻精品一区二区在线视频 | 国产乱码精品一区三上| 国产成人免费一区二区三区| 日韩人妻无码免费视频一区二区三区| 国产成人精品一区二区A片带套| 中文精品一区二区三区四区| 丝袜美腿一区二区三区| 成人免费视频一区| 美女视频一区二区三区| 日本精品一区二区三区在线视频| 丰满人妻一区二区三区视频|