知乎網頁登錄背景的動畫是怎麼做出來的?

知拉


看到這個問題,一下子想起了我剛畢業不久去杭州一家叫盼達在線的公司找工作的事...當時那個面試官要求我在android上實現這種效果,學藝不精,被它刁難住了,現在那種臉紅的灼燒感還記憶猶新。

話說回來,這效果,用ps做成圖片放背景圖,實現肯定是不容易的,但是用代碼實現就很簡單。

先說思路吧,想要復現這個界面,第一步:用random生成一定數量,速度方向隨機,大小不同的點,然後在繪製函數裡面把它們都連起來;

第二步是選線,這個效果我一開始想的是把距離<1/6屏幕高度的點連接就好了,發現連接效果不是很連貫,而且缺少連線越近越清晰,越遠越淡的漸進效果。

再仔細觀察,覺得還是根據連點的距離,通過paint.setAlpha設置透明度來實現;

這個效果看起來還是很滿意的;

再加入手指移動觀察的效果:

這樣,具體的代碼就不貼出來了,放在了github上:

wuyongxiang/DottedLineAnimation


&
&
&
&
&&
&*{
margin: 0;
padding: 0;
}
body{
overflow: hidden;
}
#myCanvas{
border: 1px;
background-color: lavenderblush;
}
.a {
text-align: center;
font-weight: bold;
font-size: 17px;
color: #787878;
font-family: "Comic Sans MS", cursive;
}
.tou {
font-size: 14px;
text-align: center;
color: #787878;
font-family: "Comic Sans MS", cursive;
}
&
&

&

&&

&
&

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//設置畫布寬高與窗口寬高一樣
canvas.width = w;
canvas.height = h;
//隨機數函數
function fnRandom(min,max){
return parseInt((max-min)*Math.random()+min+1)
}
function Round(){
this.r = fnRandom(10,30);
this.diam = this.r*2;
//隨機位置
var x = fnRandom(0,canvas.width - this.r);
this.x = x& var y = fnRandom(0,canvas.height-this.r);
this.y = y& //隨機速度
var speed = fnRandom(2,4)/10
this.speedX = fnRandom(0,4)&>2?speed:-speed;
this.speedY = fnRandom(0,4)&>2?speed:-speed;
//顏色

this.color = "orange";
}
Round.prototype.draw = function(){
//繪製函數
ctx.fillStyle = this.color;
ctx.beginPath()
ctx.arc(this.x,this.y,this.r,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}
Round.prototype.move = function(){
this.x+=this.speedX;
if(this.x&>canvas.width-this.r){
// this.speedX*=-1;
this.x=this.r

}else if(this.x& this.x=canvas.width-this.r
}
this.y+=this.speedY;
if(this.y&>canvas.height-this.r){
// this.speedY*=-1;
this.y=this.r
}else if(this.y& this.y=canvas.height-this.r
}
}
//使用Round
var allRound = [];
function initRound(){
//初始化30個圓形對象,放到數組中
for(var i = 0 ; i&<30;i++){
var obj = new Round();
obj.draw();
obj.move();
allRound.push(obj);


}
}
initRound();
var dxdy = []
function roundMove(){
ctx.clearRect(0,0,canvas.width,canvas.height);
//遍歷所有的圓形對象,讓對象自己重繪,移動
for (var i = 0 ;i & var round = allRound[i];
round.draw();
round.move();

dxdy[i]={
dx:round.x,
dy:round.y
};
var dx = dxdy[i].dx;
var dy =dxdy[i].dy;
for (var j=0;j& var sx = dxdy[j].dx;
var sy = dxdy[j].dy;
l = Math.sqrt((dx-sx)*(dx-sx)+(dy-sy)*(dy-sy));
var C = 1/l*7-0.009;
var o = C &> 0.03 ? 0.03 : C;
ctx.strokeStyle = "rgba(0,0,0,"+ o +")"
console.log(l);
ctx.beginPath()
ctx.lineWidth=2;
ctx.moveTo(dxdy[i].dx,dxdy[i].dy)
ctx.lineTo(dxdy[j].dx,dxdy[j].dy);
ctx.closePath()
ctx.stroke()


}
}
window.requestAnimationFrame(roundMove)
}
roundMove();
&
&


這是用canvas強大的繪圖能力完成的,可以直接寫在html的代碼里


//2016年3月7日更新
看到評論有人問:能轉化成圖片來實現嗎?
答案是不能,這種粒子效果本身就是依靠canvas的強大繪圖API來實現的,如果非要用圖片來實現這種效果,代碼書寫難度非常之大,效果也不會太好。
本人是從去年開始接觸html5,去年年末開始研究canvas,這種效果也嘗試寫過,主要的思路我簡單列一下,您就知道是怎麼做出來的了:
①獲取canvas 和 context繪圖環境
②.onmousemove .clientX .clientY 三個方法獲取滑鼠移動時候的坐標
③隨機添加粒子xy點的坐標,設置粒子xy軸的移動速度
④用requestAnimationFrame創建基於時間的動畫
⑤編寫動畫邏輯: 循環計算粒子之間的距離,如果粒子距離小於一個值,則用context.beginPath() ,context.moveTo);context.lineTo(); context.stroke()進行畫線。
⑥添加條件,遇到邊界將加速度反向,滑鼠移過,則讓粒子向滑鼠的位置移動
大體思路大概就這些,代碼就不上了。

