首頁  >  文章  >  web前端  >  HTML5高階程式設計之圖形扭曲及其應用三(擴充篇)

HTML5高階程式設計之圖形扭曲及其應用三(擴充篇)

黄舟
黄舟原創
2017-03-02 13:22:202038瀏覽

本篇是本系列文章第三篇,前兩篇介紹了在html5中實現圖片扭曲效果的原理,以及drawtriangles函數的詳細用法,

下面來看看drawtriangles函數的擴充。 利用drawtriangles函數來實作一個旋轉的3D地球,效果如下


因為lufylegend1.5.0版的drawtriangles函數有個bug,所以我悄悄的更新了lufylegend1.5.1版,大家可以到官網下載,地址如下

#http: //lufylegend.com/lufylegend

其實繪製3d球體效果的話,首先就是繪製一個平面,然後將這個平面分成一個一個的小三角形,然後再用這些小三角形拼湊成一個圓球就可以了

現在,我先建立一個空白的LBitmapData對象,然後將這個物件分割成N個小三角形,具體做法看下面程式碼

earthBitmapData = new LBitmapData("#ffffff", 0, 0, 500, 300);
var i, j;
vertices = new Array();
for(i=0;i<=cols;i++){
	for(j=0;j<=rows;j++){
		vertices.push(i*15,j*15);
	}
}
indices = new Array();
for (i = 0; i < cols; i++) {
	for (j = 0; j < rows; j++) {
		indices.push(i * (rows + 1) + j, (i + 1) * (rows + 1) + j, i * (rows + 1) + j + 1);
		indices.push((i + 1) * (rows + 1) + j, i * (rows + 1) + j + 1, (i + 1) * (rows + 1) + j + 1);
	}
}
uvtData = new Array();
for (i = 0; i <= cols; i++) {
	for (j = 0; j <= rows; j++) {
		uvtData.push(i / cols, j / rows);
	}
}

接著,利用drawtriangles函數將LBitmapData物件繪製到畫面上

backLayer = new LSprite();
addChild(backLayer);
backLayer.graphics.clear();
backLayer.graphics.beginBitmapFill(earthBitmapData);
backLayer.graphics.drawTriangles(vertices, indices, uvtData, 2);

得到效果如下圖。


要想將這個平面編程一個圓,就需要計算圖中每個小三角形的座標,先來看看y座標應該如何計算,看下面一張圖,是一個球的垂直切面


利用三角函數,計算圖中的y座標,和y座標所在位置的球的水平切面圓的半徑r1

var a = Math.sin(angle);
if((90-180*j/rows)%90==0 && (90-180*j/rows)%180!=0)a=(90-180*j/rows)>0?1:-1;
var y =  -r*a;
var sa = Math.cos(angle);
var r1 =  Math.abs(r*sa);

於是,首先將計算好的y座標帶入到vertices數組中

for(i=0;i<=cols;i++){
	for(j=0;j<=rows;j++){
		var angle = (90-180*j/rows)*Math.PI/180;
		var a = Math.sin(angle);
		if((90-180*j/rows)%90==0 && (90-180*j/rows)%180!=0)a=(90-180*j/rows)>0?1:-1;
		if((90-180*j/rows)%180==0)a=0;
		var sy =  -r*a;
		vertices.push(i*15,sy);
	}
}

因為還沒有計算x的座標,所以得到一個特殊圖形,如下


接著,看看x的座標如何計算,先將半徑為r1的平面切面拿出來,如下圖


利用三角函數,計算圖中的x座標

var b = Math.cos(angle*Math.PI/180);
var x =  r1*b;

這時,如果只將計算好的x座標帶入vertices陣列中的話

for(i=0;i<=cols;i++){
	for(j=0;j<=rows;j++){
		var sa = Math.cos(angle);
		if((90-180*j/rows)%180==0)sa=1;
		var sr =  Math.abs(r*sa);
		var angle2 = 360*(i+1)/cols;
		var b = Math.cos(angle2*Math.PI/180);
		if(angle2%360==0)b=1;
		else if(angle2%180==0)b=-1;
		var sx =  sr*b;
		vertices.push(sx,j*15);
	}
}

因為沒有計算y的座標,所以得到一個很有意思的圖形,如下


如果將計算好的x座標和y座標,同時帶入vertices數組中的話

for(i=0;i<=cols;i++){
	for(j=0;j<=rows;j++){
		var angle = (90-180*j/rows)*Math.PI/180;
		var a = Math.sin(angle);
		if((90-180*j/rows)%90==0 && (90-180*j/rows)%180!=0)a=(90-180*j/rows)>0?1:-1;
		if((90-180*j/rows)%180==0)a=0;
		var sy =  -r*a;
		var sa = Math.cos(angle);
		if((90-180*j/rows)%180==0)sa=1;
		var sr =  Math.abs(r*sa);
		var angle2 = 360*(i+1)/cols;
		var b = Math.cos(angle2*Math.PI/180);
		if(angle2%360==0)b=1;
		else if(angle2%180==0)b=-1;
		var sx =  sr*b;
		vertices.push(sx, sy);
	}
}

得到一個完整的球體圖形,如下


#接下來就簡單了,將空白圖片換成地球的平面圖,程式碼如下

earthBitmapData = new LBitmapData(imglist["earth"]);

再次運行程式碼,就可以得到下面的3D圖形了


#下面,該讓這個地球轉動起來了,根據上一篇介紹的內容,傳入drawtriangles函數的uvtData數組中的元素是每個小三角形在原圖片中的相對位置,它們決定了繪製圖片的開始位置,如果將一組位置比如0123,變換其中的位置成為1230,再繼續變換成2301,這樣不斷的進行位置變換,那麼從視覺上,其實就已經實現了旋轉了,那麼在代碼中,只需要將分割完的數組的按照每一列進行移動,每次都將第一列的兩組三角形移到最後一列,這樣第二列的兩組三角形就變為了第一列,這樣不停的變換就能讓一個地球轉動起來

for (i = 0; i <= rows; i++) {
	uvtData.push(uvtData.shift());
	uvtData.push(uvtData.shift());
}

如果要改變這個地球的大小的話,就更簡單了,改變LSprite物件的scaleX和scaleY屬性就可以改變它的大小了,大家可以點選下面的連接,來測試一下它的效果

http:/ /lufy.netne.net/lufylegend-js/3dearth/index.html


備註:

#再次說明一下,本篇所介紹的內容需要HTML5開源引擎lufylegend的1.5.1版或以上版本的支持,lufylegend1.5.1版發佈地址如下

#http://lufylegend.com /lufylegend

 以上就是HTML5高階程式設計圖形扭曲及其應用三(擴充篇)的內容,更多相關內容請關注PHP中文網(www.php.cn)!


#
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn