成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

簡(jiǎn)單的canvas翻角效果

kun_jian / 1807人閱讀

摘要:由于工作需求需要寫一個(gè)翻角效果鏈接右上角需要從無(wú)的狀態(tài)撕開一個(gè)標(biāo)記且有動(dòng)畫過程上圖是實(shí)現(xiàn)的效果圖不是對(duì)這個(gè)翻角效果的難點(diǎn)在于沒有翻開的時(shí)候露出的是下面的內(nèi)容實(shí)現(xiàn)角度來(lái)說純動(dòng)畫的設(shè)計(jì)方案并沒有相出一個(gè)好的對(duì)策于是撿起了好久之前學(xué)的入門級(jí)別的下

由于工作需求 , 需要寫一個(gè)翻角效果;

demo鏈接

右上角需要從無(wú)的狀態(tài)撕開一個(gè)標(biāo)記 , 且有動(dòng)畫過程 , 上圖是實(shí)現(xiàn)的效果圖 , 不是gif

對(duì)這個(gè)翻角效果的難點(diǎn)在于沒有翻開的時(shí)候露出的是dom下面的內(nèi)容 , 實(shí)現(xiàn)角度來(lái)說 純dom + css動(dòng)畫的設(shè)計(jì)方案并沒有相出一個(gè)好的對(duì)策 ; 于是撿起了好久之前學(xué)的入門級(jí)別的canvas;

下面說一下實(shí)現(xiàn)思路:

動(dòng)畫拆分 :
將此動(dòng)畫分解成兩部分 , 一部分是翻頁(yè)出現(xiàn)的黑色三角區(qū)域 , 另一個(gè)是露出的橘色展示內(nèi)容
對(duì)于橘色的展示內(nèi)容區(qū)域相對(duì)好一些 , 因?yàn)槭且粋€(gè)規(guī)則圖形 , 而黑色區(qū)域相對(duì)較難;

先從基礎(chǔ)canvas使用方法說起 :

布局如上 , 這里要說一點(diǎn)踩過的坑是 , canvas必須要設(shè)置上width 與 height , 此處并非為css中的width與height;而是寫在dom上的屬性 ; 因?yàn)閐om上的width與height標(biāo)識(shí)了canvas的分辨率(個(gè)人理解); 所以此canvas畫布分辨率為100*100 , 而展示尺寸是可以通過css控制;

js中首先要做的是獲取canvas對(duì)象 ,

var canvas = document.querySelector(".myCanvas"); //獲取canvas對(duì)應(yīng)dom
var ctx = canvas.getContext("2d"); //此方法較為基礎(chǔ) , 意為獲取canvas繪畫2d內(nèi)容的工具(上下文)
var cw = 100; //分辨率 , 其實(shí)直接從dom上獲取可能更好些
var ch = 100; //分辨率 , 其實(shí)直接從dom上獲取可能更好些

ctx這個(gè)繪畫上下文在這個(gè)教程中起到的作用至關(guān)重要 ; 它提供了非常強(qiáng)大的api , 比如用于畫線 , 填充 , 寫文字等 , 這樣看來(lái)理解為畫筆會(huì)更為簡(jiǎn)明一些;

此處效果需要用到的api如下 ( 不做詳細(xì)解釋 , 可w3c自行查詢 );

ctx.save() //保存上下文狀態(tài) (比如畫筆尺寸 顏色 旋轉(zhuǎn)角度)
ctx.restore() //返回上次保存的上下文狀態(tài)
ctx.moveTo(x,y) //上下文移動(dòng)到具體位置
ctx.lineTo(x,y) //上下文以劃線的形式移動(dòng)到某位置
ctx.stroke() // 畫線動(dòng)作
ctx.quadraticCurveTo() //上下文(畫筆)按貝塞爾曲線移動(dòng)(簡(jiǎn)單理解為可控的曲線即可)
ctx.arc() //畫圓
ctx.beginPath() //開啟新的畫筆路徑
ctx.closePath() //關(guān)閉當(dāng)前畫筆路徑
ctx.createLinearGradient() //創(chuàng)建canvas漸變對(duì)象
ctx.fill() //對(duì)閉合區(qū)域進(jìn)行填充
ctx.globalCompositeOperation //畫筆的重疊模式

可能方法列舉的不夠詳盡 , 見諒.

首先是繪制黑色翻出的部分 , 圖形分解為如下幾部分(請(qǐng)根據(jù)上圖腦補(bǔ))

左上角向右下的半弧 ╮