用到了html5 canvas繪畫技術結合javascript。
你所提到的知乎登錄背景的這個動畫屬於「線條粒子效果「,純代碼就可以寫出來,不用設計軟體。


我在codepen上面第一次看到這個效果

Canvas Particle Animation


Github上的一個開源庫。
地址:https://github.com/VincentGarreau/particles.js


Processing? --&> Processing.org (瞎猜)

Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts.

高贊回答的很到位啦,就推薦一下這個tool。


有段時間覺得canvas很好玩,專門寫了這種,自己用來當桌面=。=

首先肯定是創建點,其實是一個個圓

function circle(x,y){
cxt.save();
cxt.beginPath();
cxt.fillStyle="black";
cxt.arc(x,y,1,0,2*Math.PI);
cxt.fill();
cxt.closePath();
cxt.restore();
}
for(var i = 0;i &< num;i++){ pos[i] = {x:Math.random()*W,y:Math.random()*H,mX:Math.random()*-1,mY:Math.random()-1}; circle(pos[i].x,pos[i].y); }; //mx和my下面會講到

然後這些圓要看似無規則的動,所以給他們一個水平方向和垂直方向的速度值,碰到牆壁後,就取反表示彈回來,這就是一次最簡單的動畫,真的只動一下。。

for(var i = 0;i &< num;i++){ pos[i].x += pos[i].mX; pos[i].y += pos[i].mY; if(pos[i].x&>W || pos[i].x&<0){ pos[i].mX = -pos[i].mX; }; if(pos[i].y&>H || pos[i].y&<0){ pos[i].mY = -pos[i].mY; }; circle(pos[i].x,pos[i].y) } window.requestAnimationFrame(animation)

到這裡所有的小球都會動了,然後要做的就是加上線,兩點之間線段長短判斷

for(var j=0;j&

分別是兩點之間,點和滑鼠之間的判斷

至此完成,完整代碼github,然後手機端的話,放進去就好了,嗯

HuangQiii/canvas_line


Github 上有lib

http://vincentgarreau.com/particles.js/


能轉化成圖片嗎?


可以用AE PLEXUS插件做循環動畫,不難。但是要用到網頁上,在下不懂代碼前端啥的,就無能為力了。


推薦閱讀:

QQ 未讀消息的拖拽動態效果是如何實現的?
Google Maps for Android 7 對 Android Design 來說有什麼突破?

TAG:AdobePhotoshop | 前端開發 | 界面 | 編程 | Android開發 |