整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          面試完50個人后我寫下這篇總結(jié)

          面試完50個人后我寫下這篇總結(jié)

          2019年的春節(jié)來的似乎格外的早,過完年相信很多童鞋都開始蠢蠢欲動了;筆者總結(jié)了多篇教程,結(jié)合平時自己的面試經(jīng)歷,整理了這份文檔,希望幫助大家來突擊一下前端知識的盲區(qū)。文章很長很長很長。。。。(建議先收藏,技術(shù)大佬請Ctrl+F4,面向基礎(chǔ)

          整理不易,希望大家關(guān)注頭條號【JAVA后端架構(gòu)

          常生產(chǎn)生活中,我們會經(jīng)常讀到或使用各種類型的圖表。圓環(huán)(圓?。┍闶且环N較常見的類型,用于直觀展現(xiàn)某一數(shù)據(jù)指標(biāo)占整體的比例。本文以 HTML Canvas 的實現(xiàn)為主(當(dāng)然,SVG 黨可以在了解原理后自行實現(xiàn)),逐層介紹圓環(huán)圖表開發(fā)的一些主要思路和原理。

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

          • 閉合的圓環(huán)可以表示流程 “進(jìn)度” 的概念
          • 非閉合圓環(huán)一般用于狀態(tài)量(標(biāo)量)的展示,一般也稱為 “儀表盤” 效果
          • 不同的色相可用于標(biāo)識狀態(tài)量的狀態(tài)區(qū)間(如:低危-中危-高危 區(qū)間的標(biāo)識可以使用三種顏色的構(gòu)成的過渡效果進(jìn)行表達(dá))

          為了更加方便、完善地解決我們在業(yè)務(wù)開發(fā)時的具體需要,可以對這些風(fēng)格、樣式進(jìn)行一定分析、抽象,總結(jié)出一個通用組件需要具備的能力,如:

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

          下面,我們著手于實現(xiàn)這樣一個功能全面、業(yè)務(wù)通用性較強(qiáng)的圓環(huán)組件。

          1. 圓環(huán)的造型

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

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

          1.1 前景圓弧的繪制

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

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

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

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

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

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

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

          以下是一些姿勢要領(lǐng):

          1.1.1 端點(diǎn)坐標(biāo)的計算

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

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

          1.1.2 端點(diǎn)半圓的起止角度

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

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

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

          1.1.3 繪制半圓

          有了端點(diǎn)坐標(biāo)和起止角度,便可以繪制端點(diǎn)的半圓:

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

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

          2. Canvas 實現(xiàn)錐形漸變

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

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

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

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

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

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

          顏色插值(漸變?nèi)∩┐a實現(xiàn)如下:

          // 用于實現(xiàn)顏色插值的工具類
          export default class ColorInterpolate {
            // 參數(shù)01: stops - 為要插值的顏色序列,數(shù)據(jù)格式形如:[[0, 'red'], [0.5, 'green'], [1.0, 'yellow']]
            // 參數(shù)02: segment - 插值段落數(shù),即插值結(jié)果的顏色值的數(shù)量
            constructor(stops = [], segment = 100) {
              // 構(gòu)建離屏 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);
            }
          
            // 根據(jù)位置偏移量獲取插值后的色值
            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 的方法,其使用習(xí)慣與 canvas 原生的 createLinearGradient 和 createRadialGradient 方法相似。具體代碼見 我的 Github(覺得有用的童鞋可以 star 一下)。

          3. 過渡動畫

          3.1 圓弧的過渡

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

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

          3.2 兩種動畫模式

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

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

          4. 結(jié)果演示

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

          5. 寫在后面

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

          “等風(fēng)來不如追風(fēng)去,追逐的過程就是人生的意義”。

          借朋友吉言,“2018在頭條,2019成為頭條”,這就是我2019的目標(biāo),我已經(jīng)在追風(fēng)的路上。你呢?不要停下腳步,繼續(xù)前行吧。

          今天來個實用的小知識,看下圖:

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          很多人看到左右的波浪邊框,第一想法,應(yīng)該是用圖片實現(xiàn)?,F(xiàn)在我們就打破這一想法,用CSS搞定這個效果。

          radial-gradient()

          radial-gradient() 函數(shù)用徑向漸變創(chuàng)建 "圖像"。徑向漸變由中心點(diǎn)定義。為了創(chuàng)建徑向漸變你必須設(shè)置兩個終止色。

          語法: background: radial-gradient(shape size at position, start-color, ..., last-color);

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          波浪造型的產(chǎn)生

          <div class="coupon"></div>
          

          這里用radial-gradient繪制一個圓,設(shè)置left為1px,top為8px,形成半圓。

          .coupon { 
           position: relative; 
           width: 400px; 
           height: 160px; 
           margin: 50px auto; 
           background-image: 
           radial-gradient( 
           circle at 1px 8px, 
           transparent 6px, 
           #ff9e6d 6px, 
           #ff9e6d 0px); 
           }
          

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          看看原本是這樣,這里的left是8px

          .coupon { 
           ... 
           background-image: 
           radial-gradient( 
           circle at 8px 8px, 
           transparent 6px, 
           #ff9e6d 6px, 
           #ff9e6d 0px); 
           ... 
           }
          

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          設(shè)置背景大小,y軸默認(rèn)平鋪,x軸不允許平鋪,形成多個半圓,造就波浪造型。

          .coupon { 
           ... 
           background-image: 
           radial-gradient( 
           circle at 1px 8px, 
           transparent 6px, 
           #ff9e6d 6px, 
           #ff9e6d 0px); 
           background-size: 200px 18px; 
           background-repeat-x: no-repeat; 
           ... 
           }
          

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          同理,我們添加右邊波浪,

          .coupon { 
           ... 
           background-image: 
           radial-gradient( 
           circle at 1px 8px, 
           transparent 6px, 
           #ff9e6d 6px, 
           #ff9e6d 0px), 
           radial-gradient( 
           circle at 199px 8px, 
           transparent 6px, 
           #ff9e6d 6px, 
           #ff9e6d 0px); 
           background-size: 200px 18px; 
           background-position: 0 0, 200px 0; 
           background-repeat-x: no-repeat; 
          }
          

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          添加文字

          <div class="coupon">50元</div>
          

          用:before偽類,制作中間的虛線,:after偽類,添加“立即領(lǐng)取”文字。同時添加金額(50元)樣式。

          .coupon { 
           ... 
           font-size: 60px; 
           color: #fff; 
           font-weight: bold; 
           line-height: 160px; 
           padding-left: 60px; 
           box-sizing: border-box; 
           cursor: pointer; 
          } 
          .coupon::before { 
           position: absolute; 
           content: ""; 
           left: 240px; 
           top: 0; 
           bottom: 0; 
           width: 0; 
           border-left: 1px dashed #fff; 
          } 
          .coupon::after { 
           position: absolute; 
           content: "立即領(lǐng)取"; 
           font-size: 26px; 
           width: 70px; 
           top: 50%; 
           right: 2%; 
           transform: translate(-50%, -50%); 
           line-height: 40px; 
           letter-spacing: 5px; 
          }
          

          CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          演示地址:CSS3徑向漸變實現(xiàn)優(yōu)惠券波浪造型

          推薦文章

          CSS3 box-shadow實現(xiàn)背景動畫

          從淺到深的學(xué)習(xí) CSS3陰影(box-shadow)

          CSS3線性漸變、陰影、縮放實現(xiàn)動畫下雨效果


          主站蜘蛛池模板: 亚洲日韩AV一区二区三区四区 | 中文无码精品一区二区三区 | 精品无码人妻一区二区免费蜜桃| 亚洲乱码一区二区三区在线观看 | 亚洲国产成人精品无码一区二区| 中文字幕av一区| 国产免费一区二区三区免费视频| 人妻无码第一区二区三区 | 无码国产精品一区二区高潮| 福利国产微拍广场一区视频在线| 国产精品一区电影| 偷拍精品视频一区二区三区| 无码国产精品一区二区高潮| jazzjazz国产精品一区二区| 日本高清不卡一区| 欧美av色香蕉一区二区蜜桃小说| 国产午夜精品一区二区三区不卡| 精品国产一区二区三区香蕉事| 蜜桃视频一区二区三区在线观看| 亚洲日韩激情无码一区| 中文字幕在线无码一区二区三区 | 中文字幕精品一区二区2021年 | www一区二区三区| 亚洲第一区在线观看| 日亚毛片免费乱码不卡一区| 琪琪see色原网一区二区| 国产aⅴ精品一区二区三区久久| 国产在线乱子伦一区二区| 无码一区二区三区免费| 无码播放一区二区三区| 一区二区三区四区电影视频在线观看 | 国产精品美女一区二区三区| 国产精品一区二区三区99| 无码人妻AV免费一区二区三区| 风间由美在线亚洲一区| 久久99国产一区二区三区| 亚洲一区在线视频| 麻豆一区二区三区蜜桃免费| 在线观看午夜亚洲一区| 日本v片免费一区二区三区 | 无码精品不卡一区二区三区 |