網頁制作poluoluo文章簡介:Canvas 相當有趣的一項功能就是可以引入圖像,它可以用於圖片合成或者制作背景等。而目前僅可以在圖像中加入文字(標准說明中並沒有包含繪制文字的功能)。只要是 Gecko 支持的圖像(如 PNG,GIF,JPEG等)都可以引入到 canvas 中,而且其它的 canvas 元素也可以作為圖
One of the more fun features of the canvas is the abillity to use images. These can be used to do dynamic photo compositing or used as backdrops of graphs etc. It's currently also the only way to add text to them (The specification does not contain any functions to draw text). External images can be used in any format supported by Gecko (e.g. PNG, GIF or JPEG format). Other canvas elements on the same page can also be used as the source.
Canvas 相當有趣的一項功能就是可以引入圖像,它可以用於圖片合成或者制作背景等。而目前僅可以在圖像中加入文字(標准說明中並沒有包含繪制文字的功能)。只要是 Gecko 支持的圖像(如 PNG,GIF,JPEG等)都可以引入到 canvas 中,而且其它的 canvas 元素也可以作為圖像的來源。
Importing images is basically a two step process:
引入圖像只需要簡單的兩步:
Let's look at step one first. There are basically four options available:
先來看看第一步,基本上有四種可選方式:
We can access all images on a page by using either the document.images collection, the document.getElementsByTagName method, or if we know the ID attribute of the image, the document.getElementById method.
我們可以通過 document.images 集合、document.getElementsByTagName 方法又或者 document.getElementById 方法來獲取頁面內的圖片(如果已知圖片元素的 ID。
Just as with normal images we access other canvas elements using either the document.getElementsByTagName method or the document.getElementById method. Make sure you've drawn something to the source canvas before using it in your target canvas.
和引用頁面內的圖片類似地,用 document.getElementsByTagName 或 document.getElementById 方法來獲取其它 canvas 元素。但你引入的應該是已經准備好的 canvas。
One of the more practical uses of this would be to use a second canvas element as a thumbnail view of the other larger canvas.
一個常用的應用就是為另一個大的 canvas 做縮略圖。
<Another option is to create new Image objects in our script. The main disadvantage of this approach is that if we don't want our script to halt in the middle because it needs to wait for an image to load, we need some form of image preloading.
另外,我們可以用腳本創建一個新的 Image 對象,但這種方法的主要缺點是如果不希望腳本因為等待圖片裝置而暫停,還得需要突破預裝載。
Basically to create a new image object we do this:
我們可以通過下面簡單的方法來創建圖片:
var img = new Image(); // Create new Image object img.src = 'myImage.png'; // Set source path
When this script gets executed, the image starts loading. If loading isn't finished when a drawImage statement gets executed, the script halts until the image is finished loading. If you don't want this to happen, use an onload event handler:
當腳本執行後,圖片開始裝載。若調用 drawImage 時,圖片沒裝載完,腳本會等待直至裝載完畢。如果不希望這樣,可以使用 onload 事件:
var img = new Image(); // Create new Image object img.onload = function(){ // execute drawImage statements here } img.src = 'myImage.png'; // Set source path
If you're only using one external image this can be a good approach but once you need to track more than one we need to resort to something more cunning. It's beyond the scope of this tutorial to look at image preloading tactics but you can check out JavaScript Image Preloader for a complete solution.
如果你只用到一張圖片的話,這已經夠了。但一旦需要不止一張圖片,那就需要更加復雜的處理方法,但圖片預裝載策略超出本教程的范圍,感興趣的話可以參考JavaScript Image Preloader。
Another possible way to include images is via the data: url. Data urls allow you to completely define an image as a Base64 encoded string of characters directly in your code. One advantage of data urls is that the resulting image is available immediately without another round trip to the server. ( Another advantage is that it is then possible to encapsulate in one file all of your CSS, Javascript, HTML, and images, making it more portable to other locations. ) Some disadvantages of this method are that your image is not cached, and for larger images the encoded url can become quite long:
我們還可以通過 data: url 方式來引用圖像。Data urls 允許用一串 Base64 編碼的字符串的方式來定義一個圖片。其優點就是圖片內容即時可用,無須再到服務器兜一圈。(還有一個優點是,可以將 CSS,JavaScript,HTML 和 圖片全部封裝在一起,遷移起來十分方便。)缺點就是圖像沒法緩存,圖片大的話內嵌的 url 數據會相當的長:
var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
Once we have a reference to our source image object we can use the drawImage method to render it to the canvas. As we we'll see later the drawImage method is overloaded and has three different variants. In its most basic form it looks like this.
一旦獲得了源圖對象,我們就可以使用 drawImage 方法將它渲染到 canvas 裡。drawImage 方法有三種形態,下面是最基礎的一種。
drawImage(image, x, y)
Where image is a reference to our image or canvas object. x and y form the coordinate on the target canvas where our image should be placed.
其中 image 是 image 或者 canvas 對象,x 和 y 是其在目標 canvas 裡的起始坐標。
In the following example I will be using an external image as the backdrop of a small line graph. Using backdrops can make your script considerably smaller because we don't need to draw an elaborate background. I'm only using one image here so I use the image object's onload event handler to execute the drawing statements. The drawImage method places the backdrop on the coordinate (0,0) which is the top left corner of the canvas.
下面一個例子我用一個外部圖像作為一線性圖的背景。用背景圖我們就不需要繪制負責的背景,省下不少代碼。這裡只用到一個 image 對象,於是就在它的 onload 事件響應函數中觸發繪制動作。drawImage 方法將背景圖放置在 canvas 的左上角 (0,0) 處。
function draw() {
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var img = new Image(); img.onload = function(){ ctx.drawImage(img,0,0); ctx.beginPath(); ctx.moveTo(30,96); ctx.lineTo(70,66); ctx.lineTo(103,76); ctx.lineTo(170,15); ctx.stroke(); } img.src = 'images/backdrop.png'; }
The second variant of the drawImage method adds two new parameters and it allows us to place scaled images on the canvas.
drawImage 方法的又一變種是增加了兩個用於控制圖像在 canvas 中縮放的參數。
drawImage(image, x, y, width, height)
Where width and height is the image's size on the target canvas. 當中 width 和 height 分別是圖像在 canvas 中顯示大小。
In this example I'm going to use an image as a wallpaper and repeat it several times on the canvas. This is done simply by looping and placing the scaled images at different positions. In the code below the first for loops through the rows the second for loop the columns. The image is scaled one third of its original size which is 50x38 pixels. We'll see how this could also have been achieved, by creating a custom pattern, later in this tutorial.
在這個例子裡,我會用一張圖片像背景一樣在 canvas 中以重復平鋪開來。實現起來也很簡單,只需要循環鋪開經過縮放的圖片即可。見下面的代碼,第一層 for 循環是做行重復,第二層是做列重復的。圖像大小被縮放至原來的三分之一,50x38 px。這種方法可以用來很好的達到背景圖案的效果,在下面的教程中會看到。
Note: Images can become blurry when scaling up or grainy if they're scaled down too much. Scaling is probably best not done if you've got some text in it which needs to remain legible.
注意:圖像可能會因為大幅度的縮放而變得起雜點或者模糊。如果您的圖像裡面有文字,那麼最好還是不要進行縮放,因為那樣處理之後很可能圖像裡的文字就會變得無法辨認了。
function draw() {
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var img = new Image(); img.onload = function(){ for (i=0;i<4;i++){ for (j=0;j<3;j++){ ctx.drawImage(img,j*50,i*38,50,38); } } } img.src = 'images/rhino.jpg'; }
The third and last variant of the drawImage method has eight new parameters. We can use this method to slice parts of a source image and draw them to the canvas.
drawImage 方法的第三個也是最後一個變種有8個新參數,用於控制做切片顯示的。
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
The first parameter image, just as with the other variants, is either a reference to an image object or a reference to a different canvas element. For the other eight parametes it's best to look at the image on the right. The first four parameters define the location and size of the slice on the source image. The last four parameters define the position and size on the destination canvas.
第一個參數和其它的是相同的,都是一個圖像或者另一個 canvas 的引用。其它8個參數最好是參照右邊的圖解,前4個是定義圖像源的切片位置和大小,後4個則是定義切片的目標顯示位置和大小。
Slicing can be a useful tool when you want to make compositions. You could have all elements in a single image file and use this method to composite a complete drawing. For instance, if you want to make a chart you could have a PNG image containing all the necessary text in a single file and depending on your data could change the scale of your chart without very much diffculty. Another advantage is that you don't need to load every image individually.
切片是個做圖像合成的強大工具。假設有一張包含了所有元素的圖像,那麼你可以用這個方法來合成一個完整圖像。例如,你想畫一張圖表,而手上有一個包含所有必需的文字的 PNG 文件,那麼你可以很輕易的根據實際數據的需要來改變最終顯示的圖表。這方法的另一個好處就是你不需要單獨裝載每一個圖像。
In this example I'm going to use the same rhino as we've seen above, but now I'm going to slice its head out and composite it into a picture frame. The image of the picture frame includes a dropshadow which has been saved as a 24-bit PNG image. Because 24-bit PNG images include a full 8-bit alpha channel, unlike GIF and 8-bit PNG images, I can place it onto any background and don't have to worry about a matte color.
在這個例子裡面我用到上面已經用過的犀牛圖像,不過這次我要給犀牛頭做個切片特寫,然後合成到一個相框裡面去。相框帶有陰影效果,是一個以 24-bit PNG 格式保存的圖像。因為 24-bit PNG 圖像帶有一個完整的 8-bit alpha 通道,與 GIF 和 8-bit PNG 不同,我可以將它放成背景而不必擔心底色的問題。
I took a different approach to the loading of the images than the example above. I just placed the images directly in my HTML document and used a CSS rule to hide them from view (display:none). I assigned both images an id attribute to make them easier to select. The script itself is very simple. I first draw the sliced and scaled image on the canvas (first drawImage statement), and then place the frame on top (second drawImage statement).
我用一個與上面用到的不同的方法來裝載圖像,直接將圖像插入到 HTML 裡面,然後通過 CSS 隱藏(display:none)它。兩個圖像我都賦了 id ,方便後面使用。看下面的腳本,相當簡單,首先對犀牛頭做好切片(第一個 drawImage )放在 canvas 上,然後再上面套個相框(第二個 drawImage )。
function draw() { var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); // Draw slice ctx.drawImage(document.getElementById('source'), 33,71,104,124,21,20,87,104); // Draw frame ctx.drawImage(document.getElementById('frame'),0,0); }
In the final example of this chapter I've made a little art gallery. The gallery consists of a table containing several images. When the page is loaded, for each image in the page a canvas element is inserted and a frame is drawn arround it.
In my case, all images have a fixed width and height, and so does the frame that's drawn around it. You could enhance the script so that it uses the image's width and height to make the frame fit perfectly around it.
The code below should be self-explanatory. We loop through the images array and add new canvas elements accordingly. Probably the only thing to note, for those not so familar with the DOM, is the use of the insertBefore method. insertBefore is a method of the parent node (a table cell) of the element (the image) before which we want to insert our new node (the canvas element).