欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

canvas學(xué)習(xí)之API整理筆記(二)

 更新時(shí)間:2016年12月29日 11:38:52   作者:luckykun  
本篇文章的主要內(nèi)容包括高級(jí)動(dòng)畫(huà)、像素操作、性能優(yōu)化等知識(shí)點(diǎn),講解每個(gè)知識(shí)點(diǎn)的同時(shí)還會(huì)有一些酷炫的demo。下面跟著小編一起來(lái)看下吧

前面我整理過(guò)一篇文章介紹了一些基本的API,從這篇文章我們已經(jīng)可以基本了解到常用繪圖的API、簡(jiǎn)單的變換和動(dòng)畫(huà)。而本篇文章的主要內(nèi)容包括高級(jí)動(dòng)畫(huà)、像素操作、性能優(yōu)化等知識(shí)點(diǎn),講解每個(gè)知識(shí)點(diǎn)的同時(shí)還會(huì)有一些酷炫的demo,保證看官們?nèi)淘诰€,毫無(wú)尿點(diǎn),看完不會(huì)后悔,哈哈,一個(gè)耿直的笑^_^。

除此之外,關(guān)于canvas的一系列實(shí)例即將來(lái)襲!歡迎關(guān)注!

開(kāi)始之前

//獲取canvas容器
var can = document.getElementById('canvas');
//創(chuàng)建一個(gè)畫(huà)布
var ctx = can.getContext('2d');

下面所有的操作都在畫(huà)布ctx上進(jìn)行操作。

高級(jí)動(dòng)畫(huà)

繼上一篇簡(jiǎn)單介紹了動(dòng)畫(huà)(主要是requestAnimationFrame方法),現(xiàn)在我們來(lái)一步步實(shí)現(xiàn)一個(gè)在畫(huà)布內(nèi)滾動(dòng)的實(shí)例。

html代碼:

<canvas id="canvas" width="400" height="200" style="background:#fff;"></canvas>

js代碼:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var ball = {  //小球?qū)傩裕c(diǎn)位置,速度,半徑等。
  x: 100, 
  y: 100,
  vx: 4,
  vy: 2,
  radius: 20,
  color: 'blue',
  draw: function() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fillStyle = this.color;
    ctx.fill();
  }
};
function draw() {
  ctx.clearRect(0,0, canvas.width, canvas.height);  //繪制之前清除整個(gè)畫(huà)布
  ball.draw();  //在畫(huà)布中繪制小球
  ball.x += ball.vx;  //改變小球位置坐標(biāo)
  ball.y += ball.vy;  //改變小球位置坐標(biāo)
  if (ball.y + ball.vy > canvas.height-15 || ball.y + ball.vy < 15) {  //邊界判斷
    ball.vy = -ball.vy;
  }
  if (ball.x + ball.vx > canvas.width-15 || ball.x + ball.vx < 15) {  //邊界判斷
    ball.vx = -ball.vx;
  }
  window.requestAnimationFrame(draw);  //循環(huán)執(zhí)行
}
draw();

上面代碼實(shí)現(xiàn)的效果如下圖:

代碼我已經(jīng)寫(xiě)了基本的注釋,不難理解,簡(jiǎn)單概括一下這個(gè)實(shí)例的實(shí)現(xiàn)思想:

創(chuàng)建一個(gè)小球?qū)ο?,包含一個(gè)繪制自己的方法。在整個(gè)畫(huà)布中繪制這個(gè)小球,然后在下一次繪制之前,先清除整個(gè)畫(huà)布,改變小球的各個(gè)屬性(包含了邏輯,比如邊界的判斷),然后重新繪制一遍,從而達(dá)到了動(dòng)起來(lái)的效果。

如果你把上面代碼中的

ctx.clearRect(0,0, canvas.width, canvas.height);

換成下面這樣:

ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillRect(0, 0, canvas.width, canvas.height);

就可以得到漸變尾巴的效果:

大概意思就是使用半透明的白色背景填充畫(huà)布來(lái)代替直接清除這個(gè)畫(huà)布,從而實(shí)現(xiàn)了想要的效果。

