Styles de ligne
Vous pouvez définir le style de ligne via une série de propriétés.
lineWidth = value lineCap = type lineJoin = type miterLimit = value
Je vais expliquer ces propriétés en détail, mais cela peut être plus facile à comprendre avec l'exemple suivant.
Exemple d'attribut lineWidth
Cet attribut définit l'épaisseur de la ligne actuellement tracée. La valeur de la propriété doit être positive. La valeur par défaut est 1,0. La largeur de ligne fait référence à l’épaisseur d’un chemin donné du centre vers les côtés. En d’autres termes, tracez la moitié de la largeur du trait de chaque côté du chemin. Les coordonnées du canevas ne correspondant pas directement aux pixels, une attention particulière doit être portée lors de l'obtention de lignes horizontales ou verticales précises. Dans l'exemple ci-dessous, 10 lignes sont tracées avec une largeur croissante. La ligne la plus à gauche a une largeur de 1,0 unités. De plus, les lignes les plus à gauche et toutes les lignes de largeur impaire ne peuvent pas être restituées avec précision en raison du problème de positionnement du chemin.
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(); } }
Pour obtenir des lignes précises, vous devez comprendre comment les lignes sont tracées. Comme le montre la figure ci-dessous, une grille est utilisée pour représenter la grille de coordonnées du canevas. Chaque grille correspond à un pixel sur l'écran. Dans la première image, le rectangle (2,1) à (5,5) est rempli et la limite de toute la zone tombe exactement sur le bord du pixel, de sorte que le rectangle résultant ait des bords clairs.
Si vous souhaitez tracer une ligne de (3,1) à (3,5) avec une largeur de 1,0, vous obtiendrez quelque chose comme le résultat de la deuxième image. La zone de remplissage réelle (bleu foncé) ne s'étend que sur la moitié des pixels de chaque côté du chemin. Ces demi-pixels sont rendus de manière approximative, ce qui signifie que ces pixels ne sont que partiellement colorés, ce qui fait que la zone entière (bleu clair et bleu foncé) est remplie avec la moitié du ton de la couleur réelle du trait. C'est pourquoi la ligne d'une largeur de 1,0 dans l'exemple ci-dessus n'est pas exacte. Pour résoudre ce problème, vous devez exercer un contrôle plus précis sur le chemin. On sait qu'une ligne d'une épaisseur de 1,0 s'étendra sur un demi-pixel des deux côtés du chemin, puis tracera une ligne de (3,5,1) à (3,5,5) comme la troisième image, et son bord tombera exactement sur la limite des pixels, et le remplissage sera précis. Une ligne d'une largeur de 1,0. Pour les lignes de largeur paire, le nombre de pixels de chaque côté est un nombre entier, vous souhaitez donc que le chemin se situe entre les pixels (par exemple de (3,1) à (3,5)) plutôt qu'à l'intérieur du point de pixels. au milieu. Notez également que la ligne verticale dans cet exemple a sa coordonnée Y tombant exactement sur la ligne de la grille. Si ce n'est pas le cas, il y aura également des pixels à moitié rendus aux extrémités. Bien que travailler avec des graphiques 2D évolutifs puisse s'avérer un peu pénible au début, une attention précoce portée à la relation entre la grille de pixels et la position du chemin peut garantir que les graphiques conserveront leur belle apparence après avoir été mis à l'échelle ou déformés d'une autre manière : largeur de ligne Après grossissement 2 fois , la ligne verticale d'une largeur de 1,0 deviendra une ligne claire d'une largeur de 2,0 et apparaîtra là où elle devrait apparaître.
lineCap
exemple d'attribut
attribut
Le pointeur de lineCap détermine la manière dont les extrémités du segment de ligne sont affichées. Il peut être de l'un des trois types suivants : bout à bout, rond et carré. La valeur par défaut est les fesses.
Dans cet exemple, j'ai dessiné trois lignes droites et attribué à chacune des valeurs lineCap différentes. Il existe également deux lignes auxiliaires. Afin de voir plus clairement la différence entre elles, les points de départ et les points finaux des trois lignes tombent tous sur les lignes auxiliaires. La ligne la plus à gauche utilise le bouton par défaut. Notez qu'il affleure la ligne de guidage. Celui du milieu est l'effet rond, avec un demi-cercle d'un rayon de la moitié de la largeur de la ligne ajouté au point final. Celui de droite est l’effet d’un carré, avec un carré de largeur égale et la moitié de la largeur de la ligne ajouté au point final.
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var lineCap = ['butt','round','square']; // Draw guides ctx.strokeStyle = '#09f'; ctx.beginPath(); ctx.moveTo(10,10); ctx.lineTo(140,10); ctx.moveTo(10,140); ctx.lineTo(140,140); ctx.stroke(); // Draw lines ctx.strokeStyle = 'black'; 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(); } }
lineJoin
exemple d'attribut
lineJoin的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round,bevel和miter。默认是miter。
这里我同样用三条折线来做例子,分别设置不同的lineJoin值。最上面一条是round的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter的效果。当值是miter的时候,线段会在连接处外侧延伸直至交于一点,延伸效果受到下面将要介绍的miterLimit属性的制约。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var lineJoin = ['round','bevel','miter']; 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。
渐变 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,'white'); lineargradient.addColorStop(1,'black');
createLinearGradient
的例子
本例中,我弄了两种不同的渐变。第一种是背景色渐变,你会发现,我给同一位置设置了两种颜色,你也可以用这来实现突变的效果,就像这里从白色到绿色的突 变。一般情况下,色标的定义是无所谓顺序的,但是色标位置重复时,顺序就变得非常重要了。所以,保持色标定义顺序和它理想的顺序一致,结果应该没什么大问题。
第二种渐变,我并不是从 0.0 位置开始定义色标,因为那并不是那么严格的。在 0.5 处设一黑色色标,渐变会默认认为从起点到色标之间都是黑色。你会发现,strokeStyle
和fillStyle属性都可以接受canvasGradient对象。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // Create gradients var lingrad = ctx.createLinearGradient(0,0,0,150); lingrad.addColorStop(0, '#00ABEB'); lingrad.addColorStop(0.5, '#fff'); //lingrad.addColorStop(0.5, '#26C000'); //lingrad.addColorStop(1, '#fff'); var lingrad2 = ctx.createLinearGradient(0,50,0,95); lingrad2.addColorStop(0.5, '#000'); lingrad2.addColorStop(1, 'rgba(0,0,0,0)'); // 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)。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // Create gradients var radgrad = ctx.createRadialGradient(45,45,10,52,50,30); radgrad.addColorStop(0, '#A7D30C'); radgrad.addColorStop(0.9, '#019F62'); radgrad.addColorStop(1, 'rgba(1,159,98,0)'); var radgrad2 = ctx.createRadialGradient(105,105,20,112,120,50); radgrad2.addColorStop(0, '#FF5F98'); radgrad2.addColorStop(0.75, '#FF0188'); radgrad2.addColorStop(1, 'rgba(255,1,136,0)'); var radgrad3 = ctx.createRadialGradient(95,15,15,102,20,40); radgrad3.addColorStop(0, '#00C9FF'); radgrad3.addColorStop(0.8, '#00B5E2'); radgrad3.addColorStop(1, 'rgba(0,201,255,0)'); var radgrad4 = ctx.createRadialGradient(0,150,50,0,140,90); radgrad4.addColorStop(0, '#F4F201'); radgrad4.addColorStop(0.8, '#E4C700'); radgrad4.addColorStop(1, 'rgba(228,199,0,0)'); // 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 = 'someimage.png'; var ptrn = ctx.createPattern(img,'repeat');
注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。Firefox 目前只支持属性值repeat。如果赋其它值,什么效果都没有的。
createPattern
的例子
这最后的例子,我创建一个图案然后赋给了fillStyle属性。值得一提的是,使用 Image 对象的onloadhandler 来确保设置图案之前图像已经装载完毕。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // create new image object to use as pattern var img = new Image(); img.src = 'images/wallpaper.png'; img.onload = function(){ // create pattern var ptrn = ctx.createPattern(img,'repeat'); ctx.fillStyle = ptrn; ctx.fillRect(0,0,150,150); } }
以上就是canvas游戏开发学习之六:运用样式与颜色(二)的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!