Heim > Artikel > Web-Frontend > Canvas-API, beliebte Canvas-Grundkenntnisse (3)
Im vollständigen Text geht es darum, wie man Dreiecke, Kreise und andere verwandte Grafiken zeichnet. Schüler, die damit nicht vertraut sind, können nach rechts gehen, zuerst den vorherigen Text lesen und dann mit unseren Grafiken – Kurven – fortfahren.
Studenten, die Mathematik studiert haben oder mit js relativ vertraut sind, kennen alle die Bezier-Kurve. In der Mathematik ist dies natürlich ein tiefgreifendes Wissen Orte wie das Stiftwerkzeug in Photoshop, das Bézier-Werkzeug in CorelDraw usw. Es spiegelt sich auch in der Leinwand wider
Wenn Sie einfach nur eine Kurve zeichnen, können Sie natürlich auch die vorherige Methode verwenden:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.arc(100,100,100,0,90*Math.PI/180,false); ctx.stroke(); ctx.beginPath(); ctx.moveTo(103,103); ctx.arcTo(183,83,162,182,40); ctx.stroke();
Wenn Sie eine geschwungene Linie zeichnen möchten, wird es schwierig, dann erscheint der folgende Protagonist:
quadraticCurveTo(cpx,cpy,x,y) Quadratische Bezierkurve
Parameter: cpx, cpy repräsentiert den ersten Kontrollpunkt, x , y repräsentiert den Endpunkt
plus Der Startpunkt bedeutet, dass 3 Punkte eine Kurve steuern. Tatsächlich ähnelt dies der Verwendung von arcTo. Der Unterschied besteht darin, dass arcTo den Radius des Bogens angeben muss, da dieser 2 ist. Zeichnen Sie eine Kurve, die durch den Tangentenpunkt gebildet wird eines Kreises und einer geraden Linie in der Linie. Nach welchem Prinzip wird diese quadratische Bézier-Kurve gezeichnet? Lassen Sie uns gemeinsam ein Bild zeichnen:
Die allgemeine Regel der quadratischen Bezier-Kurve: Ausgehend vom Startpunkt gilt: Je näher die Kurve am Kontrollpunkt liegt, desto steiler ist die Kurve , und dann langsam Bewegen Sie sich vom Kontrollpunkt weg, die Kurve wird bis zum Endpunkt immer glatter, und diese Kurve verläuft tangential zum Startpunkt und zum Endpunkt
Ist dieser Kontrollpunkt ein bisschen so? Ein Magnet, der diese Kurve anzieht? Sport, wie das Sprichwort sagt, hören ist schlimmer als sehen, versuchen wir es:
ctx.moveTo(50,50); ctx.lineTo(70,120); ctx.lineTo(200,80); ctx.stroke(); ctx.beginPath(); ctx.moveTo(50,50); ctx.quadraticCurveTo(70,120,200,80); ctx.stroke();
Sehen Sie, ist das so? Natürlich gibt es eine Formel für den Grad der Kurvenbiegung, aber wir müssen uns nicht darum kümmern. Wir müssen uns nur an eines erinnern: die Die Kurve liegt näher am Kontrollpunkt, je steiler die Kurve, und je weiter vom Kontrollpunkt entfernt, desto steiler ist die Kurve. Oh!
Erinnern Sie mich noch einmal: Verstehen Sie jetzt den Unterschied zwischen arcTo und quadraticCurveTo?
Jetzt stellen wir die kubische Bezier-Kurve vor:
bezierCurveTo(cpx1,cpy1,cpx2,cpy2,x,y) Kubische Bezier-Kurve
Parameter: cpx1, cpy1 repräsentiert die Der erste Kontrollpunkt, cpx2, cpy2 repräsentiert den zweiten Kontrollpunkt x, y repräsentiert den Endpunkt
einschließlich des Startpunkts und bestimmt zusammen mit 4 Punkten eine Kurve Die Kurve ist dieselbe, mit nur einem weiteren Kontrollpunkt. Das Wesentliche ist immer noch dasselbe: Je näher die Kurve am Kontrollpunkt liegt, desto steiler ist die Kurve, und je weiter die Kurve vom Kontrollpunkt entfernt ist, desto flacher ist sie.
Beginnen wir mit einem einfachen Beispiel (Erstellen Sie eine U-Form):
ctx.moveTo(20,20); ctx.bezierCurveTo(20,100,200,100,200,20); ctx.stroke();
Wie im Bild oben gezeigt, ist Nr. eine ein Rendering und die zweite ist eine schematische Darstellung. Die Kurve beginnt am Startpunkt und es gibt einen Kontrollpunkt darunter. Die Position der Tangente zwischen dem zweiten Kontrollpunkt und der Kurve wird erreicht, weil sie von zwei Punkten gesteuert wird. Durch die Beeinflussung durch die Punkte beginnt die Kurve allmählich flacher zu werden, da die beiden Kontrollpunkte gerade symmetrisch sind, also am Mittelpunkt , wird die Kurve horizontal und wird dann weiterhin von den beiden Kontrollpunkten beeinflusst, wobei der zweite Kontrollpunkt immer wichtiger wird, da die Position des Tangentenpunkts zwischen dem ersten Kontrollpunkt und der Kurve bekannt ist vom zweiten Kontrollpunkt beeinflusst werden, und die Kraft wird umgekehrt, bis sie den Endpunkt erreicht, ähm, ich verstehe nicht, okay, verstehe es einfach nicht, wenn du es nicht verstehst. Erinnere dich einfach an diesen Schlusssatz!
Das klassische Beispiel ist das Sinusdiagramm (unter Verwendung von 2 Bezier-Kurven, einem positiven U und einem umgekehrten U):
ctx.beginPath(); ctx.moveTo(20,150); ctx.bezierCurveTo(20,50,150,50,150,150); ctx.stroke(); ctx.beginPath(); ctx.moveTo(150,150); ctx.bezierCurveTo(150,250,280,250,280,150); ctx.stroke();
Natürlich weiß ich nicht, dass kubische Bezier-Kurven U-förmige Diagramme zeichnen können, aber jede Kurve kann gezeichnet werden, solange man das nicht kann Denken Sie darüber nach, es gibt nichts, was Sie nicht zeichnen können. Haha, lasst uns unsere Fantasie erweitern!
Es wird gesagt, dass diejenigen, die malen, nicht immer Tuschemalerei machen sollten. Nun, Leinwand kann auch Farbverläufe wie CSS3 verwenden Zunächst einmal ist der Regenbogen nicht mehr weit, hehe
Schauen wir uns zunächst an, wie man den Farbverlauf von CSS3 einstellt, und vergleichen dann den Farbverlauf von Canvas. Wir alle wissen, dass Farbverläufe in lineare und radiale Farbverläufe unterteilt sind Vergleichen wir die Farbverläufe einzeln:
Linearer Farbverlauf:
.box1{ width:500px; height:50px; background: -webkit-linear-gradient(left, red 0%, #0F0 20%,rgb(51,102,255) 50%, rgba(204,255,0,0.8) 100%); }
css3可以指定颜色,支持各种颜色格式,且可以指定颜色所在位置,不仅如此,css3还可以指定渐变的方向:
.box1{ width:500px; height:50px; background: -webkit-linear-gradient(45deg , red 0%, #0F0 20%,rgb(51,102,255) 50%, rgba(204,255,0,0.8) 100%); }
方向可以用角度来定义,45度角是从左下到右上进行渐变
径向渐变:
.box2{ width:300px; height:200px; background:-webkit-radial-gradient(red 0%, #0F0 20%,rgb(51,102,255) 50%, rgba(204,255,0,0.8) 100%); }
渐变原点为中心,渐变颜色为百分百之间的颜色渐变
可以看出,径向渐变是以中心为原点,一圈一圈向外扩散,同样支持自定义颜色,支持各种颜色格式,支持指定位置,也是可以设置原点和渐变方式(圆形,椭圆):
.box2{ width:300px; height:200px; background:-webkit-radial-gradient(bottom left, ellipse,red 0%, #0F0 20%,rgb(51,102,255) 50%, rgba(204,255,0,0.8) 100%); }
原点左下,渐变形状为椭圆
.box2{ width:300px; height:200px; background:-webkit-radial-gradient(bottom left, circle,red 0%, #0F0 20%,rgb(51,102,255) 50%, rgba(204,255,0,0.8) 100%); }
原点左下,渐变形状为圆形
以上只是简单列举一下css3的渐变样式,当然css3的渐变肯定不止这些,这里主要是想对比一下canvas的渐变样式,顺便科普一下!
canvas的渐变相对要简单一些,没有那么多的花花肠子:
createLinearGradient(x1,y1,x2,y2) 创建线性渐变
参数:x1,y1 表示渐变起始点 x2,y2 表示渐变结束点
createRadialGradient(x1,y1,r1,x2,y2,r2) 创建径向渐变
参数:x1,y1 表示渐变开始圆心坐标,r1表示渐变开始圆的半径 x2,y2 表示渐变结束圆心坐标,r2表示渐变结束圆的半径
gradient.addColorStop(stop,color) 规定gradient 对象中的颜色和位置
参数: stop 取值0-1之间,表示渐变中开始与结束之间的位置 color表示渐变颜色
注意,这里添加渐变颜色的对象并不是context,而是gradient
怎么用呢?看线性渐变一个小例子:
这个科普一个误区:
ctx.fillRect(50,50,200,50); var line = ctx.createLinearGradient(50,50,200,50); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)');
这样是错误的,什么都出不来!
照理说,应该是先创建一个图像,然后给这个图形加渐变色,一般的规律都如此,比如画画,比如css,但是canvas不一样,重点来了:canvas凡是设置样式的,必须放在绘图前面 ,怎么理解这句话?
绘图的方法: fill() , fillRect() , stroke() , strokeRect() , rect()
那设置:比如文字类字体,字体大小,字体颜色,字体阴影,渐变色 路径类如线条,矩形,圆形,背景,渐变等等
所以正确的格式是:
var line = ctx.createLinearGradient(50,50,200,50); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,50);
可以看到canvas一样可以自定义颜色,支持各种颜色格式,支持指定位置(用0-1的数,跟百分比类似),相比css3之下,我觉得canvas的渐变颜色区域更加准确!
好了,既然canvas能像css3一样设置渐变样式,那可不可以设置方向呢?怎么设?以上面的代码为例,我们画一张图:
图可能画的有点蒙啊,解释一下,第一张图表示我们上面的代码显示的效果,渐变方向是(50,50)——> (200,50),是一条水平线,表示方向是从左到右渐变,要是我将坐标方向设为(50,50)——> (200,100),如第二张图,那么渐变是否是从左上角到右下角呢?我们试一下:
var line = ctx.createLinearGradient(50,50,200,100); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,50);
可以看出角度是正确的,createLinearGradient的2个坐标就是为了指明渐变方向的,那么canvas的径向渐变会不会跟css3相同呢?我们写一个小例子:
var line = ctx.createRadialGradient(150,150,0,150,150,200); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,150);
可以看到,如果图形即使不是一个正方形,径向渐变的圆依然是正圆,与css3的渐变机制有点不一样(css3是椭圆,看上面的css3图),并且渐变区域是根据两个圆来决定的,我们改一下这2个圆的区域看看:
var line = ctx.createRadialGradient(150,150,50,150,150,100); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,150);
比对上面的图可以看出,下图在50-100的区间里是有渐变的,其他地方则是首尾的颜色填充,那么圆心在边角上呢?
var line = ctx.createRadialGradient(50,50,0,50,50,200); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,150);
效果跟css3的样式一样,颜色更加准确,如果2圆的圆心不一样,会有什么反应?
var line = ctx.createRadialGradient(50,50,0,150,150,200); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillRect(50,50,200,150);
一个圆心在左上角,一个圆心在中间
咦,什么鬼,算了,如果想要正常的径向渐变,还是同圆心吧,不同圆心太诡异,hold 不住啊!
那径向渐变能像css3一样可以设置椭圆吗?咳咳,我只能借用一句台词:臣妾做不到啊!
我们来一个炫酷的渐变应用:
ctx.font = "40px 微软雅黑"; var line = ctx.createLinearGradient(10,100,200,100); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.fillText("狂拽炫酷吊炸天",10,100);
下面我们介绍另外一个与颜色有关的属性——透明!
globalAlpha = num 参数:num取值0-1之间 设置或返回绘图的当前透明值
有同学会问,按这个词的意思是全局透明,那么它是全局的吗?我也想问,那我们试一下:
ctx.fillStyle = "red"; ctx.fillRect(50,50,100,100); ctx.globalAlpha = 0.5; ctx.fillStyle = "green"; ctx.fillRect(100,100,100,100); ctx.fillStyle = "blue"; ctx.fillRect(150,150,100,100);
可以看到,第一个没有变透明,后面2个变透明了,那么如果我将路径闭合,是否还会出现这样的效果:
ctx.beginPath(); ctx.fillStyle = "red"; ctx.fillRect(50,50,100,100); ctx.closePath(); ctx.globalAlpha = 0.5; ctx.beginPath(); ctx.fillStyle = "green"; ctx.fillRect(100,100,100,100); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "blue"; ctx.fillRect(150,150,100,100); ctx.closePath();
结果是一样的,说明它是”人“如其名啊,果然是全局的,那么将它放入闭合路径中,会污染其他的路径吗?
ctx.beginPath(); ctx.globalAlpha = 0.5; ctx.fillStyle = "red"; ctx.fillRect(50,50,100,100); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "green"; ctx.fillRect(100,100,100,100); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "blue"; ctx.fillRect(150,150,100,100); ctx.closePath();
马蛋,简直是严重的核污染啊,穿透力如此之强?如果我只想让第一个透明,后面的不透明?我要怎么弄呢?
为了解决这个问题,我们需要引入2个方法,同样是一对活宝啊:
context.save() 保存当前环境的状态
context.restore() 返回之前保存过的路径状态和属性
怎么理解这对活宝呢?
可以这么理解:当设置了save()方法,就相当于将后面的绘图放在一个堆栈中,与世隔绝,知道看到restore(),就返回到原来的位置,举个例子哈,就像是一堆糖果,save()就是将一部分糖果装进盒子,restore()就是封闭盒子,继续捡糖果,但是盒子里的糖果就不会与其他糖果混合了,恩,可以这么理解,特别注意的是,restore()方法必须要有save()才起作用,你想啊,都没有盒子装糖果,怎么能封闭盒子呢
那咱们来看看他们的神奇技能:
ctx.save(); ctx.beginPath(); ctx.globalAlpha = 0.5; ctx.fillStyle = "red"; ctx.fillRect(50,50,100,100); ctx.closePath(); ctx.restore(); ctx.beginPath(); ctx.fillStyle = "green"; ctx.fillRect(100,100,100,100); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "blue"; ctx.fillRect(150,150,100,100); ctx.closePath();
哎呀,瞬间觉得整个世界都完美了!在面对凶悍的全局变量,属性或方法时,我们可以用上面的这对活宝来避免它们对我们需要的部分的侵害(这里为什么要说侵害,会让人想污的),确实是好技能!
回到globalAlpha,它的用处还是有很多的,路径,图形,文字都可以设置透明,那我们来一个文字透明看看:
ctx.font = "40px 微软雅黑"; var line = ctx.createLinearGradient(10,100,200,100); line.addColorStop(0,'red'); line.addColorStop(0.2 ,'#0F0'); line.addColorStop(0.5 ,'rgb(51,102,255)'); line.addColorStop(1 ,'rgba(204,255,0,0.8)'); ctx.fillStyle = line; ctx.globalAlpha = 0.3; ctx.fillText("狂拽炫酷吊炸天",10,100);
恩,今天就介绍到这里吧,后面的内容比较复杂,需要认真的准备,就这样吧!
以上就是canvas API ,通俗的canvas基础知识(三) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!
相关文章:
canvas API 介绍,常见的canvas基础知识(一)