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

基礎(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ù)圖像?

那么現(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:

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)的呼吸漸變效果。

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