日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

用Canvas制作简单的画图工具

發(fā)布時間:2024/8/26 综合教程 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 用Canvas制作简单的画图工具 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

今天用Canvas制作了一個畫圖工具,非常簡單,功能也不是很多,主要有背景網(wǎng)格,畫線,畫圓,畫矩形和畫圓角矩形,也用到了canvas的一些基本知識,在這里一一列舉。

線段的繪制

如何繪制真正的1像素的線段?

如果在像素邊界處繪制一條1像素寬的垂直線段,那么canvas的繪圖環(huán)境對象會試著將半個像素畫在邊界中線的右邊,將另外半個像素畫在邊界中線的左邊。然而,在一個整像素的范圍內(nèi)繪制半個像素寬的線段是不可能的,,所以左右兩個方向上的半像素都被擴展為1像素。如圖所示

本來我們想要將線段繪制在深灰色的區(qū)域內(nèi),但實際上瀏覽器卻將其延伸繪制到整個灰色的范圍內(nèi)。

如果我們將線段繪制在兩個像素之間的那個像素中,這時出現(xiàn)的效果便成了下面圖片展示的效果:

這是因為當(dāng)線段繪制在兩個像素之間,中間左右兩端的那半個像素就不會再延伸了,它們合起來恰好占據(jù)了一個像素的寬度。

所以,如果要繪制一條真正的1像素寬的線段,必須將該線段繪制在某兩個像素之間的那個像素中。

在繪制背景網(wǎng)格中,繪制的線段寬度為0.5像素的,這是因為所有瀏覽器的Canvas都實現(xiàn)了“抗鋸齒”技術(shù),能呈現(xiàn)出“亞像素”線段的繪制效果來。

背景網(wǎng)格的繪制代碼如下:

 1 function drawGrid(color,stepx,stepy){
 2     context.save();
 3     context.strokeStyle = color;
 4     context.lineWidth = 0.5;
 5 
 6     for(var i = stepx + 0.5; i<context.canvas.width; i += stepx){
 7         context.beginPath();
 8         context.moveTo(i,0);
 9         context.lineTo(i,context.canvas.height);
10         context.stroke();
11     }
12     for(var i = stepy + 0.5;i<context.canvas.height; i += stepy){
13         context.beginPath();
14         context.moveTo(0,i);
15         context.lineTo(context.canvas.width,i);
16         context.stroke();
17     }
18     context.restore();
19 }

drawGrid

坐標(biāo)轉(zhuǎn)換

畫圖的一個基本轉(zhuǎn)換為將鼠標(biāo)坐標(biāo)轉(zhuǎn)換為Canvas坐標(biāo)。因為瀏覽器通過事件對象傳遞給監(jiān)聽器的鼠標(biāo)坐標(biāo)是窗口坐標(biāo),而不是相對于canvas的自身坐標(biāo),所以需要轉(zhuǎn)換。

轉(zhuǎn)換的代碼如下:

1 function windowToCanvas(x,y){
2     var bbox = canvas.getBoundingClientRect();
3     return {
4         x:x-bbox.left*(canvas.width / bbox.width),
5         y:y-bbox.top*(canvas.height / bbox.height)
6     };
7 }

windowToCanvas

監(jiān)聽事件

因為繪制圖畫是通過監(jiān)聽鼠標(biāo)事件進行的,該程序用了canvas.onmousedown,canvas.onmousemove和canvas.onmouseup事件進行繪制的。

當(dāng)mousedown時,記錄x坐標(biāo)和y坐標(biāo),設(shè)置畫圖標(biāo)簽dragging為True,并保存當(dāng)前畫布上所繪制的內(nèi)容。

保存當(dāng)前畫布上的內(nèi)容的函數(shù)如下:

1 function saveDrawingSurface(){
2     // getImageData() 復(fù)制畫布上指定矩形的像素數(shù)據(jù)
3     drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height);
4 }

saveDrawingSurface

當(dāng)mousemove時,記錄x坐標(biāo)和y坐標(biāo),恢復(fù)在mousedown時保存的畫布內(nèi)容,并在此基礎(chǔ)上繪制新的圖案。

恢復(fù)畫布上的內(nèi)容的函數(shù)如下:

1 function restoreDrawingSurface(){
2     //通過 putImageData() 將圖像數(shù)據(jù)放回畫布
3     context.putImageData(drawingSurfaceImageData,0,0);
4 }

restoreDrawingSurface

當(dāng)mouseup時,記錄x坐標(biāo)和y坐標(biāo),恢復(fù)在mousedown時保存的畫布內(nèi)容,并在此基礎(chǔ)上繪制新的圖案,最后將畫圖標(biāo)簽dragging設(shè)置為False。

畫圖

下面重點講解一下畫圓和畫圓形矩形的方法。

先說畫圓,畫圓需要知道圓心和半徑。首先利用反三角函數(shù)圓心和當(dāng)前鼠標(biāo)位置之間連線與X軸的夾角,然后用輔助矩陣的高度除以這個夾角的正弦值,來得出最終所畫圓形的半徑。

代碼如下:

 1 function drawRubberbandShapeCircle(loc){
 2     var angle,
 3         radius;
 4     if(mousedown.y === loc.y){
 5         radius = Math.abs(loc.x - mousedown.x);
 6     }else{
 7         angle = Math.atan(rubberbandRect.height/rubberbandRect.width);
 8         radius = rubberbandRect.height / Math.sin(angle);
 9     }
10     context.beginPath();
11     context.arc(mousedown.x,mousedown.y,radius,0,Math.PI*2,false);
12     context.stroke();
13 }

drawRubberbandShapeCircle

畫圓形矩形用的方法是arcTo(x1,y1,x2,y2.radius),arcTo方法的參數(shù)分別代表兩個點以及圓形的半徑該方法以指定的半徑來繪制一條圓弧,此圓弧與當(dāng)前點到第一個點(x1,y1)的連線相切,而且與第一個點到第二個點(x2,y2)的連線也相切。

那么如何通過arcTo繪制出矩形呢?因為arcTo()方法繪制的可能不僅僅是一段圓弧,如果在當(dāng)前路徑中有子路徑的話,那么瀏覽器會將子路徑的終點與圓弧的起點用線段連起來。

在某一時刻,canvas之中只能有一條路徑存在,Canvas規(guī)范將其稱為“當(dāng)前路徑”。然而這條路徑卻包含許多子路徑,而子路徑,又是由兩個或更多的點組成的。beginPath()方法會將當(dāng)前路徑中的所有子路徑都清楚掉。

圓形矩陣的代碼如下:

1 function roundedRect(cornerX,cornerY,width,height,cornerRadius){
2     context.moveTo(cornerX + cornerRadius, cornerY);
3     context.arcTo(cornerX + width, cornerY,cornerX + width,cornerY + height,cornerRadius);
4     context.arcTo(cornerX + width, cornerY + height,cornerX,cornerY + height,cornerRadius);
5     context.arcTo(cornerX, cornerY + height,cornerX,cornerY,cornerRadius);
6     context.arcTo(cornerX, cornerY,cornerX + cornerRadius,cornerY,cornerRadius);
7     context.stroke();
8 }

roundedRect

至此,畫圖工具就已經(jīng)可以用了。

源碼地址:git@github.com:weiruifeng/paint.git

總結(jié)

以上是生活随笔為你收集整理的用Canvas制作简单的画图工具的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。