像素操作

如果我們想對(duì)一個(gè)canvas畫(huà)布進(jìn)行如下操作:獲取每一個(gè)點(diǎn)的信息,對(duì)每一個(gè)坐標(biāo)點(diǎn)進(jìn)行操作。那我們就需要了解一下ImageData對(duì)象了。

ImageData對(duì)象(由getImageData方法獲取的)中存儲(chǔ)著canvas對(duì)象真實(shí)的像素?cái)?shù)據(jù),它包含以下幾個(gè)只讀屬性:

width

圖片寬度,單位是像素。

height

圖片高度,單位是像素。

data

Uint8ClampedArray類型的一維數(shù)組,包含著RGBA格式的整型數(shù)據(jù),范圍在0至255之間(包括255)。簡(jiǎn)單講,就是一個(gè)數(shù)組,每四個(gè)元素存儲(chǔ)一個(gè)點(diǎn)的顏色信息,這四個(gè)元素分別對(duì)應(yīng)為R、G、B、A的值(知道顏色取值的一眼就明白了,不知道的也沒(méi)關(guān)系,后面有實(shí)例,一看就明白)。

創(chuàng)建ImageData對(duì)象

去創(chuàng)建一個(gè)新的,空白的ImageData對(duì)像,你應(yīng)該會(huì)使用createImageData()方法:

var myImageData = ctx.createImageData(width, height);

上面代碼創(chuàng)建了一個(gè)新的具體特定尺寸的ImageData對(duì)像。所有像素被預(yù)設(shè)為透明黑。

獲取像素?cái)?shù)據(jù)

為了獲得一個(gè)包含畫(huà)布場(chǎng)景像素?cái)?shù)據(jù)的ImageData對(duì)像,你可以用getImageData()方法

var myImageData = ctx.getImageData(left, top, width, height);

創(chuàng)建的myImageData對(duì)象就有width、height、data三個(gè)屬性的值了??聪旅孢@個(gè)實(shí)例:

html代碼:

<div id="color">hover處的顏色</div>
<canvas id="myCanvas" width="300" height="150"></canvas>

js代碼:

var can = document.getElementById('myCanvas');
var ctx = can.getContext('2d');
var img = new Image();
  img.src = "img_the_scream.jpg";
ctx.drawImage(img, 0, 0);
var color = document.getElementById('color');
function pick(event) {
  var x = event.layerX;
  var y = event.layerY;
  var area = ctx.getImageData(x, y, 1, 1); //創(chuàng)建ImageData對(duì)象
  var data = area.data;  //獲取data屬性(一個(gè)存儲(chǔ)顏色rgba值的數(shù)組)
  var rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + data[3] + ')';
  color.style.color = rgba;
  color.textContent = rgba;
}
can.addEventListener('mousemove', pick);

實(shí)現(xiàn)的效果如下圖:

注意: 如果有些同學(xué)試到這里發(fā)現(xiàn)有這個(gè)報(bào)錯(cuò)內(nèi)容Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.,需要檢查這行代碼:

img.src = "img_the_scream.jpg";

這里的圖片地址不能是跨域地址。網(wǎng)上有一些解決辦法,這里就不展開(kāi)講了。

寫(xiě)入像素?cái)?shù)據(jù)

你可以用putImageData()方法去對(duì)場(chǎng)景進(jìn)行像素?cái)?shù)據(jù)的寫(xiě)入。

ctx.putImageData(myImageData, x, y);  //在畫(huà)布的(x, y)點(diǎn)開(kāi)始繪制myImageData所存儲(chǔ)的像素信息。

所以我們可以把獲取到的像素信息進(jìn)行處理,然后再重新繪制,就得到了新的圖形。看看下面這個(gè)實(shí)例:

html代碼:

<canvas id="canvas" width="660" height="277"></canvas>

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'img_the_scream.jpg';
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0,0,canvas.width, canvas.height); //獲取ImageData
var colors = imageData.data; //獲取像素信息
function invert() {
  for (var i = 0; i < colors.length; i += 4) { //四個(gè)為一組
    colors[i]   = 225 - colors[i];   // red
    colors[i+1] = 225 - colors[i+1]; // green
    colors[i+2] = 225 - colors[i+2]; // blue
    colors[i+3] = 255;  //alpha
  }
  ctx.putImageData(imageData, 220, 0); //從(220, 0)開(kāi)始繪制改變過(guò)的顏色
}
function toGray() {
  for (var i = 0; i < colors.length; i += 4) {
    var avg = (colors[i] + colors[i+1] + colors[i+2]) / 3; 
    colors[i] = avg; // red
    colors[i+1] = avg; // green
    colors[i+2] = avg; // blue
    colors[i+3] = 255;  //alpha
  }
  ctx.putImageData(imageData, 440, 0); //從(440, 0)開(kāi)始繪制改變過(guò)的顏色
}
invert();  //反轉(zhuǎn)色
toGray();  //變灰色

實(shí)現(xiàn)的效果如下圖:

左邊部分是原圖,中間部分是把原圖顏色經(jīng)過(guò)反轉(zhuǎn)得到的圖案,右邊部分是把原圖顏色變灰得到的圖案。

性能優(yōu)化

坐標(biāo)點(diǎn)盡量用整數(shù)

瀏覽器為了達(dá)到抗鋸齒的效果會(huì)做額外的運(yùn)算。為了避免這種情況,請(qǐng)保證使用canvas的繪制函數(shù)時(shí),盡量用Math.floor()函數(shù)對(duì)所有的坐標(biāo)點(diǎn)取整。比如:

ctx.drawImage(myImage, 0.3, 0.5); //不提倡這樣寫(xiě),應(yīng)該像下面這樣處理
ctx.drawImage(myImage, Math.floor(0.3), Math.floor(0.5));

使用多個(gè)畫(huà)布繪制復(fù)雜場(chǎng)景

比如做一個(gè)游戲,有幾個(gè)層面:背景層(簡(jiǎn)單變化)、游戲?qū)樱〞r(shí)刻變化)。這個(gè)時(shí)候,我們就可以創(chuàng)建兩個(gè)畫(huà)布,一個(gè)專門(mén)用來(lái)繪制不變的背景(少量繪制),另一個(gè)用來(lái)繪制游戲動(dòng)態(tài)部分(大量繪制),就像這樣:

<canvas id="background-can" width="480" height="320"></canvas>
<canvas id="game-can" width="480" height="320"></canvas>

用CSS設(shè)置靜態(tài)大圖

如果有一層是永遠(yuǎn)不變的,比如一張靜態(tài)的背景圖,最好使用div+css的方法去替代ctx.drawimage(),這么做可以避免在每一幀在畫(huà)布上繪制大圖。簡(jiǎn)單講,dom渲染肯定比canvas的操作性能更高。

盡量少操作canvas的縮放

如果要對(duì)一個(gè)畫(huà)布進(jìn)行縮放,如果可以的話,盡量使用CSS3的transform來(lái)實(shí)現(xiàn)??傊?,記住一個(gè)原則,能用html+div實(shí)現(xiàn)的盡量不用js對(duì)canvas進(jìn)行操作。

更多Tips

  • 將畫(huà)布的函數(shù)調(diào)用集合到一起(例如,畫(huà)一條折線,而不要畫(huà)多條分開(kāi)的直線)
  • 使用不同的辦法去清除畫(huà)布(clearRect()、fillRect()、調(diào)整canvas大小)
  • 盡可能避免 shadowBlur特性
  • 有動(dòng)畫(huà),請(qǐng)使用window.requestAnimationFrame() 而非window.setInterval()

結(jié)語(yǔ)

OK,canvas常用的API就基本總結(jié)完了,靠這些API已經(jīng)足夠開(kāi)發(fā)一些中型游戲了。比如之前自己寫(xiě)的實(shí)例demo之小游戲tinyHeart,就是用這些函數(shù)畫(huà)出來(lái)的。關(guān)鍵是這些函數(shù)的組合使用,多多練習(xí)就好了。