然后是豎直向下的豎線 |

然后是向右的半圓 ╰

再然后是向右的橫線

接著還是向右下的半弧 ╮

最后是將線連接會(huì)起點(diǎn)

于是第一步 我們要先將畫筆移動(dòng)到 起始位置

   ctx.moveTo(50,0);

然后

ctx.quadraticCurveTo(55 , 5 , 55 , 25); // 可以理解為從(50,0)這個(gè)點(diǎn)劃線到(55,25)這個(gè)點(diǎn) , 中間會(huì)受到(55,5)這個(gè)點(diǎn)將直線想磁鐵一樣"吸"成曲線;

于是第一個(gè)向右下的半弧完成 , 此時(shí)canvas上沒有任何繪制內(nèi)容 , 因?yàn)檫€沒有執(zhí)行過繪制方法例如stroke或fill,

接下來(lái)直線向下就是簡(jiǎn)單的移動(dòng)

ctx.lineTo(55 , 40);

這個(gè)時(shí)候我們接下來(lái)應(yīng)該畫向右的半圓 , 這個(gè)時(shí)候再用貝塞爾曲線繪制 實(shí)在有些不太合適 , 因?yàn)閺膱D上來(lái)看 , 這里完全是1/4的圓 , 所以要使用canvas提供的畫圓的api

ctx.arc(60 , 40 , 5 , Math.PI , Math.PI / 2 , true);

上述畫圓的代碼意為 : 以(60,40)點(diǎn)為圓心 , 5為半徑 , 逆時(shí)針從 180度繪制到90度 , 180度就是圓心的水平向左 到達(dá)點(diǎn)(55,40) , 與上一步連接上 , 然后又因?yàn)槠聊幌蛳聻檎?, 90度在圓心正下方 , 所以繪制出此半圓

于是按照相同的步驟 水平向右

ctx.lineTo(75 , 45);

然后再次使用貝塞爾曲線用第一步的思路畫出向右下的弧;

ctx.quadraticCurveTo( 95 , 45 , 100 , 50 );

同理 上述貝塞爾曲線可以理解為一條從( 75 , 45 ) 到 ( 100 , 50 )的線被 ( 95 , 45 )"吸"成曲線

最后鏈接起點(diǎn) , 閉合繪畫區(qū)域

ctx.lineTo(50 , 0);

這個(gè)時(shí)候黑色區(qū)域的翻頁(yè)就畫完了 , 然后此時(shí)開始填充顏色 ;

var gradient = ctx.createLinearGradient(50 , 50 , 75 , 75);
gradient.addColorStop(0 , "#ccc");
gradient.addColorStop(0.7 , "#111");
gradient.addColorStop(1 , "#000");

我們通過上述代碼創(chuàng)建一個(gè) 從( 50 , 50 )點(diǎn)到(75 , 75)點(diǎn)的線性漸變 , 顏色從 #ccc 到 #111 到 #000 ; 創(chuàng)建高光效果;
然后填充:

ctx.fillStyle = gradient;
ctx.fill();

于是翻頁(yè)效果的一半就算完成了。

至此 , 我要說一點(diǎn)我領(lǐng)悟的canvas的繪畫"套路";

對(duì)于上述教程中 , 有一步我們使用了一個(gè)詞叫做 閉合 , 閉合的概念在canvas中是真是存在的 , 對(duì)于fill方法來(lái)說 填充的區(qū)間是有一個(gè)空間尺寸才可以的 , 比如我們繪畫的這個(gè)黑色的三角形 , 加入我們最后沒有將終點(diǎn)與起點(diǎn)相連接 , 同樣canvas會(huì)自動(dòng)幫我們鏈接最后一筆繪畫的位置到起點(diǎn) , 強(qiáng)制行程閉合空間 , 而這樣我們想再多畫幾個(gè)新的閉合空間就麻煩了 , 所以canvas提供了如下api 新建閉合路徑:

ctx.beginPath(); //新建路徑
ctx.closePath(); //閉合路徑

所以對(duì)于我們接下來(lái)要繪制右上角橘色區(qū)域來(lái)說 , 我們?cè)诶L制黑色區(qū)域之前首先要做的是

ctx.beginPath();
...

然后在fill之前 我們應(yīng)該

ctx.closePath();

也就是說beginPath 到 closePath之間標(biāo)識(shí)著我們自己的一個(gè)完整的繪畫階段.

