|
Jack Herrington (jack_d_herrington@codegeneration.net), 高級軟件工程師, "Code Generation Network"
2006 年 9 月 07 日
“使用 PHP 和 DHTML 設計 Web 2.0 應用程序” 系列文章的第 1 部分探討了如何使用 JavaScript、層疊樣式表(CSS) 和 HTML 構建帶有選項卡、微調控制項、彈出框等用戶(hù)界面元素的 PHP 應用程序。第 2 部分將擴展上一篇文章的內容,將圖形技術(shù)包含在內,使用 JavaScript 動(dòng)態(tài)創(chuàng )建新的 HTML 元素。
第 1 部分 介紹了移動(dòng)、隱藏和顯示 Web 頁(yè)面內容的方法。但如何動(dòng)態(tài)創(chuàng )建新的 HTML 元素呢?該如何圖形化數據及使用類(lèi)似的有趣技術(shù)呢?圖 1 展示了全世界文盲率的圖表(數據來(lái)自 Unesco,請參閱 參考資料)。
圖 1. 按年份排列的全球文盲率
這并非最有趣的數據集,但振奮人心。那么如果只想查看歐洲的文盲率呢?非常簡(jiǎn)單:?jiǎn)螕粝吕藛?,選擇 Europe 即可。
圖 2. 按年份排列的歐洲文盲率
圖表顯示出,歐洲的文盲率遠遠低于全球水平。清單 1 給出了產(chǎn)生此動(dòng)態(tài)圖表的代碼。
清單 1. 條形圖代碼
<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 ];
var rates = [];
rates[ ‘World‘ ] = [ 36.6, 30.3, 24.7, 22.4,
20.3, 18.3, 16.5, 15.0 ];
rates[ ‘Africa‘ ] = [ 72.4, 62.4, 51.2, 45.6,
40.2, 35.2, 30.8, 26.8 ];
rates[ ‘America‘ ] = [ 14.8, 11.6, 9.0, 7.9,
6.9, 6.0, 5.3, 4.6 ];
rates[ ‘Asia‘ ] = [ 48.5, 38.7, 30.2, 27.2,
24.4, 21.8, 19.6, 17.7 ];
rates[ ‘Europe‘ ] = [ 6.4, 4.3, 2.8, 2.2, 1.8,
1.4, 1.1, 0.8 ];
rates[ ‘Oceania‘ ] = [ 11.1, 8.7, 7.1, 6.6,
6.1, 5.6, 5.3, 5.0 ];
function plot( region )
{
var html = "";
html += "<table width=‘100%‘ cellspacing=‘0‘ cellpadding=‘1‘>";
for( var year in years )
{
var val = Math.round( rates[region][year] );
html += "<tr>";
html += "<td width=‘8%‘>"+years[year]+"</td>";
html += "<td width=‘1%‘ class=‘bar-start‘></td>";
html += "<td width=‘92%‘>";
html += "<table width=‘100%‘ cellspacing=‘0‘ ";
html += "cellpadding=‘0‘><tr>";
html += "<td width=‘"+val+"%‘ class=‘bar-on‘>";
html += " </td>";
html += "<td width=‘"+(100-val);
html += "%‘ class=‘bar-off‘> </td>";
html += "</tr></table></td>";
html += "<td width=‘1%‘ class=‘bar-start‘></td>";
html += "</tr>";
}
html += "</table>";
document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot(‘World‘)">
Region:
<select onchange="plot(this.options[this.selectedIndex].value)">
<option value="World">World</option>
<option value="Africa">Africa</option>
<option value="America">America</option>
<option value="Asia">Asia</option>
<option value="Europe">Europe</option>
<option value="Oceania">Oceania</option>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>
|
首先給出了一個(gè) ID 為 "graph" 的空 <div>。<body> 標記的 onload 屬性告訴瀏覽器在載入頁(yè)面時(shí)調用 plot 函數。這段代碼有趣的地方就在于 plot 函數。
此函數首先創(chuàng )建了一個(gè)空字符串。接下來(lái),它通過(guò)在字符串中添加 <table>、<tr> 和 <td> 標記構建圖表。此函數隨后將 graph <div> 標記的 innerHTML 屬性設置為新生成的 HTML。
圖形本身是一個(gè)表,有四列:年份、小分隔符、條形圖及另外一個(gè)分隔符。條形符列的各行中是另外一個(gè)表。這些嵌套表有兩個(gè)單元格:第一個(gè)單元格為藍色,第二個(gè)單元格為白色。藍色單元格的寬度為文盲率,白色單元格的寬度為 100% 減文盲率。結果得到簡(jiǎn)單的 HTML 條形圖,沒(méi)有任何圖像。
Region 下拉菜單有一個(gè) onchange 處理程序,只要選中新項目,此處理程序就會(huì )被調用。此時(shí),以當前選中的值調用 plot 方法,圖形即被更新。
此代碼的兼容性非常好。所使用的 innerHTML 可用 createElement 和 appendChild 等 DOM 方法取代,可兼容所有現代瀏覽器。
條形圖的 PHP 代碼
在 PHP 中實(shí)現條形圖時(shí),本文著(zhù)眼于如何從服務(wù)器的 PHP 代碼中獲取數據并將其置入 Dynamic HTML(DHTML)JavaScript 中。條形圖的 PHP 代碼如清單 2 所示。
清單 2. 條形圖的 PHP 代碼
<?php
$years = array( 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 );
$countries = array();
$countries[ "World" ] = array( 36.6, 30.3, 24.7, 22.4,
20.3, 18.3, 16.5, 15.0 );
$countries[ "Africa" ] = array( 72.4, 62.4, 51.2, 45.6,
40.2, 35.2, 30.8, 26.8 );
$countries[ "America" ] = array( 14.8, 11.6, 9.0, 7.9,
6.9, 6.0, 5.3, 4.6 );
$countries[ "Asia" ] = array( 48.5, 38.7, 30.2, 27.2,
24.4, 21.8, 19.6, 17.7 );
$countries[ "Europe" ] = array( 6.4, 4.3, 2.8, 2.2,
1.8, 1.4, 1.1, 0.8 );
$countries[ "Oceania" ] = array( 11.1, 8.7, 7.1, 6.6,
6.1, 5.6, 5.3, 5.0 );
?>
<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ <?php echo( join( ",", $years ) ); ?> ];
var rates = [];
<?php
foreach( $countries as $name => $values ) {
?>
rates[ ‘<?php echo($name) ?>‘ ] = [
<?php echo( join( ",", $values ) ); ?> ];
<?php } ?>
function plot( region )
{
var html = "";
html += "<table width=‘100%‘ cellspacing=‘0‘ cellpadding=‘1‘>";
for( var year in years )
{
var val = Math.round( rates[region][year] );
html += "<tr>";
html += "<td width=‘8%‘>"+years[year]+"</td>";
html += "<td width=‘1%‘ class=‘bar-start‘></td>";
html += "<td width=‘92%‘>";
html += "<table width=‘100%‘ cellspacing=‘0‘ cellpadding=‘0‘><tr>";
html += "<td width=‘"+val+"%‘ class=‘bar-on‘> </td>";
html += "<td width=‘"+(100-val)+"%‘ class=‘bar-off‘> </td>";
html += "</tr></table></td>";
html += "<td width=‘1%‘ class=‘bar-start‘></td>";
html += "</tr>";
}
html += "</table>";
document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot(‘World‘)">
Region: <select onchange="plot(this.options[this.selectedIndex].value)">
<?php
foreach( $countries as $name => $values ) {
?>
<option value="<?php echo($name) ?>"><?php echo($name) ?></option>
<?php } ?>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>
|
在文件頂端,為 years 和 countries 數組預先加載年份、國家列表及其掃盲值。隨后,PHP 需要生成 DHTML 代碼的三個(gè)區域。第一個(gè)填充 JavaScript 中的 years 數組,第二個(gè)填充 rates,第三個(gè)以國家名設置 <select> 標記的內容。
散點(diǎn)圖
動(dòng)態(tài)創(chuàng )建新 HTML 是 DHTML 的核心。選擇之一是構建字符串并在頁(yè)面上設置元素的內部 HTML。本例給出了第二種方法,使用散點(diǎn)圖作為示例。圖 3 展示了一個(gè)簡(jiǎn)單等式的散點(diǎn)圖。
圖 3. 多周期正弦波形圖
您可更改等式,并單擊 Try It! 按鈕更新圖形,如圖 4 所示。
圖 4. 略有差異的等式圖形
所有這一切都不必返回 PHP 服務(wù)器。本例甚至沒(méi)有用到服務(wù)器 —— 您可以新建一個(gè) HTML 文件,開(kāi)始編寫(xiě) HTML 代碼。本圖的實(shí)現代碼如清單 3 所示。
清單 3. 散點(diǎn)圖代碼
<html>
<head>
<title>Dynamic Graphing Example</title>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
height:500px; width:500px;
border:1px solid black;
position:relative;
}
</style>
<script>
function drawgraph()
{
var g = document.getElementById( "graphdiv" );
var eq = document.getElementById( "eq" ).value;
var dx = [];
var dy = [];
var sx = 10000;
var ex = -10000;
var sy = 10000;
var ey = -10000;
for( var i = 0; i < 100; i++ )
{
var x = i / 100;
var y = eval( eq );
if ( y > ey ) ey = y;
if ( y < sy ) sy = y;
if ( x > ex ) ex = x;
if ( x < sx ) sx = x;
dx.push( x );
dy.push( y );
}
var gwidth = 500;
var gheight = 500;
var imgwidth = 100;
var imgheight = 100;
var fx = (gwidth-(imgwidth/2))/(ex-sx);
var fy = ((gheight-(imgheight/2))/2)/(ey-sy);
g.innerHTML = "";
for( i = 0; i < dx.length; i++ )
{
var x = ( dx[i] * fx );
var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
var img = document.createElement( "img" );
img.src = "ball.gif";
img.style.position = "absolute";
img.style.top = y+"px";
img.style.left = x+"px";
g.appendChild( img );
}
}
</script>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<div id="graphdiv">
</div>
</body>
</html>
|
本例的大部分代碼都位于 JavaScript 函數 drawgraph 中。該函數創(chuàng )建兩個(gè)數字數組 —— 一個(gè)存儲 x 值,另外一個(gè)存儲 y 值。x 軸的數字范圍為 0 到 1,y 軸的數字是通過(guò)將各 x 值代入等式計算得出的。
數據通過(guò)等式生成,但代碼為各軸設置了最小值和最大值,并按此自動(dòng)調整數據。
將圖像置入圖形需要用到一種新技術(shù):我們使用 document.createElement 來(lái)構建一個(gè) <img> 標記,隨后使用 appendChild 將新創(chuàng )建的 img 對象添加到圖形對象中。這項技術(shù)要優(yōu)于使用字符串設置 innerHTML,因為代碼更易于閱讀和維護 —— 而且您不必擔心字符串編碼問(wèn)題。
使用 createElement 的技術(shù)符合 World Wide Web Consortium(W3C)Document Object Model(DOM)規范,也是動(dòng)態(tài)創(chuàng )建 HTML 元素的首選方法。
散點(diǎn)圖的 PHP 代碼
散點(diǎn)圖示例自成體系。PHP 代碼將散點(diǎn)圖打包為組件。該組件的代碼如清單 4 所示。
清單 4. 散點(diǎn)圖的 PHP 代碼
<?php
function graph_header()
{
?>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
height:500px; width:500px;
border:1px solid black;
position:relative;
}
</style>
<script>
function drawgraph()
{
var g = document.getElementById( "graphdiv" );
var eq = document.getElementById( "eq" ).value;
var dx = [];
var dy = [];
var sx = 10000;
var ex = -10000;
var sy = 10000;
var ey = -10000;
for( var i = 0; i < 100; i++ )
{
var x = i / 100;
var y = eval( eq );
if ( y > ey ) ey = y;
if ( y < sy ) sy = y;
if ( x > ex ) ex = x;
if ( x < sx ) sx = x;
dx.push( x );
dy.push( y );
}
var gwidth = 500;
var gheight = 500;
var imgwidth = 100;
var imgheight = 100;
var fx = (gwidth-(imgwidth/2))/(ex-sx);
var fy = ((gheight- (imgheight/2))/2)/(ey-sy);
g.innerHTML = "";
for( i = 0; i < dx.length; i++ )
{
var x = ( dx[i] * fx );
var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
var img = document.createElement( "img" );
img.src = "ball.gif";
img.style.position = "absolute";
img.style.top = y+"px";
img.style.left = x+"px";
g.appendChild( img );
}
}
</script>
<?php
}
function graph_place()
{
?>
</head>
<div id="graphdiv">
</div>
<?php
}
?>
|
此代碼定義了兩個(gè)函數:graph_header 和 graph_place。graph_header 函數應在文檔的開(kāi)頭部分調用,graph_place 則應在您需要加入圖形的地方調用。清單 5 展示了更新的圖形頁(yè)面代碼。
清單 5. 更新的散點(diǎn)圖 PHP 代碼
<?php
require_once( "graph_component.php" );
?>
<html>
<head>
<title>Dynamic Graphing Example</title>
<?php graph_header(); ?>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<?php graph_place(); ?>
</body>
</html>
|
這比原始頁(yè)面要簡(jiǎn)單得多。首先將組件代碼包含進(jìn)來(lái)。隨后調用 graph_header 來(lái)添加 JavaScript 和 CSS。最后在希望將圖形放置在頁(yè)面上的地方調用了 graph_place 函數。
DHTML 能走多遠?
JavaScript 代碼的強大與簡(jiǎn)單非常吸引人。但問(wèn)題很快發(fā)生了變化,不再是插入的代碼有多么少,而是革新的路能走多遠。Google Maps(參見(jiàn) 參考資料)是 DHTML 應用程序的典范,它證明了 DHTML 應用程序不僅在站點(diǎn)上有用,而且可集成到任何 Web 頁(yè)面上 —— 只需編寫(xiě)一些簡(jiǎn)單的 JavaScript。但 Google 并沒(méi)有就此止步:它又創(chuàng )建了 Gmail(參見(jiàn) 參考資料),將 DHTML 的應用擴展到創(chuàng )建易于使用的郵件客戶(hù)端 —— 就在瀏覽器中。(或許您的 JavaScript 無(wú)法成就至此,但如果您確實(shí)投入時(shí)間去努力,也會(huì )欣喜地發(fā)現能取得怎樣的成果。)
每一名 DHTML 程序員都應該鉆研的一項技術(shù)就是 Asynchronous JavaScript and XML(Ajax)。Ajax 為瀏覽器帶來(lái)了后臺處理 Web 請求的能力。這意味著(zhù),您的 DHTML 應用程序可回調到 PHP 應用程序,而不需刷新頁(yè)面。隨后頁(yè)面可使用那些數據刷新所顯示的信息 —— 完全不會(huì )使瀏覽頁(yè)面的用戶(hù)感覺(jué)不快。(關(guān)于 Ajax 文章與教程的相關(guān)信息,請參見(jiàn) 參考資料 部分。)
結束語(yǔ)
“使用 PHP 和 DHTML 設計 Web 2.0 應用程序” 系列的上一篇文章從新的時(shí)髦詞 Web 2.0 展開(kāi)討論。而業(yè)界的另一重要時(shí)髦詞就是富客戶(hù)機應用程序。兩者同樣意味著(zhù)極酷的 Web 應用程序,您可以同樣的方式看待它們。大量技術(shù)日益涌現,目標都是創(chuàng )建功能豐富的 Internet 應用程序。Laszlo 和 MXML 大大簡(jiǎn)化了 Flash 的構建,Microsoft? 的 Vista 也引入了一些新理念。但就構建功能豐富的 Internet 應用程序而言,DHTML 依然是最有誘惑力的,原因就在于您可以使用 PHP 這樣的現有技術(shù)來(lái)完成這一使命。
本文示范了通過(guò)簡(jiǎn)單的 CSS 和 JavaScript 豐富客戶(hù)體驗的幾種方法。您可以在現有 Web 應用程序中實(shí)現同樣的目標 —— 立即開(kāi)始一個(gè) <script> 標記,享受樂(lè )趣吧。
參考資料
學(xué)習
獲得產(chǎn)品和技術(shù)
- 使用 IBM 試用軟件 革新您的下一個(gè)開(kāi)放源碼開(kāi)發(fā)項目,可通過(guò)下載獲得,也可通過(guò) DVD 獲得。
討論
關(guān)于作者
|
|
|
|
Jack D. Herrington 是一名高級軟件工程師,有著(zhù)二十余年的經(jīng)驗。他撰寫(xiě)了三本圖書(shū):Code Generation in Action、Podcasting Hacks 和即將出版的 PHP Hacks。他的作品還包括三十多篇文章。
|
|