首頁 web前端 H5教程 canvas API ,通俗的canvas基礎知識(四)

canvas API ,通俗的canvas基礎知識(四)

Mar 16, 2017 pm 01:45 PM

今天要講的內容是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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)

咦,你會看到一個很奇怪的現象,它不是從定位的原點開始縮放的,而是偏移了原點,實際上是不僅僅是圖形縮放了,就連圖形的邊距也縮放了,且縮放的倍數與圖形倍數一致,我們看一下css3的scale會有什麼樣的表現:

.box{
    width:50px;
    height:50px;
    border:1px solid #000;
    margin:20px;
}
.box:hover{
    -webkit-transform:scale(2,2);
}
登入後複製



canvas API ,通俗的canvas基礎知識(四)

canvas API ,通俗的canvas基礎知識(四)
##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 API ,通俗的canvas基礎知識(四)
咦,這是什麼鬼?

第二組,我們用canvas標籤屬性來設寬高,不用css設定:


#

<canvas width="300" height="300" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span>
</canvas>
登入後複製



canvas API ,通俗的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 = &#39;red&#39;;
timer = setInterval(function(){
    ctx.beginPath();
    ctx.scale(1.5,1.5);
    ctx.strokeRect(5,5,50,50);
    ctx.closePath();
},500)
登入後複製


canvas API ,通俗的canvas基礎知識(四)可以從這個gif圖中可以看出,scale的變化是在前面的一次繪圖的基礎上再次縮放,然後再縮放,有人說,你這個定時器是本來就是原來的基礎上再縮放一次,理所應該就是這樣,但是這個效果不好看,能不能我設一個參數,然後讓它累加,慢慢的縮放,而且只有一個圖形呢?

嗯,這裡就需要解釋一個方法叫clearRect(),表示在指定的範圍內清除樣式,這裡如果需要只有一個圖形,那麼就必須在下一次繪製圖形之前清除掉前面的一次繪圖,因為中間的時間極短,就感覺是連續的,我們先介紹一下這個clearRect()方法吧:

clearRect(x,y,w,h) 參數:w,y表示需要清除的矩形的左上角座標,w,h表示需要清除的矩形的寬高

從參數可以看出,它是可以清除局部區域的像素的,如果區域設為畫布,則是清除整個畫布了,好了,讓我們一起來寫一下你想要的那種效果:


var timer = null;
        var num = 1;
        ctx.strokeStyle = &#39;red&#39;;
        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)
登入後複製


canvas API ,通俗的canvas基礎知識(四)

看上图,现在就可以安安静静看它是怎么缩放的了,边距和图形一起缩放,比例也是一样的,这里的效果之所以没有和上面的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);
}
登入後複製


canvas API ,通俗的canvas基礎知識(四)

可以看到css3的旋转是以中心为原点进行旋转,切接受的参数直接就是角度,而不是弧度,那canvas的rotate的表现是什么呢?

ctx.fillStyle = &#39;red&#39;;
ctx.fillRect(0,0,150,50);
ctx.beginPath();
ctx.rotate(30*Math.PI/180);
ctx.strokeRect(0,0,150,50);
ctx.closePath();
登入後複製


canvas API ,通俗的canvas基礎知識(四)
红色为初始图形,黑色为旋转图形,这是将图形坐标设置画布左上角的地方的

ctx.fillStyle = &#39;red&#39;;
ctx.fillRect(50,50,150,50);
ctx.beginPath();
ctx.rotate(30*Math.PI/180);
ctx.strokeRect(50,50,150,50);
ctx.closePath();
登入後複製


canvas API ,通俗的canvas基礎知識(四)
图形坐标设置50,50处

ctx.fillStyle = &#39;red&#39;;
ctx.fillRect(100,100,150,50);
ctx.beginPath();
ctx.rotate(30*Math.PI/180);
ctx.strokeRect(100,100,150,50);
ctx.closePath();
登入後複製


canvas API ,通俗的canvas基礎知識(四)
图形坐标设在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),刚好在第一个图形的右下角,这样方便观察,然后再画一个坐标和大小一模一样的矩形,我们来看看效果:

canvas API ,通俗的canvas基礎知識(四)

第二个矩形就刚好是以(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);
}
登入後複製


canvas API ,通俗的canvas基礎知識(四)

从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);
登入後複製


canvas API ,通俗的canvas基礎知識(四)

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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)

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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)



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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)

那么,如果我想实现平移,旋转,倾斜加放大呢,怎么做?那就分开写呗:

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);
登入後複製


canvas API ,通俗的canvas基礎知識(四)

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度,结果:

canvas API ,通俗的canvas基礎知識(四)

后面的图形也放大了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个方法,我就不得不给你赞一个,说明前面的你看进去了

canvas API ,通俗的canvas基礎知識(四)

但是我想说的是,我们有更好的方法,就是我们现在要讲的这个--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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)

效果跟上面的一样,官方解释是该变换只会影响 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);
登入後複製



canvas API ,通俗的canvas基礎知識(四)

要是把这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基礎知識(四)

看看,效果就又不一样了,所以,在用这些变换方法的时候,必须要弄清楚他们的作用范围和顺序,才能做出我们想要的效果,也不会污染其他的效果,这点,需谨记了!

好了,变换部分就讲完了,感谢大家的关注,如有将的不对的地方,希望能踊跃指正,不甚感谢!

 以上就是canvas API ,通俗的canvas基础知识(四) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

相关文章:

canvas API 介绍,常见的canvas基础知识(一)

canvas API 介绍,常见的canvas基础知识(二)

canvas API 介绍,常见的canvas基础知识(三)

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1249
24
canvas哪些學校用 canvas哪些學校用 Aug 18, 2023 pm 05:59 PM

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

學習canvas框架 詳解常用的canvas框架 學習canvas框架 詳解常用的canvas框架 Jan 17, 2024 am 11:03 AM

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

uniapp實現如何使用canvas繪製圖表和動畫效果 uniapp實現如何使用canvas繪製圖表和動畫效果 Oct 18, 2023 am 10:42 AM

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

canvas箭頭插件有哪些 canvas箭頭插件有哪些 Aug 21, 2023 pm 02:14 PM

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

html2canvas有哪些版本 html2canvas有哪些版本 Aug 22, 2023 pm 05:58 PM

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

canvas時鐘有哪些細節 canvas時鐘有哪些細節 Aug 21, 2023 pm 05:07 PM

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

探索canvas在遊戲開發中的強大作用及應用 探索canvas在遊戲開發中的強大作用及應用 Jan 17, 2024 am 11:00 AM

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

tkinter canvas有哪些屬性 tkinter canvas有哪些屬性 Aug 21, 2023 pm 05:46 PM

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

See all articles