55行js代碼通過控制Canvas和requestAnimationFrame實(shí)現(xiàn)呼吸漸變效果

效果演示

錄下來的漸變GIF圖沒法看,失真太嚴(yán)重了,所以還是請移步到Codepen上面看吧:

地址:


sp180414_232941.png

基礎(chǔ)知識

canvas

先來看看canvas的瀏覽器兼容性:

來自 MDN文檔

Browser compatibility.png

這里有一個 <canvas> 元素

<canvas id="canvas"></canvas>

按照以下形式獲取 canvas 上下文:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

然后如何創(chuàng)建漸變?

以下代碼可以創(chuàng)建一個起點(diǎn)為左上角白色到右下角黑色的漸變:

let gradient=context.createLinearGradient(0,0,100,100);
gradient.addColorStop(0,"white");
gradient.addColorStop(1,"black");

更詳細(xì)的API請參考這里:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createLinearGradient


requestAnimationFrame

可以參考 張鑫旭的 CSS3動畫那么強(qiáng),requestAnimationFrame還有毛線用?
講得非常清楚,我這里就不贅述一次了。


實(shí)現(xiàn)思路

通過 requestAnimationFrame 每次執(zhí)行的時候更改漸變顏色:

let startColor="rgb(201, 75, 75)";
let stopColor="rgb(75, 19, 79)";

function update(){
  autoChange(startColor,stopColor);
  requestAnimationFrame(update);
}

創(chuàng)建基礎(chǔ)的漸變函數(shù)如下:

let ele=document.getElementById("gradient");
ele.width=300;
ele.height=300;

let r=Math.sqrt(ele.width**2+ele.height**2).toFixed(0);
let xPos=r;
let yPos=r;

function autoChange(startColor,stopColor){

  let gradient=context.createLinearGradient(0,0,xPos,yPos);
  gradient.addColorStop(0,startColor);
  gradient.addColorStop(1,stopColor);

  context.fillStyle=gradient;
  context.fillRect(0,0,300,300);
}

為了實(shí)現(xiàn)呼吸效果,那么RGB的值要緩和變化,也就是從 0 一直增加到 最大值 255 , 然后 又由255一直減少到0,如此反復(fù)。

像不像一個 Sin 正弦函數(shù)圖像?

Sin函數(shù)圖像.png

那么現(xiàn)在我們的漸變函數(shù)變成了這樣:


let RGB={
  r:0,
  g:0,
  b:0
}

function autoChange(startColor,stopColor){

  autoLoopRGB(RGB);

  let gradient=context.createLinearGradient(0,0,xPos,yPos);
  gradient.addColorStop(0,startColor);
  gradient.addColorStop(1,stopColor);

  context.fillStyle=gradient;
  context.fillRect(0,0,300,300);
}

function autoLoopRGB(RGB){
  RGB.r=Math.abs(getSinValue(deg,100));
  RGB.g=Math.abs(getSinValue(deg-20,180));
  RGB.b=Math.abs(getSinValue(deg-30,180));
}

// 讓值從區(qū)間 [-Max ~ +Max] 往返遞增,遞減
function getSinValue(val,Max){
  return Math.ceil(Math.sin(val*Math.PI/180)*Max);
}

那么想讓漸變有旋轉(zhuǎn)效果呢?一邊轉(zhuǎn)一邊變化顏色?

function autoChange(startColor,stopColor){
  autoLoopPos();
  autoLoopRGB(RGB);
  //...
}

應(yīng)該怎么寫 autoLoopPos()?

我們重新看看 產(chǎn)生漸變的API:


image.png

x1和y1 應(yīng)該圍繞 起點(diǎn)做圓心運(yùn)動 ,那么這里根據(jù) 圓的坐標(biāo)方程 (x1-x0)^2 - (y1-y0)^2 = r^2 ,我們使得終點(diǎn)的x1在圓的范圍內(nèi)一直往返遞增遞減,已知半徑和起點(diǎn),那么很輕易可以算出終點(diǎn)的y1坐標(biāo):

function autoLoopPos(){
  if(deg>=360){
    deg%=360;
  }else{
    deg+=1;
  }
  if(xPos<=r){
    xPos=getSinValue(deg,r);  //讓終點(diǎn)x1的坐標(biāo)在圓的范圍內(nèi)往返遞增遞減
    yPos=Math.ceil(Math.sqrt(r**2-xPos**2));  //算出 終點(diǎn) y1的位置
  }
}

那么現(xiàn)在就可以得到一個類似于呼吸的漸變,從暗 ~ 炫彩 ~ 暗 ~ 炫彩 的效果。

其實(shí)也能利用這個思路,使用 requestAnimationFrame 來給元素設(shè)置 background-image的漸變屬性值, 來創(chuàng)造更多的效果。
比如結(jié)合 -webkit-background-clip:text 能給 文字弄上一層動態(tài)的呼吸漸變效果。

image.png

這里有代碼,有興趣可以看看:
https://codepen.io/CosPie/pen/jzRJQq

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,880評論 2 32
  • 一、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標(biāo)簽 Canvas是一個矩形區(qū)...
    J_L_L閱讀 1,690評論 0 4
  • 啥是canvas? HTML5 標(biāo)簽用于繪制圖像(通過腳本,通常是 JavaScript)。不過, 元素本身...
    kiaizi閱讀 854評論 0 4
  • 一.Canvas的基本介紹 1.什么是Canvas 定義:是HTML5提供的一種新標(biāo)簽, ie9才開始支持的,Ca...
    LiLi原上草閱讀 804評論 0 3
  • 處世從容,不失善道 原文: 子語魯大師樂,曰:“樂其可知也:始作,翕如也;從之,純?nèi)缫?,皦如?繹如也,以成。” ...
    剝不掉的橘子皮閱讀 356評論 0 0

友情鏈接更多精彩內(nèi)容