javascript
JavaScript权威指南--多媒体和图形编程
知識要點?
21.1節介紹如何用傳統的JavaScript技術實現諸如圖片翻轉(鼠標指針移動到一張靜態圖片上切換成另外一張圖片)這樣的視覺效果。
21.2節介紹HTML5的<audio>和<video>元素以及它們的JavaScript API。
21.3和21.4介紹兩項非常強大的用于客戶端繪圖的技術。能夠在瀏覽器中動態生成復雜圖形是非常重要的,因為:
- 用于在客戶端生成圖形的代碼大小要比圖片本身小很多,這樣可以減少部分帶寬。
- 通過一些實時數據來動態生成圖形,需要消耗大量的CPU周期。而如果把這個任務放到客戶端做,就可以有效地減輕服務器的負擔,某種程度上也是節約了硬件開銷。
- 在客戶端生成圖形也是符合現代Web應用的架構:服務器提供數據,然后客戶端負責展現這些數據
21.3節介紹可伸縮的矢量圖形(Scalable Vector Graphics,SVG)。SVG是一種基于XML的并且用于描述圖形的語言,SVG圖形可以通過JavaScript和DOM來創建和操控。
21.4節會介紹HTML5的<canvas>元素及其用于客戶端畫圖的、功能齊全的JavaScript API。<canvas>元素是一項革命性的技術。
1.腳本化圖片
如下的HTML代碼段是一個非常簡單的例子:它創建一張圖片,并在鼠標指針經過的時候改變該圖片:
<img src="images/help.gif"οnmοuseοver="this.src='images/help_rollover.gif'"οnmοuseοut="this.src='images/help.gif'">為了有用起見,像圖片翻轉這樣的效果需要較高響應度。這也意味著需要想辦法來確保一些必要的圖片要預提取,讓瀏覽器緩存起來。客戶端JavaScript定義了一個專用的API來達到這一目的:為了強制讓圖片緩存起來,首先利用Image()構造函數來創建一個屏幕外圖片對象,之后,將該對象的src屬性設置成期望的URL。由于圖片元素并沒有添加到文檔中,因此,它是不可見的,但是瀏覽器還是會加載圖片并將其緩存起來。這樣一來,之后當設置成同樣的URL來顯示該屏幕內圖片的時候,它就能很快從瀏覽器緩存中加載,而不需要再通過網絡加載。
前面展示的圖片翻轉的代碼片段并沒有預提取它使用的翻轉圖片,這樣,當用戶第一次將鼠標指針移到圖片上的時候會明顯感到翻轉效果有延時。要解決這個問題,將代碼修改成如下形式:
<script>(new Image()).src="images/help_rollover.gif";</script> <img src="images/help.gif"onmouseover="this.src='images/help_rollover.gif'"onmouseout="this.src='images/help.gif'">優雅的圖片翻轉實現方式
上述代碼用了一個<script>元素和兩個JavaScript事件處理程序的屬性來實現一個簡單的圖片翻轉效果。這個例子的代碼非常不優雅:大量的JavaScript和HTML代碼混在一起。
例子中展示了一種更為優雅的實現方式,這種方式允許在任意的<img>元素上,只要簡單地指定了data-rollover屬性(參見15.4.3節),就會創建一個圖片翻轉效果。要注意的是,該例使用了例13-5中介紹的onLoad()函數。同時它還用到了document.images[]數組(參見15.2.3節)從文檔中查找所有的<img>元素。
例21-1:優雅的圖片翻轉實現方式。
2.腳本化音頻和視頻
<audio src="background_music.mp3"/> <video src="news.mov"width=320 height=240/>由于各家瀏覽器制造商未能在對標準音頻和視頻編解碼器支持上達成一致,因此,通常都需要使用<source>元素來為指定不同格式的媒體源:
<audio id="music"> <source src="music.mp3"type="audio/mpeg"> <source src="music.ogg"type='audio/ogg;codec="vorbis"'> </audio>支持<audio>和<video>元素的瀏覽器不會渲染這些元素的內容。而不支持它們的瀏覽器則會將它們的內容都渲染出來,因此,可以在這些元素中放置后備內容(比如,一個用于調用Flash插件的<object>元素)
<video id="news"width=640 height=480 controls preload><!--Firefox和Chrome支持的WebM格式--><source src="news.webm"type='video/webm;codecs="vp8,vorbis"'><!--IE和Safari支持的H.264格式--><source src="news.mp4"type='video/mp4;codecs="avc1.42E01E,mp4a.40.2"'><!--Flash插件作為后備方案--><object width=640 height=480 type="application/x-shockwave-flash" data="flash_movie_player.swf"><!--這里的參數元素用于配置Flash視頻播放器--><!--文本是最終的后備內容--><div>video element not supported and Flash plugin not installed.</div></object> </video>Audio()構造函數
在不設置controls屬性的情況下,<audio>元素沒有任何視覺外觀。正如可以使用Image()構造函數來創建一張屏幕外圖片那樣,HTML5中的媒體API同樣也允許使用Audio()構造函數,并將媒體源URL作為參數,來創建一個屏幕外音頻元素:new Audio("chime.wav").play();//載入并播放聲音效果。Audio()構造函數的返回值和通過從文檔中查詢<audio>元素或者使用document.createElement("audio")來創建一個新的元素獲得的都是同一類對象。這里要注意的是,Audio()是音頻元素特有的API,換句話說,視頻元素是沒有類似Video()這樣的構造函數的。
盡管對于多種不同格式的文件要分別定義媒體比較繁瑣,但是,能夠不借助插件在瀏覽器中原生播放音頻和視頻是HTML5中非常強大的新特性。要注意的是,對于媒體編解碼器的問題以及瀏覽器對其兼容性的問題并不在本書討論的范疇。接下來會集中討論如何利用JavaScript API來操控音頻和視頻流。
2.1.類型選擇和加載
想要測試一個媒體元素能否播放指定類型的媒體文件,可以調用canPlayType()方法并將媒體的MIME類型(有時需要包含codec參數)傳遞進去。如果它不能播放該類型的媒體文件,該方法會返回一個空的字符串(一個假值);反之,它會返回一個字符串:"maybe"或者"probably"。之所以返回"probably"這樣不確定的結果,是因為音頻和視頻編解碼器本身就非常復雜,在沒有真正下載并嘗試播放指定類型的媒體前很難確定是否真的可以支持播放此類型文件:
var a=new Audio(); if(a.canPlayType("audio/wav")){a.src="soundeffect.wav";a.play(); }當設置媒體元素的src屬性的時候,加載媒體的過程就開始了(除非將preload設置成"auto",否則,只會加載少量內容,因此該過程不會持續很長時間)。當設置src屬性的時候,如果有其他的媒體文件正在加載或者播放,則會中止它們的加載或者播放過程。如果通過在媒體元素中添加<source>元素而不是設置src屬性的方式指定媒體源,媒體元素無法知道是否已經將一系列<source>元素都添加完畢了,因此它也不會開始選擇并加載<source>元素指定的媒體源文件,除非顯式地調用load()方法。
2.2.控制媒體播放
//文檔載入完成后,開始播放背景音樂 window.addEventListener("load",function(){document.getElementById("music").play(); },false);2.3.查詢媒體狀態
例如,假設媒體文件從開始緩存起中間沒有定點播放發生(跳過一段播放),可以使用如下代碼來確定當前緩存內容的百分比:
var percent_loaded=Math.floor(song.buffered.end(0)/song.duration*100);readyState屬性指定當前已經加載了多少媒體內容,因此同時也暗示著是否已經準備好可以播放了。如下表格展示了該屬性的取值以及對應的意義:
NetworkState屬性指定媒體元素是否使用網絡或者為什么媒體文件不使用網絡:
當在加載媒體或者播放媒體過程中發生錯誤時,瀏覽器就會設置<audio>或者<video>元素的error屬性。在沒有錯誤發生的情況下,error屬性值為null。反之,error的屬性值是一個對象,包含了描述錯誤的數值code屬性。同時,error對象也定義了一些描述可能的錯誤代碼的常量:
可以以如下方式使用error屬性:
if(song.error.code==song.error.MEDIA_ERR_DECODE)alert("Can't play song:corrupt audio data.");下表根據它們觸發的先后順序,總結了22個媒體相關事件。這些事件不能通過屬性來注冊事件,只能通過<audio>和<video>元素的addEventListener()方法來注冊處理程序函數。
3 SVG:可伸縮的矢量圖形
一個簡單的SVG文件如下所示:
<!--SVG圖形一開始聲明命名空間--> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><!--圖形的坐標系--><defs><!--設置后面要用到的一些定義--><linearGradient id="fade"><!--將一種漸變色命名為"fade"--><stop offset="0%"stop-color="#008"/><!--深藍--><stop offset="100%"stop-color="#ccf"/><!--漸變到淺藍--></linearGradient></defs><!--畫一個具有寬的黑色邊框并且漸變色為填充色的矩形--><rect x="100"y="200"width="800"height="600" stroke="black"stroke-width="25"fill="url(#fade)"/> </svg>學習資料:
http://www.w3school.com.cn/svg/index.asp
https://www.w3.org/TR/
當使用<img>或者<object>元素展示SVG圖形的時候,SVG就變成了另外一種圖片格式了,這種方式對于JavaScript程序員來說是不友好的。更好的方式是直接將SVG圖片嵌入到HTML文檔中,這樣這些圖片就可以通過腳本的方式來控制。由于SVG就是一種XML語法,因此可以將它以如下的方式嵌入到XHTML文檔中:
//保存為XHTML文件 <?xml version="1.0"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg"> <!--聲明HTML作為默認的命名空間,以"svg:"前綴的為SVG的命名空間--> <body> This is a red square:<svg:svg width="10" height="10"> <svg:rect x="0" y="0" width="10" height="10" fill="red"/> </svg:svg> This is a blue circle:<svg:svg width="10" height="10"> <svg:circle cx="5" cy="5" r="5" fill="blue"/> </svg:svg> </body> </html>HTML5將XML和HTML的區別進一步縮小,允許SVG(和MathML)標記直接在HTML文件中使用,不需要命名空間的聲明或者標簽前綴:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title> </head> <body>This is a red square:<svg width="10"height="10"><rect x="0"y="0"width="10"height="10"fill="red"/></svg>This is a blue circle:<svg width="10"height="10"><circle cx="5"cy="5"r="5"fill="blue"/></svg> </body> </html>例21-2是一個pieChart()函數。
例21-3是另外一個用腳本繪制SVG圖形的例子:它使用SVG來繪制一個模擬時鐘
4.<canvas>中的圖形
大部分的畫布繪制API都不是在<canvas>元素自身上定義的,而是定義在一個“繪制上下文”對象上,獲取該對象可以通過調用畫布的getContext()方法。調用getContext()方法時,傳遞一個"2d"參數,會獲得一個CanvasRenderingContext2D對象,使用該對象可以在畫布上繪制二維圖形。這里很重要的一點是要搞清楚,畫布元素和它的上下文對象是兩個完全不同的對象。由于CanvasRenderingContext2D名字太長了,因此這里做個約定,統一簡稱為“上下文對象”。同樣地,“畫布API”指的也就是CanvasRenderingContext2D對象的方法。
畫布中的3D圖形
瀏覽器提供商實現<canvas>元素用于繪制3D圖形的API。這些API稱為:"WebGL",它是綁定到OpenGL標準API的一個JavaScript。將"webgl"字符串作為參數傳遞給畫布的getContext()方法可以獲得用于繪制3D圖形的上下文對象。由于WebGL很龐大,而且也非常復雜,本書將不會介紹它的一些底層API:其實Web開發者也更傾向于使用封裝了WebGL底層API的工具類庫而不喜歡直接使用WebGL API。
示例:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title> </head> <body> This is a red square:<canvas id="square"width=10 height=10></canvas>. This is a blue circle:<canvas id="circle"width=10 height=10></canvas>. <script>var canvas=document.getElementById("square");//獲取第一個畫布元素var context=canvas.getContext("2d");//獲取2D繪制上下文 context.fillStyle="#f00";//設置填充色為紅色 context.fillRect(0,0,10,10);//填充一個正方形 canvas=document.getElementById("circle");//第二個畫布元素 context=canvas.getContext("2d");//獲取它的繪制上下文 context.beginPath();//開始一條新的路徑 context.arc(5,5,5,0,2*Math.PI,true);//將圓形添加到該路徑中 context.fillStyle="#00f";//設置填充色為藍色 context.fill();//填充路徑 </script> </body> </html>之前我們看到SVG使用可以繪制或填充的線段和曲線這種路徑來描述復雜的圖形。畫布API也采用“路徑”的思想。然而不同的是,相比SVG使用一個包含了字母和數字的字符串來描述路徑,畫布API是通過一系列方法調用來定義路徑的,如上述代碼中的beginPath()和arc()方法調用。一旦定義了路徑,其他的諸如fill()這樣的方法就可以在該路徑上操作了。而像fillStyle這樣的上下文對象的屬性則是指定了如何進行這些操作。接下來的內容將解釋:
- 如何定義路徑、如何繪制或者說勾勒路徑的外邊框以及如何填充路徑的內部。
- 如何設置和獲取畫布上下文對象的屬性以及如何保存和恢復這些屬性的當前狀態。
- 畫布的大小、默認畫布坐標系以及如何進行坐標變換。
- 畫布API定義的大量的繪制曲線的方法。
- 一些用于繪制長方形的專用工具方法。
- 如何指定顏色、使用透明度以及如何繪制漸變色和重復的圖案。
- 控制線條寬度以及頂點和端點外觀的屬性。
- 如何在<canvas>元素中繪制文本。
- 如何“裁剪”圖形以保證圖形不超過指定區域。
- 如何給圖形添加下拉陰影效果。
- 如何在畫布中繪制(和選擇性地伸縮)圖形以及如何作為圖片從畫布中提取內容。
- 如何控制畫布中新畫(半透明)像素和原有像素的融合過程。
- 在畫布中,如何設置和查詢像素的紅、綠、藍色值以及alpha值(透明度)。
- 當在畫布中繪制圖形的時候,如何判定是否觸發了鼠標事件。
?
轉載于:https://www.cnblogs.com/Chen-XiaoJun/p/6692791.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JavaScript权威指南--多媒体和图形编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 将Sublime Text3添加到右键菜
- 下一篇: Codeforces Round #40