Heim >Web-Frontend >H5-Tutorial >Canvas-API, beliebte Canvas-Grundlagen (4)
Worüber ich heute sprechen werde, ist die Konvertierungsfunktion von Canvas. Wenn Sie den vorherigen Inhalt nicht verstehen, können Sie einen Blick auf die Grundlagen werfen Kommen wir ohne Umschweife zur Sache!
Was ist die Konvertierungsfunktion? Schüler, die mit CSS3 vertraut sind, wissen, dass es in CSS3 Transformations-, Übersetzungs-, Rotations- und Animationsfunktionen gibt. Dies ist auch die Transformationsfunktion von CSS3, aber nur teilweise Welche werden im Vergleich zu CSS3 unterstützt?
1. Maßstab
scale(scaleWidth, scaleHeight) Skaliert die aktuelle Zeichnung
Parameter: scaleWidth stellt die Breite der aktuellen Zeichnung dar, mit Werten wie 0,5 = 50 %, 1 = 100 %, 2 = 200 % usw.; ScaleHeight bedeutet, die Höhe der aktuellen Zeichnung zu skalieren, mit Werten wie 0,5 = 50 %, 1 = 100 %, 2 = 200 % usw.
Wir Werfen Sie zunächst einen Blick auf die Leistung von CSS3:
css3 scale(sx,sy) sx,sy stellen die Skalierungsvektoren auf der Abszisse bzw. der Ordinate dar, mit Werten wie 0,5 = 50 %, 1 = 100 % , 2 = 200 % usw., die im Grunde mit „canvas“ identisch sind. Das Sprichwort ist nur anders. Da die Verwendung dieselbe ist, probieren wir es aus:
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);
Hey, Sie werden ein sehr seltsames Phänomen sehen. Es beginnt nicht mit der Skalierung vom Positionierungsursprung, sondern versetzt den Ursprung. Tatsächlich werden nicht nur die Grafiken skaliert. aber auch die Ränder der Grafiken werden ebenfalls skaliert, und das Skalierungsmultiplikator In Übereinstimmung mit Grafikmultiplikatoren werfen wir einen Blick darauf, wie sich die Skalierung von CSS3 verhält:
.box{ width:50px; height:50px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform:scale(2,2); }
Die Leistung von CSS3 besteht darin, den Mittelpunkt der Grafik als Ursprung zu nehmen und ihn dann um ihn herum zu skalieren Unterschiede zwischen der Skalierung von Canvas und der Skalierung von CSS3;
Einer der Unterschiede Der zweite besteht darin, dass die Skalierung von CSS3 auf einen Parameter verkürzt werden kann, wenn die Skalierungsfaktoren der x- und y-Achse gleich sind. Zum Beispiel:
.box:hover{ -webkit-transform:scale(2); }
Der Effekt ist derselbe. Ja, aber die beiden Parameter von Canvas können nicht abgekürzt werden, selbst wenn sie den gleichen Skalierungsfaktor haben. Beide Parameter müssen sein geschrieben, um ausgeführt zu werden;
Apropos, ich erinnere mich, dass es am Anfang von „canvasAPI“ eine Spannung gab, das heißt, die Breiten- und Höheneinstellungen der Leinwand müssen im Canvas-Tag-Attribut festgelegt werden und können nicht festgelegt werden in CSS. Warum ist das so? Schauen wir uns ein Beispiel an:
In der ersten Gruppe verwenden wir CSS, um die Breite und Höhe der Leinwand zu definieren, und es gibt keinen Stil für das Etikettenattribut:
canvas{ background:#fff; width:300px; height:300px; }
ctx.strokeStyle = 'red'; ctx.strokeRect(5,5,50,50);
Hey, was zum Teufel ist das?
In der zweiten Gruppe verwenden wir die Canvas-Tag-Attribute, um die Breite und Höhe ohne CSS-Einstellungen festzulegen:
<canvas width="300" height="300" id="canvas"> <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span> </canvas>
Offensichtlich sind die für das Etikettenattribut festgelegten Breiten und Höhen normal. Warum werden Breite und Höhe der CSS-Einstellung in einer so seltsamen Situation angezeigt? Der Grund dafür ist, dass die Leinwand selbst eine Standardbreite und -höhe hat (). Breite 300, Höhe 150. Wenn Sie die Breite und Höhe in CSS festlegen, geht die Leinwand davon aus, dass die Breite der Leinwand jetzt automatisch skaliert wird. Dann ist es verständlich. Die von CSS festgelegte Breite beträgt jetzt 300. Wenn die Höhe 300 beträgt, wird die Breite auf 300/300 skaliert und die Höhe wird auf natürliche Weise verdoppelt Aus diesem Grund müssen Breite und Höhe in den Eigenschaften der Leinwand festgelegt werden.
Gehen wir zurück zum Maßstab. Lassen Sie uns ein dynamisches Diagramm erstellen, um den Änderungsprozess der Skalierung zu sehen:
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)
Wie aus diesem GIF ersichtlich ist, besteht die Maßstabsänderung darin, erneut auf der Grundlage der vorherigen Zeichnung zu skalieren und dann erneut zu skalieren Der Timer wird wieder auf der Grundlage des Originals skaliert. Dies ist, wie es sein sollte, aber der Effekt sieht nicht gut aus. Kann ich einen Parameter festlegen und ihn mit nur einer Grafik langsam akkumulieren und skalieren lassen?
Nun, hier müssen wir eine Methode namens clearRect() erklären, was bedeutet, dass der Stil innerhalb des angegebenen Bereichs gelöscht wird. Wenn hier nur eine Grafik erforderlich ist, muss die vorherige Zeichnung vor der nächsten Grafik gelöscht werden Da die Zeit dazwischen sehr kurz ist, stellen wir zunächst die Methode „clearRect()“ vor:
clearRect(x,y,w,h) Parameter: w,y repräsentieren das Rechteck muss gelöscht werden. Die Koordinaten der oberen linken Ecke von , okay, schreiben wir gemeinsam den gewünschten Effekt:
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基础知识(一)