那么接下來(lái)繪制右上角的橘色區(qū)域就簡(jiǎn)單很多了:

ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(100,50);
ctx.lineTo(100,0);
ctx.lineTo(50,0);
ctx.closePath();
ctx.fillStyle = "#ff6600";
ctx.fill();

于是右上角的橘色區(qū)域我們就繪制完成了;

文字繪制

接下來(lái)繪制"new" , 實(shí)際上是使用canvas簡(jiǎn)單的文本繪制 , 代碼如下:

var deg = Math.PI / 180;
ctx.globalCompositeOperation = "source-atop"; //canvas層疊模式
ctx.beginPath();
ctx.font = "14px Arial"; //設(shè)置字體大小 字體
ctx.textAlign = "center"; // 字體對(duì)齊方式
ctx.translate(78 , 22);  // 移動(dòng)canvas畫布圓點(diǎn)
ctx.rotate(45 * deg);    // 旋轉(zhuǎn)畫布
ctx.fillStyle = "#fff";  // 設(shè)置文字顏色
ctx.fillText("NEW" , 0 , 0); //文字繪制動(dòng)作
ctx.closePath();

對(duì)于上述代碼中 , 文字的相關(guān)api是屬于沒有難度的 , 只是設(shè)置而已 , 需要理解的部分在于 translate和rotate,

這兩個(gè)方法中 translate的意思為移動(dòng)canvas畫布的( 0 , 0 )點(diǎn)到 (78,22),然后旋轉(zhuǎn)45度, 再將文字渲染在原點(diǎn) , 實(shí)際就是 ( 78 , 22 ) 這個(gè)點(diǎn)上, 此時(shí)我們對(duì)canvas的畫筆做出了非常大的修改

比如我們修改了旋轉(zhuǎn)角度以及畫布圓點(diǎn) , 這種操作或許只在我們需要繪制傾斜的new 的時(shí)候需要 , 后期可能就不需要使用了 ,

還好canvas的畫筆是存在"狀態(tài)"的, 通過ctx.save();可以保存當(dāng)前畫筆的狀態(tài) , 通過ctx.restore();可以恢復(fù)到上次畫筆保存的狀態(tài).

于是我個(gè)人理解到 , 在開發(fā)canvas動(dòng)畫時(shí) , 一個(gè)較好的習(xí)慣就是 , 在beginPath之前先ctx.save();保存畫筆狀態(tài) , 在closePath后ctx.restore();恢復(fù)之前的畫筆狀態(tài) , 這樣我們的每一個(gè)繪制階段對(duì)于畫筆的修改都將是不會(huì)有影響的.( 個(gè)人經(jīng)驗(yàn) )

ctx.globalCompositeOperation = "source-atop"; //canvas層疊模式

代碼中這部分是指 我們繪制的文字new 與 橘色三角形區(qū)域的重疊關(guān)系 , 此方法取值較多 , 此處不做過多介紹 , source-atop值可以使重疊區(qū)域保留 , 新繪制的內(nèi)容在重疊區(qū)域以外的部分消失 , 以此達(dá)到new在里面的效果

到這里我們就開發(fā)好了翻角效果的完全展示的狀態(tài) , 那么如何讓這個(gè)區(qū)域動(dòng)起來(lái)呢?

此處需要使用h5提供的用于刷幀的函數(shù) requestAnimationFrame ;

此方法可簡(jiǎn)單理解為 16毫秒的定時(shí)器 , 但是厲害的是可以再各個(gè)環(huán)境中自動(dòng)匹配到可達(dá)到的相對(duì)順暢的幀率 , 實(shí)際并不是定時(shí)器哈~

我們需要在這個(gè)循環(huán)執(zhí)行的函數(shù)中 , 將上述的繪制內(nèi)容重復(fù)繪制 , 例如 :

function draw(){
    drawMethod(); //繪制三角等內(nèi)容
    window.requestAnimationFrame(function(){
        draw();
    })
}
function drawMethod(){
    //...
}

這樣我們就可以達(dá)到刷幀的效果了 , 于是接著我們要做的就是控制繪制時(shí)各個(gè)數(shù)值的參數(shù).

比如我們是以 (50,0)為起點(diǎn) , ( 100 , 50 )為終點(diǎn)這樣的兩個(gè)移動(dòng)點(diǎn)為繪制標(biāo)記的 , 如果我們將兩個(gè)點(diǎn)進(jìn)行存儲(chǔ) , 并且每次執(zhí)行drawMethod的時(shí)候更新點(diǎn)的位置 , 然后清空canvas ,再繪制新的點(diǎn) 那么就可以達(dá)到canvas動(dòng)起來(lái)的目的了;

