Heim  >  Artikel  >  Web-Frontend  >  Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

黄舟
黄舟Original
2017-01-16 17:56:431237Durchsuche

Linienstile

Sie können den Linienstil über eine Reihe von Eigenschaften festlegen.

lineWidth = value
lineCap = type
lineJoin = type
miterLimit = value

Ich werde diese Eigenschaften im Detail erklären, aber anhand des folgenden Beispiels ist es möglicherweise einfacher, sie zu verstehen.

Beispiel für das lineWidth-Attribut

Dieses Attribut legt die Dicke der aktuell gezeichneten Linie fest. Der Immobilienwert muss positiv sein. Der Standardwert ist 1,0. Die Linienbreite bezieht sich auf die Dicke eines bestimmten Pfads von der Mitte zu den Seiten. Mit anderen Worten: Zeichnen Sie auf jeder Seite des Pfades die halbe Linienbreite. Da Leinwandkoordinaten nicht direkt Pixeln entsprechen, muss beim Erhalten präziser horizontaler oder vertikaler Linien besondere Aufmerksamkeit gewidmet werden. Im Beispiel unten werden 10 Linien mit zunehmender Breite gezeichnet. Die Zeile ganz links hat eine Breite von 1,0 Einheiten. Darüber hinaus können die Linie ganz links und alle Linien mit ungerader Breite aufgrund des Positionierungsproblems des Pfads nicht genau wiedergegeben werden.

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

function draw() {  
     var ctx = document.getElementById('canvas').getContext('2d');  
     for (var i = 0; i < 10; i++){  
       ctx.lineWidth = 1+i;  
       ctx.beginPath();  
       ctx.moveTo(5+i*14,5);  
       ctx.lineTo(5+i*14,140);  
       ctx.stroke();  
     }  
  }

Um genaue Linien zu erhalten, müssen Sie verstehen, wie Linien gezeichnet werden. Wie in der folgenden Abbildung dargestellt, wird ein Gitter verwendet, um das Koordinatengitter der Leinwand darzustellen. Jedes Gitter entspricht einem Pixel auf dem Bildschirm. Im ersten Bild ist das Rechteck von (2,1) bis (5,5) gefüllt, und die Grenze der gesamten Fläche fällt genau auf den Rand des Pixels, sodass das resultierende Rechteck klare Kanten hat.

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

Wenn Sie eine Linie von (3,1) nach (3,5) mit einer Breite von 1,0 zeichnen möchten, erhalten Sie in etwa das Ergebnis des zweiten Bildes. Der tatsächliche Füllbereich (dunkelblau) erstreckt sich nur über die Hälfte der Pixel auf beiden Seiten des Pfads. Diese halben Pixel werden ungefähr gerendert, was bedeutet, dass diese Pixel nur teilweise gefärbt sind, was dazu führt, dass der gesamte Bereich (die hellblauen und dunkelblauen Teile) mit einem halben Ton der tatsächlichen Strichfarbe gefüllt wird. Aus diesem Grund ist die Linie mit einer Breite von 1,0 im obigen Beispiel nicht korrekt. Um dieses Problem zu lösen, müssen Sie eine präzisere Kontrolle über den Pfad ausüben. Es ist bekannt, dass sich eine Linie mit einer Dicke von 1,0 auf beiden Seiten des Pfades um ein halbes Pixel erstreckt. Zeichnen Sie dann wie im dritten Bild eine Linie von (3,5,1) nach (3,5,5), und ihre Kante fällt genau auf der Pixelgrenze, und die Füllung ist genau. Eine Linie mit einer Breite von 1,0. Bei Linien mit gleichmäßiger Breite ist die Anzahl der Pixel auf jeder Seite eine ganze Zahl. Dann soll der Pfad zwischen den Pixeln liegen (z. B. von (3,1) bis (3,5)) und nicht innerhalb des Pixelpunkts mitten drin. Beachten Sie außerdem, dass die Y-Koordinate der vertikalen Linie in diesem Beispiel genau auf die Gitterlinie fällt. Andernfalls sind an den Endpunkten auch halb gerenderte Pixel vorhanden. Auch wenn die Arbeit mit skalierbaren 2D-Grafiken anfangs etwas mühsam sein kann, kann eine frühzeitige Beachtung der Beziehung zwischen Pixelraster und Pfadposition dafür sorgen, dass die Grafiken nach der Skalierung oder anderweitigen Verformung weiterhin gut aussehen: Linienbreite nach 2-facher Vergrößerung , wird die vertikale Linie mit einer Breite von 1,0 zu einer klaren Linie mit einer Breite von 2,0 und erscheint dort, wo sie erscheinen sollte.

lineCap
Beispiel für das Attribut

Attribut