如果你把我之前的兩篇文章都看了的話,相信你會(huì)對(duì)canvas越來(lái)越感興趣。所以為了讓大家的興趣不會(huì)中斷,我后續(xù)還會(huì)出一系列的關(guān)于canvas的實(shí)例,注意,是一系列!敬請(qǐng)期待!

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • 淺析showModalDialog數(shù)據(jù)緩存問(wèn)題(用禁止瀏覽器緩存解決)

    淺析showModalDialog數(shù)據(jù)緩存問(wèn)題(用禁止瀏覽器緩存解決)

    在使用showModalDialog彈出窗口時(shí),顯示的數(shù)據(jù)是上次修改前的數(shù)據(jù),這是因?yàn)槟J(rèn)情況下頁(yè)面保存了緩存,所以顯示的數(shù)據(jù)并不是修改后的情況
    2013-07-07
  • JavaScript調(diào)用客戶端Java程序的方法

    JavaScript調(diào)用客戶端Java程序的方法

    這篇文章主要介紹了JavaScript調(diào)用客戶端Java程序的方法,實(shí)例分析了javascript調(diào)用java程序的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • video.js添加自定義組件的方法

    video.js添加自定義組件的方法

    這篇文章主要介紹了videojs添加自定義組件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • ECharts入門(mén)教程

    ECharts入門(mén)教程

    ECharts 是一個(gè)使用JavaScript實(shí)現(xiàn)的開(kāi)源可視化庫(kù),涵蓋各行業(yè)圖表,滿足各種需求。這篇文章介紹了ECharts的基礎(chǔ)知識(shí),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 微信小程序?qū)崿F(xiàn)簡(jiǎn)單秒表設(shè)計(jì)

    微信小程序?qū)崿F(xiàn)簡(jiǎn)單秒表設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)簡(jiǎn)單秒表設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • JavaScript利用正則表達(dá)式替換字符串中的內(nèi)容

    JavaScript利用正則表達(dá)式替換字符串中的內(nèi)容

    本文主要介紹了JavaScript利用正則表達(dá)式替換字符串中內(nèi)容的具體實(shí)現(xiàn)方法,并做了簡(jiǎn)要注釋,便于理解。具有一定的參考價(jià)值,需要的朋友可以看下
    2016-12-12
  • bootstrap modal+gridview實(shí)現(xiàn)彈出框效果

    bootstrap modal+gridview實(shí)現(xiàn)彈出框效果

    這篇文章主要介紹了bootstrap modal+gridview實(shí)現(xiàn)彈出框效果,gridview點(diǎn)擊更新彈出填寫(xiě)信息表單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Javascript 拖拽的一些高級(jí)的應(yīng)用(逐行分析代碼,讓你輕松了拖拽的原理)

    Javascript 拖拽的一些高級(jí)的應(yīng)用(逐行分析代碼,讓你輕松了拖拽的原理)

    這篇文章主要介紹了Javascript 拖拽的一些高級(jí)的應(yīng)用(逐行分析代碼,讓你輕松了拖拽的原理),需要的朋友可以參考下
    2015-01-01
  • WebSocket中心跳檢測(cè)與斷開(kāi)重連機(jī)制詳解

    WebSocket中心跳檢測(cè)與斷開(kāi)重連機(jī)制詳解

    心跳檢測(cè)是指在WebSocket連接過(guò)程中定時(shí)向服務(wù)端發(fā)送和接收心跳消息,來(lái)確定當(dāng)前連接是否是正常狀態(tài)的檢測(cè)機(jī)制,斷開(kāi)重連是指在WebSocket不正常斷開(kāi)連接后,進(jìn)行重新連接的策略,下面我們就來(lái)看看這二者的具體實(shí)現(xiàn)吧
    2024-01-01
  • javascript canvas時(shí)鐘模擬器

    javascript canvas時(shí)鐘模擬器

    這篇文章主要為大家詳細(xì)介紹了javascript canvas時(shí)鐘模擬器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07

最新評(píng)論