23 《每週一點canvas動畫》 3維環境搭建

2021-08-18 21:50:06 字數 3521 閱讀 5675

是不是很逼真,立體效果不錯吧!我記得前段時間**首頁有乙個簡單的3d效果(可是我沒找到,不過有那麼個印象),以為用了webgl。其實,canvas完全就可以模擬。下面我們介紹3d環境的搭建。

1.座標系統

前面部分的動畫內容之所以是2維的,是因為我們所有的動畫都基於乙個2維座標系統。要實現3維的動畫效果,除了x軸,y軸,我們還需要另一條座標軸—— z軸。但是,canvas先天是不具備這條座標軸的。所以,我們需要手工的去設定這條座標軸。

在座標軸的設定上,我們有兩種選擇,如下圖所示:

第一種叫做左手座標系(左手的食指,中指,大拇指三者垂直,大拇指指向自己),第二種叫做右手座標系(右手的食指,中指,大拇指三者垂直,大拇指指向外面)。他們之間的區別如圖所示,z軸的指向不同。以右手座標為例,反映到物體的表現上(如果只是考慮物體的大小),當物體朝著z軸的正向運動,那麼我們會看到物體變得越來越小。就如第一幅效果圖中展示的那樣,當物體朝著負方向運動的時候。我們可以看到物體變得越來越大,產生一種朝我們迎面飛來的感覺。另外,在本文中我們預設使用的是右手座標系。

2.透視(perspective)

2.1 概念

不管你是叫他景深也好,透視也罷。perspective是3d場景中最重要的概念之一,如果你使用過three.js,就會發現camera中有乙個引數,就是perspective。另乙個你很熟悉的場景,恐怕就是css3中的perspective了吧!如果你對這其中的任何乙個有了解,那麼perspective的概念就很好理解了。

perspective的作用是確定物體是靠近我們,還是遠離我們。因為在2維的空間中,我們只需要兩個座標就可以確定乙個物體在平面上的位置。但是,在3維的環境中這是行不通的,兩個物體可能具有相同的x座標,y座標。但是只要z座標不相同,我們就不能判斷他們兩的位置是不是重合的。

那麼,怎麼在2維的平面去體現透視效果呢?各位看官請試想一下,當籃球從遠處飛向你的時候(這裡如果我們只考慮乙個元素——籃球大小),籃球是不是越來越大呢,當你把籃球扔出去,它是不是越來越小呢!ok,就是這個理。在2維的平面,我們想要讓物體感覺向我們走來,就放大它,同理遠離的效果就是讓它變小。

除了讓它的大小發生變化。另乙個比較重要的點是:當物體遠離直至消失的過程中,要想模擬三維的消失效果,我們必須讓物體的x座標,y座標向消失點移動。這個消失點你可以理解為汽車向遠方駛去,最終它會逐漸變成黑點消失在地平線上,這個黑點就是消失點。

所以總結下來,我們在perspective這一塊要做兩件事:

放大或者縮小物體

讓它靠近或者遠離消失點

2.2 公式

上面的概念中我們了解了要想形成透視的效果,我們需要做兩件事。下圖展示了乙個側面檢視,人眼代表觀察點,藍色的球體代表螢幕中的物體,人眼距離螢幕的距離為fl,物體與螢幕之間有一段距離z值(這個值在成像的時候並不存在,反映到物體大小的變化上)

物體的大小與這fl,z兩者之間滿足下面的關係:

scale =fl / (fl + z) = 1/ ( 1+ z/fl)
fl的值就如 css3 中我們設定的perspective值。 同理,這裡也是我們自己設定的乙個值,200,300,500都無所謂啦。

從公式中我們可以得出:

scale的值一般情況下範圍為(0,1.0),這個值之後會用在縮放物體的比例與靠近消失點的比例。

試想兩種比較極端的情況:

當z軸無限大的時候(也就是朝著z軸的正向持續運動),scale的值就會趨近於0。當z的距離趨近於-fl的時候,scale的值就會變得很大,就像是戳進我們的眼裡。

以我們前面使用的小球為例,在draw方法上我們定義

context.scale(this.scalex, this.scaley)
當縮放比例確定後,一方面我們確定了球體大小的變化,另一方面我們用物體的座標乘以這個比例就可以得到物體的新座標。

可能這樣說比較抽象,我們假定 fl=200 ,這時物體的z座標等於0,由公式可得 scale=1.0 ,那麼物體的大小不變,物體的位置不變。如果 z=200 ,那麼 scale=0.5 。物體的大小變為原來的 1/2,同時我們要讓它現在的座標乘以縮放比例 scale,得到新的位置。如果原來的為(200,300),那麼新座標就為(100,150)。具體效果如下圖:

3.**實現

先上效果圖

//物體的 3d座標

ypos = 0,

zpos = 0,

fl = 250,

//距離螢幕的距離(焦距)

vpx = canvas.width / 2,

//消失點

vpy = canvas.height / 2;

window.addeventlistener('keydown', function(e) else

if (e.keycode === 40)

}, false);

(function drawframe() else

if (ball.visible)

}())

**相對來說比較簡單。首先,我們設定物體的3d座標xpos,ypos,zpos,初始預設為0。然後設定焦距fl = 250,最後設定消失點(vpx, vpy)。這裡需要注意的地方是,我們設定的消失點為畫布的中心。如果不這樣做,物體就會向畫布的左上角(0,0)處匯集,這並不是我們想要的效果。

接下來,在動畫迴圈中我們根據公式計算縮放比例 scale,然後作用於 ball 的 scale 上,最後計算物體的新位置。這裡有個值得注意的點是,我們在外層加了乙個判定條件(zpos > -fl),這樣做的目的是當物體太大的時候,超出了 canvas 畫布我們就不再繪製它。

這一節的內容是整個3維效果的核心,後面的所有效果都是基於此。所以請務必弄明白!

11 《每週一點canvas動畫》 緩動動畫

本系列文章 檔案 前面的章節我們介紹了許多基本的動畫,在本節我們將使用這些基本的動畫來建立一些高階動畫。今天我們介紹的第乙個高階動畫叫做緩動動畫 ease 也許在寫css動畫的時候已經接觸過ease這個概念。但我們今天要介紹的是如何在canvas中實現這樣的動畫效果。本章主要內容 百分比運動的概念 ...

一 每週一學 Harris角點

點,就是影象中的特殊位置,是很常用的一類特徵,點的區域性特徵也可以叫做 關鍵特徵點 keypoint feature 或 興趣點 interest point 或 角點 conrner 今天所講的角點簡單定義來說 就是極值點,即在某方面屬性特別突出的點。如上圖紅圈就是一種很簡單的角點。為什麼要檢測角...

每週一點小技術之不是我說的

首先說下,這個系列的博文基本上是針對一些新人或者說是業餘的但對安卓開發有一定興趣的人,所以會對使用說的比較細但對一些基本原理的方面說的比較籠統,只講個大概意思。這個安卓工程是在eclipse中建立的,所以需要您配置安卓的開發環境,其中分別為eclipse jdk android sdk adt,具體...