Der Zeiger von lineCap bestimmt, wie die Endpunkte des Liniensegments angezeigt werden. Es gibt drei Typen: stumpf, rund und quadratisch. Der Standardwert ist Hintern.
In diesem Beispiel habe ich drei gerade Linien gezeichnet und jeder unterschiedliche lineCap-Werte zugewiesen. Es gibt auch zwei Hilfslinien, um den Unterschied zwischen ihnen deutlicher zu erkennen. Die Start- und Endpunkte der drei Linien liegen alle auf den Hilfslinien. Die Zeile ganz links verwendet die Standardschaltfläche. Beachten Sie, dass es bündig mit der Führungslinie abschließt. Der mittlere Effekt ist der runde Effekt, bei dem am Endpunkt ein Halbkreis mit einem Radius von der halben Linienbreite hinzugefügt wird. Das rechte ist der Effekt eines Quadrats. Die Endpunkte werden mit einem Quadrat gleicher Breite und einer Höhe der halben Linienbreite hinzugefügt.

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

function draw() {  
     var ctx = document.getElementById(&#39;canvas&#39;).getContext(&#39;2d&#39;);  
     var lineCap = [&#39;butt&#39;,&#39;round&#39;,&#39;square&#39;];  
      
     // Draw guides  
     ctx.strokeStyle = &#39;#09f&#39;;  
     ctx.beginPath();  
     ctx.moveTo(10,10);  
     ctx.lineTo(140,10);  
     ctx.moveTo(10,140);  
     ctx.lineTo(140,140);  
     ctx.stroke();  
     
     // Draw lines  
     ctx.strokeStyle = &#39;black&#39;;  
     for (var i=0;i<lineCap.length;i++){  
       ctx.lineWidth = 15;  
       ctx.lineCap = lineCap[i];  
       ctx.beginPath();  
       ctx.moveTo(25+i*50,10);  
       ctx.lineTo(25+i*50,140);  
       ctx.stroke();  
     }  
   }

Beispiel für das lineJoin
-Attribut

lineJoin的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round,bevel和miter。默认是miter。
这里我同样用三条折线来做例子,分别设置不同的lineJoin值。最上面一条是round的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter的效果。当值是miter的时候,线段会在连接处外侧延伸直至交于一点,延伸效果受到下面将要介绍的miterLimit属性的制约。

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

function draw() {  
      var ctx = document.getElementById(&#39;canvas&#39;).getContext(&#39;2d&#39;);  
      var lineJoin = [&#39;round&#39;,&#39;bevel&#39;,&#39;miter&#39;];  
      ctx.lineWidth = 10;  
      for (var i=0;i<lineJoin.length;i++){  
        ctx.lineJoin = lineJoin[i];  
        ctx.beginPath();  
        ctx.moveTo(-5,5+i*40);  
        ctx.lineTo(35,45+i*40);  
        ctx.lineTo(75,5+i*40);  
        ctx.lineTo(115,45+i*40);  
        ctx.lineTo(155,5+i*40);  
        ctx.stroke();  
     }  
   }

miterLimit
属性的演示例子

就如上一个例子所见的应用miter
的效果,线段的外侧边缘会延伸交汇于一点上。线段直接夹角比较大的,交点不会太远,但当夹角减少时,交点距离会呈指数级增大。miterLimit
属性就是用来设定外延交点与连接点的最大距离,如果交点距离大于此值,连接效果会变成了 bevel。

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

渐变 Gradients

就好像一般的绘图软件一样,我们可以用线性或者径向的渐变来填充或描边。我们用下面的方法新建一个canvasGradient
对象,并且赋给图形的fillStyle或strokeStyle


属性。

createLinearGradient(x1,y1,x2,y2)
createRadialGradient(x1,y1,r1,x2,y2,r2)


createLinearGradient方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。createRadialGradient方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。

var lineargradient = ctx.createLinearGradient(0,0,150,150);  
var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);


创建出canvasGradient对象后,我们就可以用addColorStop方法给它上色了。

addColorStop(position, color)

addColorStop
方法接受 2 个参数,position参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。你可以根据需要添加任意多个色标(color stops)。下面是最简单的线性黑白渐变的例子。

var lineargradient = ctx.createLinearGradient(0,0,150,150);  
 lineargradient.addColorStop(0,&#39;white&#39;);  
 lineargradient.addColorStop(1,&#39;black&#39;);

createLinearGradient
的例子

本例中,我弄了两种不同的渐变。第一种是背景色渐变,你会发现,我给同一位置设置了两种颜色,你也可以用这来实现突变的效果,就像这里从白色到绿色的突 变。一般情况下,色标的定义是无所谓顺序的,但是色标位置重复时,顺序就变得非常重要了。所以,保持色标定义顺序和它理想的顺序一致,结果应该没什么大问题。

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

第二种渐变,我并不是从 0.0 位置开始定义色标,因为那并不是那么严格的。在 0.5 处设一黑色色标,渐变会默认认为从起点到色标之间都是黑色。你会发现,strokeStyle
和fillStyle属性都可以接受canvasGradient对象。

function draw() {  
   var ctx = document.getElementById(&#39;canvas&#39;).getContext(&#39;2d&#39;);  
   
   // Create gradients  
   var lingrad = ctx.createLinearGradient(0,0,0,150);  
   lingrad.addColorStop(0, &#39;#00ABEB&#39;);  
   lingrad.addColorStop(0.5, &#39;#fff&#39;);  
   //lingrad.addColorStop(0.5, &#39;#26C000&#39;);  
   //lingrad.addColorStop(1, &#39;#fff&#39;);  
   
   var lingrad2 = ctx.createLinearGradient(0,50,0,95);  
   lingrad2.addColorStop(0.5, &#39;#000&#39;);  
   lingrad2.addColorStop(1, &#39;rgba(0,0,0,0)&#39;);  
   
   // assign gradients to fill and stroke styles  
   ctx.fillStyle = lingrad;  
   ctx.strokeStyle = lingrad2;  
     
   // draw shapes  
   ctx.fillRect(10,10,130,130);  
   ctx.strokeRect(50,50,50,50);

createRadialGradient
的例子

这个例子,我定义了 4 个不同的径向渐变。由于可以控制渐变的起始与结束点,所以我们可以实现一些比(如在 Photoshop 中所见的)经典的径向渐变更为复杂的效果。(经典的径向渐变是只有一个中心点,简单地由中心点向外围的圆形扩张)。这里,我让起点稍微偏离终点,这样可以达到一种球状 3D 效果。但最好不要让里圆与外圆部分交叠,那样会产生什么效果就真是不得而知了。4 个径向渐变效果的最后一个色标都是透明色。如果想要两色标直接的过渡柔和一些,只要两个颜色值一致就可以了。代码里面看不出来,是因为我用了两种不同的颜色表示方法,但其实是相同的,#019F62 = rgba(1,159,98,1)。

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

function draw() {
  var ctx = document.getElementById(&#39;canvas&#39;).getContext(&#39;2d&#39;);

  // Create gradients
  var radgrad = ctx.createRadialGradient(45,45,10,52,50,30);
  radgrad.addColorStop(0, &#39;#A7D30C&#39;);
  radgrad.addColorStop(0.9, &#39;#019F62&#39;);
  radgrad.addColorStop(1, &#39;rgba(1,159,98,0)&#39;);
  
  var radgrad2 = ctx.createRadialGradient(105,105,20,112,120,50);
  radgrad2.addColorStop(0, &#39;#FF5F98&#39;);
  radgrad2.addColorStop(0.75, &#39;#FF0188&#39;);
  radgrad2.addColorStop(1, &#39;rgba(255,1,136,0)&#39;);

  var radgrad3 = ctx.createRadialGradient(95,15,15,102,20,40);
  radgrad3.addColorStop(0, &#39;#00C9FF&#39;);
  radgrad3.addColorStop(0.8, &#39;#00B5E2&#39;);
  radgrad3.addColorStop(1, &#39;rgba(0,201,255,0)&#39;);

  var radgrad4 = ctx.createRadialGradient(0,150,50,0,140,90);
  radgrad4.addColorStop(0, &#39;#F4F201&#39;);
  radgrad4.addColorStop(0.8, &#39;#E4C700&#39;);
  radgrad4.addColorStop(1, &#39;rgba(228,199,0,0)&#39;);
  
  // draw shapes
  ctx.fillStyle = radgrad4;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad3;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad2;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad;
  ctx.fillRect(0,0,150,150);
}

图案 Patterns

上一节的一个例子里面,我用了循环来实现图案的效果。其实,有一个更加简单的方法:createPattern。


createPattern(image,type)

该方法接受两个参数。Image 可以是一个Image对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y
和no-repeat。图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给fillStyle或strokeStyle属性即可。

var img = new Image();  
 img.src = &#39;someimage.png&#39;;  
 var ptrn = ctx.createPattern(img,&#39;repeat&#39;);

注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。Firefox 目前只支持属性值repeat。如果赋其它值,什么效果都没有的。

createPattern
的例子

这最后的例子,我创建一个图案然后赋给了fillStyle属性。值得一提的是,使用 Image 对象的onloadhandler 来确保设置图案之前图像已经装载完毕。

Lernen zur Entwicklung von Canvas-Spielen, Teil 6: Verwendung von Stilen und Farben (2)

function draw() {
  var ctx = document.getElementById(&#39;canvas&#39;).getContext(&#39;2d&#39;);
  // create new image object to use as pattern
  var img = new Image();
  img.src = &#39;images/wallpaper.png&#39;;
  img.onload = function(){
    // create pattern
    var ptrn = ctx.createPattern(img,&#39;repeat&#39;);
    ctx.fillStyle = ptrn;
    ctx.fillRect(0,0,150,150);
  }
  }

以上就是canvas游戏开发学习之六:运用样式与颜色(二)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn