canvas API ,通俗的canvas基礎知識(四)
今天要講的內容是canvas的轉換功能,前面的內容沒用看的同學可以出門右轉,先看看前面的基礎知識,廢話不多說,開始進入正題吧!
何為轉換功能?熟悉css3的同學都知道,css3裡面有transform,translate,scale,rotate,animation等等,這就是css3的轉換功能,同樣,canvas也支持,但是只是支持部分,那我們來看看,都支持哪些,和css3相比,有什麼差別?
1、scale
scale(scaleWidth,scaleHeight) 縮放目前繪圖
參數:scaleWidth 表示縮放目前繪圖的寬度,取值如0.5 = 50% ,1 = 100% , 2 = 200% 以此類推; scaleHeight 表示縮放當前繪圖的高度,取值如0.5 = 50% ,1 = 100% , 2 = 200%以此類推
我們可以先看看css3是什麼表現:
css3 scale(sx,sy) sx,sy分別表示向橫座標和縱座標的縮放向量,取值如0.5 = 50% ,1 = 100% , 2 = 200%以此類推基本上跟canvas是一樣,只是說法不一樣而已,那既然用法是一樣的,我們就來試一下:
ctx.strokeStyle = 'red'; ctx.strokeRect(5,5,50,50); ctx.scale(2,2); ctx.strokeRect(5,5,50,50); ctx.scale(2,2); ctx.strokeRect(5,5,50,50);
咦,你會看到一個很奇怪的現象,它不是從定位的原點開始縮放的,而是偏移了原點,實際上是不僅僅是圖形縮放了,就連圖形的邊距也縮放了,且縮放的倍數與圖形倍數一致,我們看一下css3的scale會有什麼樣的表現:
.box{ width:50px; height:50px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform:scale(2,2); }
##css3的表現是以圖形的中心點為原點,然後向四周縮放,由此我們得到canvas 的scale與css3的scale的不同點之一;
不同點之二就是,css3的scale,如果x,y軸的縮放倍數一樣的話,是可以縮寫成一個參數的,如:
.box:hover{ -webkit-transform:scale(2); }
效果是一樣一樣的,但是canvas的2個參數即使縮放倍數一樣,也是不能進行簡寫的,必須2個參數都寫才能運行;
說到這裡,我想起來在canvasAPI開篇的時候留了一個懸念,就是canvas畫布的寬高設定必須在canvas標籤屬性上設置,而不能在css裡設置,這是為什麼呢?下面大家來看一個例子:
第一組,我們用css來定義canvas的寬高,標籤屬性上不設樣式:
canvas{ background:#fff; width:300px; height:300px; }
ctx.strokeStyle = 'red'; ctx.strokeRect(5,5,50,50);
咦,這是什麼鬼?
第二組,我們用canvas標籤屬性來設寬高,不用css設定:
#
<canvas width="300" height="300" id="canvas"> <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span> </canvas>
##明顯是在標籤屬性上設定的寬高是正常的,為什麼css設定寬高會出現這種詭異的狀況,原因是canvas本身是有預設寬高的(寬300,高150),如果在css中設定寬高,會讓canvas認為,現在canvas的寬度倍自動縮放了,縮放比例為css設定的寬度/300,高的也一樣,那麼就可以理解了,現在css設定的寬度是300,高的是300,那麼就會縮放寬=300/300,高縮放=300/150,高的自然就被拉高了一倍,所以這才是必須在canvas的屬性上設定寬高的原因
我們回到scale,我們來給一個動態圖,來看看scale的變化過程:
#
var timer = null; ctx.strokeStyle = 'red'; timer = setInterval(function(){ ctx.beginPath(); ctx.scale(1.5,1.5); ctx.strokeRect(5,5,50,50); ctx.closePath(); },500)
可以從這個gif圖中可以看出,scale的變化是在前面的一次繪圖的基礎上再次縮放,然後再縮放,有人說,你這個定時器是本來就是原來的基礎上再縮放一次,理所應該就是這樣,但是這個效果不好看,能不能我設一個參數,然後讓它累加,慢慢的縮放,而且只有一個圖形呢?
嗯,這裡就需要解釋一個方法叫clearRect(),表示在指定的範圍內清除樣式,這裡如果需要只有一個圖形,那麼就必須在下一次繪製圖形之前清除掉前面的一次繪圖,因為中間的時間極短,就感覺是連續的,我們先介紹一下這個clearRect()方法吧:
clearRect(x,y,w,h) 參數:w,y表示需要清除的矩形的左上角座標,w,h表示需要清除的矩形的寬高
從參數可以看出,它是可以清除局部區域的像素的,如果區域設為畫布,則是清除整個畫布了,好了,讓我們一起來寫一下你想要的那種效果:
var timer = null; var num = 1; ctx.strokeStyle = 'red'; timer = setInterval(function(){ if(parseInt(num) >=5){ clearInterval(timer); num =5; }else{ num +=0.1; } ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight); ctx.save(); ctx.beginPath(); ctx.scale(num,num); ctx.strokeRect(5,5,50,50); ctx.closePath(); ctx.restore(); },500)
看上图,现在就可以安安静静看它是怎么缩放的了,边距和图形一起缩放,比例也是一样的,这里的效果之所以没有和上面的gif图一样,在上一次缩放的基础上缩放,是因为这一对活宝:save()和restore(),这对活宝上一篇已经讲过了,如果还是不熟悉的同学出门右转,找到API的第3篇,这里的这一对主要功能是保存当前的路径,不被其他的路径污染,这对活宝和clearRect()在做运动的时候是非常有用的,这里终点提示一下!
2、rotate
rotate(angle) 旋转当前绘图 参数:angle表示旋转角度,这里需要填写弧度(弧度和角度的关系,在前面就已经讲过了,不熟悉的同学可以找到API的第2篇)
同样我们看一下css3 rotate的表现:
.box{ width:50px; height:50px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform:rotate(30deg); }
可以看到css3的旋转是以中心为原点进行旋转,切接受的参数直接就是角度,而不是弧度,那canvas的rotate的表现是什么呢?
ctx.fillStyle = 'red'; ctx.fillRect(0,0,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(0,0,150,50); ctx.closePath();
红色为初始图形,黑色为旋转图形,这是将图形坐标设置画布左上角的地方的
ctx.fillStyle = 'red'; ctx.fillRect(50,50,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(50,50,150,50); ctx.closePath();
图形坐标设置50,50处
ctx.fillStyle = 'red'; ctx.fillRect(100,100,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(100,100,150,50); ctx.closePath();
图形坐标设在100,100处
从这个3组效果中,我们可以得出这样的结论:
1、canvas的旋转原点并不是以自身的中心为原点,而是以画布的左上角为原点,3张图的比较可以看出来
2、图形的旋转原点也不是其自身的中心,而是其左上角为原点
这里说了2个原点,可能不好理解哈,几个例子,比如地球,它即绕太阳转,自己本身也转,那么它让太阳转就是我们说的第一点,图形绕画布旋转,准确的来说,也是图形的左上角绕画布左上角旋转,太阳的自转就是我们说的第2点,它自己本身的旋转,只不过canvas图形中的自转不是以中心为原点的旋转,其中心在左上角,这应该就明白看吧!
3、translate
translate(x,y) 重新映射画布上的 (0,0) 位置,这怎么理解?通俗的将,就是重新定义坐标原点,默认原点是(0,0),用此方法会将原点改成(x,y)
参数:x 添加到水平坐标(x)上的值 y添加到垂直坐标(y)上的值
定义不好理解,那我们就用例子来理解:
ctx.fillRect(10,10,100,100); //设置新原点 ctx.translate(110,110); ctx.fillRect(10,10,100,100);
首先我们画了一个100*100的矩形,图形坐标(10,10),因为默认原点是画布左上角,所以此图形在距离左上角(10,10)的位置,理论上说,我们再画一个一模一样的矩形,坐标也一样,2图形是会覆盖的,但是我们现在重新设置原点(110,110),刚好在第一个图形的右下角,这样方便观察,然后再画一个坐标和大小一模一样的矩形,我们来看看效果:
第二个矩形就刚好是以(110,110)为新的原点,然后距离新原点(10,10)的距离画了一个矩形,恩,这就是translate的作用
css3也是有translate的,我们不妨也来对比一下,下面我写一个css3的translate的例子:
.box{ width:150px; height:150px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform: translate(100px,0); }
从gif图可以看出,css3的translate是以自身中心为原点进行平移,但是不会改变原点坐标,所以,canvas的translate跟css3的translate又不一样
4、transform
transform(a,b,c,d,e,f) 替换当前的变换矩阵
参数:
a:水平缩放绘图
b:水平倾斜绘图
c:垂直倾斜绘图
d:垂直缩放绘图
e:水平移动绘图
f:垂直移动绘图
参数很多,但是看这参数的解释,还是很好理解,我们都知道css3的transform是一个集合,其中包含:scale,rotate,translate,skew和matrix,并且其中的matrix(矩阵)是可以转换成前面的任何效果的,换句话说,就是matrix(矩阵)可以包含前面的任何效果,包括自身,而canvas中的transform就是扮演css3的matrix的角色,只是跟css3的效果不一样而已,前面已经对比过了,具体的原理我们在这里就不说了,如果不清楚的,可以看一下css3的matrix是什么个原理,canvas的transform跟他的原理差不多!css3 matrix看这里
scale转成transform公式可得:
context.scale(sx, sy)
缩放我直接用公式来解释:
x’=sx*x
y’=sy*y
(其中,sx 和sy分别表示在x轴和y轴上的缩放倍数,x和y默认为1)
matrix(sx*x,0,0,sy*y,0,0) --> context.transform(sx*x,0,0,sy*y,0,0) -->context.transform(sx,0,0,sy,0,0)
ctx.fillRect(10,10,100,100); //缩放 ctx.transform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100);
rotate转化成transform
rotate(a*Math.PI/180)
公式推导就不推了,直接拿过来了
context.transform(cos(a),sin(a),-sin(a),cos(a),0,0) (a为角度)
--> context.transform(Math.cos(a*Math.PI/180),Math.sin(a*Math.PI/180),-Math.sin(a*Math.PI/180),Math.cos(a*Math.PI/180),0,0)
ctx.fillRect(10,10,100,100); //旋转 ctx.transform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100);
translate转化成transform
translate(tx,ty)
context.transform(1,0,0,1,tx,ty)
ctx.fillRect(10,10,100,100); //平移 ctx.transform(1,0,0,1,110,110); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100);
skew转化成transform
虽然canvas没有skew方法,但是transform依然可以做出来
context.transform(1,tan(ay),tan(ax),1,0,0) (ax,ay表示x方向,y方向的倾斜角度)
-->context.transform(1,Math.tan(ay*Math.PI/180),Math.tan(ax*Math.PI/180),1,0,0)
ctx.fillRect(10,10,100,100); //倾斜 ctx.transform(1,Math.tan(30*Math.PI/180),Math.tan(30*Math.PI/180),1,0,0) ctx.fillStyle="red"; ctx.fillRect(10,10,100,100);
那么,如果我想实现平移,旋转,倾斜加放大呢,怎么做?那就分开写呗:
ctx.fillRect(10,10,100,100); //综合 ctx.transform(1,0,0,1,110,110);//平移 ctx.transform(Math.cos(10*Math.PI/180),Math.sin(10*Math.PI/180),-Math.sin(10*Math.PI/180),Math.cos(30*Math.PI/180),0,0);//旋转 ctx.transform(0.5,0,0,0.5,0,0);//缩放 ctx.transform(1,Math.tan(30*Math.PI/180),Math.tan(30*Math.PI/180),1,0,0);//倾斜 ctx.fillStyle="red"; ctx.fillRect(10,10,100,100);
5、setTransform
setTransform(a,b,c,d,e,f) 当前的变换矩阵重置为单位矩阵,用法与transform相同
参数:
a:水平缩放绘图
b:水平倾斜绘图
c:垂直倾斜绘图
d:垂直缩放绘图
e:水平移动绘图
f:垂直移动绘图
怎么理解这个方法呢?
当我们用transform时,前面的变换方法会影响到后面的变换方法,我们俗称污染,比如:
//缩放 ctx.transform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100); ctx.beginPath(); //旋转 ctx.transform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="green"; ctx.fillRect(10,10,100,100);
前面的一个图形我想让它放大2倍,后面的我不想让它放大,而是想让它旋转30度,结果:
后面的图形也放大了2倍,这不是我们想要的结果,有人会说,我用save()和restore()不就可以了吗?
//缩放 ctx.save(); ctx.transform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100); ctx.restore(); ctx.beginPath(); //旋转 ctx.transform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="green"; ctx.fillRect(10,10,100,100);
如果你用这2个方法,我就不得不给你赞一个,说明前面的你看进去了
但是我想说的是,我们有更好的方法,就是我们现在要讲的这个--setTransform
//缩放 ctx.setTransform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100); ctx.beginPath(); //旋转 ctx.setTransform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="green"; ctx.fillRect(10,10,100,100);
效果跟上面的一样,官方解释是该变换只会影响 setTransform() 方法调用之后的绘图,当然,如果你把transform和setTransform一起混用,那也是会污染的:
//缩放 ctx.setTransform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100); ctx.beginPath(); //旋转 ctx.transform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="green"; ctx.fillRect(10,10,100,100);
要是把这2方法调个个看看:
//缩放 ctx.transform(2,0,0,2,0,0); ctx.fillStyle="red"; ctx.fillRect(10,10,100,100); ctx.beginPath(); //旋转 ctx.setTransform(Math.cos(30*Math.PI/180),Math.sin(30*Math.PI/180),-Math.sin(30*Math.PI/180),Math.cos(30*Math.PI/180),0,0); ctx.fillStyle="green"; ctx.fillRect(10,10,100,100);
看看,效果就又不一样了,所以,在用这些变换方法的时候,必须要弄清楚他们的作用范围和顺序,才能做出我们想要的效果,也不会污染其他的效果,这点,需谨记了!
好了,变换部分就讲完了,感谢大家的关注,如有将的不对的地方,希望能踊跃指正,不甚感谢!
以上就是canvas API ,通俗的canvas基础知识(四) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!
相关文章:
canvas API 介绍,常见的canvas基础知识(一)

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在用canvas的學校有史丹佛大學、麻省理工學院、哥倫比亞大學、加州大學柏克萊分校等。詳細介紹:1、史丹佛大學,使用Canvas作為其主要的線上學習平台,史丹佛大學的教師和學生使用Canvas來管理和交流課程內容,並透過線上討論、作業提交和考試等功能進行學習;2、麻省理工學院,MIT也採用了Canvas作為其線上學習管理系統,透過Canvas平台進行課程管理;3、哥倫比亞大學等

探索Canvas框架:了解常用的Canvas框架有哪些,需要具體程式碼範例引言:Canvas是HTML5中提供的一個繪圖API,透過它我們可以實現豐富的圖形和動畫效果。為了提高繪圖的效率和便利性,許多開發者開發了不同的Canvas框架。本文將介紹一些常用的Canvas框架,並提供具體程式碼範例,以幫助讀者更深入地了解這些框架的使用方法。一、EaselJS框架Ea

uniapp實現如何使用canvas繪製圖表和動畫效果,需要具體程式碼範例一、引言隨著行動裝置的普及,越來越多的應用程式需要在行動裝置上展示各種圖表和動畫效果。而uniapp作為一款基於Vue.js的跨平台開發框架,提供了使用canvas繪製圖表和動畫效果的能力。本文將介紹uniapp如何使用canvas來實現圖表和動畫效果,並給出具體的程式碼範例。二、canvas

canvas箭頭外掛有:1、Fabric.js,具有簡單易用的API,可以創建自訂箭頭效果;2、Konva.js,提供了繪製箭頭的功能,可以創建各種箭頭樣式;3、Pixi.js ,提供了豐富的圖形處理功能,可以實現各種箭頭效果;4、Two.js,可以輕鬆地創建和控制箭頭的樣式和動畫;5、Arrow.js,可以創建各種箭頭效果;6、Rough .js,可以創造手繪效果的箭頭等。

html2canvas的版本有html2canvas v0.x、html2canvas v1.x等。詳細介紹:1、html2canvas v0.x,這是html2canvas的早期版本,目前最新的穩定版本是v0.5.0-alpha1。它是一個成熟的版本,已經被廣泛使用,並且在許多專案中得到了驗證;2、html2canvas v1.x,這是html2canvas的新版本。

canvas時鐘的細節有時鐘外觀、刻度線、數位時鐘、時針、分針和秒針、中心點、動畫效果、其他樣式等。詳細介紹:1、時鐘外觀,可以使用Canvas繪製一個圓形錶盤作為時鐘的外觀,可以設定錶盤的大小、顏色、邊框等樣式;2、刻度線,在錶盤上繪製刻度線,表示小時或分鐘的位置;3、數位時鐘,可在錶盤上繪製數位時鐘,表示目前的小時和分鐘;4、時針、分針和秒針等等。

了解canvas在遊戲開發中的威力與應用概述:隨著網路科技的快速發展,網頁遊戲越來越受到廣大玩家的喜愛。而作為網頁遊戲開發中重要的一環,canvas技術在遊戲開發中逐漸嶄露頭角,展現出強大的威力與應用。本文將介紹canvas在遊戲開發中的潛力,並透過具體的程式碼範例來展示其應用。一、canvas技術簡介canvas是HTML5中新增的元素,它允許我們使用

tkinter canvas屬性有bg、bd、relief、width、height、cursor、highlightbackground、highlightcolor、highlightthickness、insertbackground、insertwidth、selectbackground、selectforeground、xscrollcommand屬性等等。詳細介紹