實(shí)際效果鏈接在這里

在上面的demo鏈接中 , 自己定義了一個(gè)速度與加速度的關(guān)系 , 比如每次繪制一次canvas后 , 將存儲(chǔ)的點(diǎn)坐標(biāo)進(jìn)行增加一個(gè)speed值 , 然后speed值也增加 , 這樣speed對(duì)應(yīng)的概念就是速度 , 而speed的增加值對(duì)應(yīng)的就是加速度. 所以就呈現(xiàn)了一種加速運(yùn)動(dòng)的狀態(tài);

以上內(nèi)容純屬個(gè)人理解內(nèi)容 , 若果有哪里理解錯(cuò)了 歡迎各位大大指點(diǎn) , 另demo鏈接失效可私信.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89923.html

相關(guān)文章

  • 簡(jiǎn)單canvas翻角效果

    摘要:由于工作需求需要寫一個(gè)翻角效果鏈接右上角需要從無(wú)的狀態(tài)撕開一個(gè)標(biāo)記且有動(dòng)畫過程上圖是實(shí)現(xiàn)的效果圖不是對(duì)這個(gè)翻角效果的難點(diǎn)在于沒有翻開的時(shí)候露出的是下面的內(nèi)容實(shí)現(xiàn)角度來(lái)說純動(dòng)畫的設(shè)計(jì)方案并沒有相出一個(gè)好的對(duì)策于是撿起了好久之前學(xué)的入門級(jí)別的下 由于工作需求 , 需要寫一個(gè)翻角效果;showImg(https://segmentfault.com/img/bVYVm4?w=135&h=12...

    Magicer 評(píng)論0 收藏0
  • 簡(jiǎn)單canvas翻角效果

    摘要:由于工作需求需要寫一個(gè)翻角效果鏈接右上角需要從無(wú)的狀態(tài)撕開一個(gè)標(biāo)記且有動(dòng)畫過程上圖是實(shí)現(xiàn)的效果圖不是對(duì)這個(gè)翻角效果的難點(diǎn)在于沒有翻開的時(shí)候露出的是下面的內(nèi)容實(shí)現(xiàn)角度來(lái)說純動(dòng)畫的設(shè)計(jì)方案并沒有相出一個(gè)好的對(duì)策于是撿起了好久之前學(xué)的入門級(jí)別的下 由于工作需求 , 需要寫一個(gè)翻角效果;showImg(https://segmentfault.com/img/bVYVm4?w=135&h=12...

    jcc 評(píng)論0 收藏0
  • 使用CANVAS實(shí)現(xiàn)交互性圓形馬賽克效果

    摘要:在中任意從本地選擇一張圖片,然后通過鼠標(biāo)移動(dòng)或者移動(dòng)端就能實(shí)現(xiàn)圓形分裂的效果。個(gè)人習(xí)慣在構(gòu)造函數(shù)最后加上方法,方法里做一些準(zhǔn)備工作,完成前的一些必要的事情。繪制第一個(gè),也是最大的一個(gè)圓形。 在看D3.js的時(shí)候,無(wú)意間看到了一個(gè)例子,覺得很有趣,像是會(huì)分裂的圓形馬賽克??戳讼麓a,使用svg完成的,但是具體實(shí)現(xiàn)方式使得在手機(jī)端無(wú)法把玩,于是就自己實(shí)現(xiàn)了一個(gè)canvas版本的。代碼很簡(jiǎn)單...

    Aklman 評(píng)論0 收藏0
  • 使用CANVAS實(shí)現(xiàn)交互性圓形馬賽克效果

    摘要:在中任意從本地選擇一張圖片,然后通過鼠標(biāo)移動(dòng)或者移動(dòng)端就能實(shí)現(xiàn)圓形分裂的效果。個(gè)人習(xí)慣在構(gòu)造函數(shù)最后加上方法,方法里做一些準(zhǔn)備工作,完成前的一些必要的事情。繪制第一個(gè),也是最大的一個(gè)圓形。 在看D3.js的時(shí)候,無(wú)意間看到了一個(gè)例子,覺得很有趣,像是會(huì)分裂的圓形馬賽克??戳讼麓a,使用svg完成的,但是具體實(shí)現(xiàn)方式使得在手機(jī)端無(wú)法把玩,于是就自己實(shí)現(xiàn)了一個(gè)canvas版本的。代碼很簡(jiǎn)單...

    starsfun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<