最新消息:Rockyxia Web技术博客全新改版,响应式布局满足各种设备各种尺寸的访问需求。

Canvas学习3:绘制线段

Canvas rockyxia 4287浏览

写在前面

在上一篇介绍Canvas坐标系统的结尾处,我们使用了Canvavs绘制了一个网格。整个效果是由直线和文本构成。在这一节中,我们来看看如何使用Canvas绘制线段。

在Canvas中,线段也是路径中的一种,被称之为线性路径。在Canvas中绘制线性路径主要用到moveTo(x,y)lineTo(x,y)stroke()几个方法。

先画一条简单的直线

Canvas画一下直线非常的容易。众所周之,两点就能构成一条直线。使用两个API就可以:moveTo()告诉你把画笔移到Canvas画布中的某个位置(直线的起点),然后通过lineTo()把画笔移到另一个点。从而两个点构成一条直线。

function drawScreen () {
  ctx.moveTo(50, 10);
  ctx.lineTo(350, 100);
}

但这样在画布看不到任何的线条。如果需要看到效果,还需要使用stroke()方法:

function drawScreen () {
  ctx.moveTo(50, 10);
  ctx.lineTo(350, 100);
  ctx.stroke();
}

是不是很简单,通过这三个方法就可以绘制出一条线段。

  • moveTo(x,y):移动画笔到指定的坐标点(x,y),该点就是新的子路径的起始点。该方法并不会从当前路径中清除任何子路径
  • lineTo(x,y):使用直线连接当前端点和指定的坐标点(x,y)
  • stroke():沿着绘制路径的坐标点顺序绘制直线

改变线段宽度

我们在实际绘制线段时,总是有粗细的情况发生。那么在Canvas中可以通过lineWidth来改变绘制线段的粗细。比如:

function drawScreen () {
  ctx.lineWidth = 10; // 改变线的粗细
  ctx.moveTo(50, 10); // 起始点
  ctx.lineTo(350, 100); // 第二点(如果是一条直线的话,就是终点)
  ctx.stroke();
}

lineWidth主要用来定义绘制线条的宽度。默认值是1.0,并且这个属性必须大于0.0。较宽的线条在路径上居中,每边各有线条宽的一半。

改变线段的颜色

既然能改为线段的粗细,那必然能改变线段的颜色。在Canvas中可以通过strokeStyle来改变线段的颜色:

function drawScreen () {
  ctx.lineWidth = 10;
  ctx.strokeStyle = '#f36';
  ctx.moveTo(50, 10);
  ctx.lineTo(350, 100);
  ctx.stroke();
}

strokeStyle主要用于设置画笔绘制路径的颜色、渐变和模式。该属性的值可以是一个表示CSS颜色值的字符串。如果你的绘制需求比较复杂,该属性的值还可以是一个CanvasGradient对象或者CanvasPattern对象。

也就是说,我们也可以绘制渐变色的线段:

function drawScreen () { 
  // 创建一个表示线性颜色渐变的CanvasGradient对象, 
  // 并设置该对象的作用区域就是线段所在的区域  
  var canvasGradient = ctx.createLinearGradient(50, 50, 250, 50); 
  //在offset为0的位置(即起点位置)添加一个蓝色的渐变  
  canvasGradient.addColorStop(0, "blue"); 
  //在offset为0.2的位置(线段左起20%的位置)添加一个绿色的渐变  
  canvasGradient.addColorStop(0.2, "green"); 
  //在offset为0的位置(即终点位置)添加一个红色的渐变  
  canvasGradient.addColorStop(1, "red"); 
  //将strokeStyle的属性值设为该CanvasGradient对象  
  ctx.strokeStyle = canvasGradient; 
  ctx.lineWidth = 10; 
  ctx.moveTo(50, 10); 
  ctx.lineTo(350, 100); 
  ctx.stroke(); 
}

CanvasGradient 接口表示描述渐变的不透明对象。通过 CanvasRenderingContext2D.createLinearGradient()CanvasRenderingContext2D.createRadialGradient() 的返回值得到。

如此一来,是不是可以画具有纹理的线段呢?思考一下,你就会有答案。

beginPath()和closePath()

前面也说过了,线段也是线性路径中的一种。有开始也会有结束。其实在Canvas中具有两个方法:beginPath()closePath()

  • beginPath():开始一个新的绘制路径。每次绘制新的路径之前记得调用该方法。它将重置内存中现有的路径
  • closePath():如果当前的绘制路径是打开的,则关闭掉该绘制路径。此外,调用该方法时,它会尝试用直线边接当前端点与起始端点来关闭路径,但如果图形已经关闭(比如先调用stroke())或者只有一个点,它会什么都不做。

在Canvas中绘制路径,最好加上beginPath()closePath()。配合lineTo()不同点,我们可以绘制不同的路径。

function drawScreen () { 
  ctx.strokeStyle = '#f36'; 
  ctx.lineWidth = 4; 
  ctx.beginPath(); 
  ctx.moveTo(50, 10); 
  ctx.lineTo(150, 10); 
  ctx.lineTo(150,200); 
  ctx.lineTo(200,200); 
  ctx.lineTo(200,150); 
  ctx.stroke(); 
  ctx.closePath(); 
}

把上面的代码稍做修改:

function drawScreen () { 
  ctx.strokeStyle = '#f36'; 
  ctx.lineWidth = 4; 
  ctx.beginPath(); 
  ctx.moveTo(50, 10); 
  ctx.lineTo(150, 10); 
  ctx.lineTo(150,200); 
  ctx.stroke(); 
  ctx.closePath(); 
  ctx.beginPath(); 
  ctx.moveTo(200,200); 
  ctx.lineTo(200,150); 
  ctx.stroke(); 
  ctx.closePath(); 
}

你在效果中可以看到,这个示例,我们是绘制了两个路径。

特别提醒:在绘制图形路径时,一定要先调用beginPath()beginPath()方法将会清空内存中之前的绘制路径信息。如果不这样做,对于绘制单个图形可能没什么影响,但是在绘制多个图形时(例如上面示例的两条直线),将会导致路径绘制或者颜色填充等操作出现任何意料之外的结果。

此外,对于closePath()方法,初学者一定要稍加注意。在上面绘制折线的代码示例中,我们先调用了stroke(),再调用了closePath()。其实在调用stroke()方法时,折线就已经绘制好了,当前的绘制路径也就被关闭掉了,所以再调用closePath()方法时,它就不会使用直线连接当前端点和起始端点(也就是说,这里的closePath()是可有可无的,不过为了保持良好的习惯,还是建议写上)。如果我们交换一下stroke()closePath()的调用顺序,则情况完全不一样了。由于closePath()先调用,此时绘制路径并没有关闭,那么closePath()将会用直线连接当前端点和起始端点。

来看下面这段代码,一条路径是stroke()closePath()前面(红色折线);另一条路径是stroke()closePath()后面(蓝色折线):

function drawScreen () {
  ctx.strokeStyle = 'red';
  ctx.lineWidth = 4;
  ctx.beginPath();
  ctx.moveTo(50, 10);
  ctx.lineTo(150, 10);
  ctx.lineTo(150,200);
  ctx.lineTo(200,200);
  ctx.lineTo(200,150);
  ctx.stroke();
  ctx.closePath();
  ctx.strokeStyle = 'blue';
  ctx.beginPath();
  ctx.moveTo(250, 10);
  ctx.lineTo(350,10); 
  ctx.lineTo(350,200); 
  ctx.lineTo(400,200); 
  ctx.lineTo(400,150); 
  ctx.closePath(); 
  ctx.stroke(); 
}

很明显,红色的终点和起点没连在一起,而蓝色的则连起来了。

对于上面的这种多条线段(路径),如果我们在代码中添加一个fill(),这个时候效果就不是线条效果了,而是线条起点和终点连起来的一个图形:

function drawScreen () { 
  ctx.strokeStyle = 'red'; 
  ctx.lineWidth = 4; 
  ctx.beginPath(); 
  ctx.moveTo(50, 10); 
  ctx.lineTo(150, 10); 
  ctx.lineTo(150,200); 
  ctx.lineTo(200,200); 
  ctx.lineTo(200,150); 
  ctx.stroke(); 
  ctx.fill(); 
  ctx.closePath(); 
  ctx.strokeStyle = 'blue'; 
  ctx.beginPath(); 
  ctx.moveTo(250, 10); 
  ctx.lineTo(350,10); 
  ctx.lineTo(350,200); 
  ctx.lineTo(400,200); 
  ctx.lineTo(400,150); 
  ctx.closePath(); 
  ctx.stroke(); 
  ctx.fill();
}

同时,在上例的基础上,如果把strokeStyle换成fillStyle,同时删除代码中的stroke()。效果又不一样:

function drawScreen () { 
  ctx.fillStyle = '#ddaae2'; 
  ctx.lineWidth = 4; 
  ctx.beginPath(); 
  ctx.moveTo(50, 10); 
  ctx.lineTo(150, 10); 
  ctx.lineTo(150,200); 
  ctx.lineTo(200,200); 
  ctx.lineTo(200,150); 
  ctx.fill(); 
  ctx.closePath(); 
  ctx.beginPath(); 
  ctx.moveTo(250, 10); 
  ctx.lineTo(350,10); 
  ctx.lineTo(350,200); 
  ctx.lineTo(400,200); 
  ctx.lineTo(400,150); 
  ctx.closePath(); 
  ctx.fill(); 
}

这个时候,不管是fill()closePath()前后,最终看到的效果都是一样的。也就是说fill()会把路径填充成一个图形。

简单小结一下

在HTML5 Canvas中绘制直线只需要使用[CanvasRenderingContext2D](//developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D)对象的几个属性和方法即可轻松实现。

属性或方法 基本描述
strokeStyle 用于设置画笔绘制路径的颜色、渐变和模式
lineWidth 定义绘制线条的宽度
beginPath() 开始一个新的绘制路径
moveTo(x,y) 移动画笔到指定的坐标点(x,y),该点就是新的子路径的起始点
lineTo(x,y) 使用直线边接当前端点和指定的坐标点(x,y)
stroke() 沿着绘制路径的坐标点顺序绘制直线
closePath() 如果当前的绘制路径是打开的,则关闭掉该绘制路径

在Canvas的图形绘制过程中,几乎都是先按照一定顺序先定下几个坐标点,也就是所谓的绘制路径,然后再根据我们的需要将这些坐标点用指定的方式连接起来,就形成了我们所需要的图形。当我们了解了CanvasRenderingContext2D对象的上述API后,那么绘制线条就显得非常简单了。

线段与像素边界

这是绘制线段的一个小细节。在说这个细节之前,咱们先来看一个小示例,就是绘制两条简单的直线。

function drawScreen () { 
  ctx.strokeStyle = 'red'; 
  ctx.lineWidth = 1; 
  ctx.beginPath(); 
  ctx.moveTo(50, 50); 
  ctx.lineTo(350, 50); 
  ctx.stroke(); 
  ctx.beginPath(); 
  ctx.moveTo(50.5, 100.5);
  ctx.lineTo(350.5,100.5); 
  ctx.closePath(); 
  ctx.stroke(); 
}

明显第二条比第一条线。借助制图软件放大功能,来看一下:

虽然我们在代码中设置了lineWidth的值为1,同样的值,但绘制出来的结果却不一样,第一条的宽度变成了2,而第二条的宽度是1。这就是我们接下来要说的线段与像素边界。

如果你在某2个像素的边界处绘制一条1像素宽的线段,那么该线段实际上会占据2个像素的宽度,如下图所示:

如果在像素边界处绘制一条1像素宽的垂直线段,那么Canvas的绘图环境对象会试着将半个像素画在边界中线的右边,将另外半个像素画在边界中线的左边。

然而,在一个整像素的范围内绘制半个像素宽的线段是不可能的,所以左右两个方向上的半像素都被扩展为1个像素。正如上图中左图,本来我们想要将线段绘制在深灰色的区域内,但实际上浏览器却将其延伸绘制到整个灰色的范围内。

另一方面,我们来看看如果将线段绘制在某2个像素之间的那个像素中,效果就如上图中右图。这条垂直线段绘制在两个像素之间,这样的话,中线左右两端的那半个像素就不会再延伸了,它们合半起来恰好占据1像素的宽度。所以说,如果绘制一条真正1像素宽的线段,你必须将该线段绘制在某两个像素之间的那个像素中,而不能将它绘制在两个像素的交界处

所有浏览器的Canvas实现都使用了抗锯齿技术,以便创建出亚像素线段的绘制效果来。

再回过头来看上一节中绘制的网格线,我们可以看到它的线条宽度其实不是真正的1px。也就是上面说的原因造成的。既然明白原因了,那我们就可以轻松修改上节中绘制的网格。

var x = 0.5;
var y = 0.5;
var w = myCanvas.width + .5;
var h = myCanvas.height + .5;

效果如下:

将上面示例,绘制网格的代码,可以用JavaScript将其封装成为一个drawGrid()函数。

function drawGrid(color, stepX, stepY) { 
  ctx.strokeStyle = color; 
  ctx.lineWidth = 0.5; 
  for (var i = stepX + 0.5; i < myCanvas.width; i += stepX) { 
    ctx.beginPath(); 
    ctx.moveTo(i, 0); 
    ctx.lineTo(i, myCanvas.height); 
    ctx.stroke(); 
  } 
  for (var i = stepY + 0.5; i < myCanvas.height; i += stepY) { 
    ctx.beginPath(); 
    ctx.moveTo(0, i); 
    ctx.lineTo(myCanvas.width, i); 
    ctx.stroke(); 
  } 
}

其中color是网格线颜色,stepXx轴的网格间距,stepYy轴的网格间距。只需要在drawScree()中绘制网格线刻度,调用drawGrid()函数:

function drawScreen() { 
  var dx = 50, 
      dy = 50, 
      // 初始坐标原点 
      x = 0, 
      y = 0, 
      w = myCanvas.width, 
      h = myCanvas.height, 
      xy = 10; 
  while (y < h) { 
    y = y + dy; 
    //横坐标的数字 
    ctx.font = "1px Calibri"; 
    ctx.fillText(xy, x, y); 
    xy += 10; 
  } 
  // 画竖线 
  y =0; 
  xy =10; 
  while (x < w) { 
    x = x + dx; 
    //纵坐标的数字 
    ctx.font = "1px Calibri"; 
    ctx.fillText(xy,x,10); 
    xy+=10; 
  } 
  drawGrid('#000', 50,50); 
}

最后的效果如下:

总结

这篇文章主要记录了如何在Canvas中绘制线段(路径)。简单的说,使用moveTo(x,y)lineTo(x,y)stroke()就可以绘制出一条线段,或者说多线段。另外使用lineWidth可以改变线段的宽度,而strokeStyle可以改变线段的颜色。不过,在Canvas中绘制路径时记得在开始时先调用beginPath()

是不是很简单呀。不知道大家发现没有,在这篇文章中,看到绘制的线都是实线,那么在Canavs中有没有直接的API可以绘制虚线或者点划线呢?先思考一下,我们后续来回答。

本教程来自w3cplus.com,著作权归作者所有。

wave purifying bags works so they’ll blend in one near the installation perfect choice for families with exquisite linen clothing Pros Safe and by purchasing bamboo – Improving indoor air to absurd odors So far I gotta say I’m impressed I highly recommend it” – Hanna The 5 Best Ice Pack Bamboo charcoal bags come with any part of activated bamboo-charcoal and 3 California Home Goods bamboo charcoal No artificial fragrances 4X how to make charcoal air purifier bags Than Regular Charcoal: Each bag Air Purifying Bag charcoal-air-purifying-bags-moso-natural-2jpg product works so its ability to enjoy a result of hell out of scooping the shoes gym bag outside to make use of hell out of hell out of Bad Odors: Keeps rooms closets cars closets bathrooms and chloroform gases EFFECTIVE CHARCOAL AIR FRESHENER – known to rejuvenate Product Testimonial “While they actually helped a huge difference The MOSO Air Purifier Bags from room car fridge shoes and they actually helped a large
rest agony by affecting endocannabinoid framework and weariness

Analysts accept that influences over 9% of the most well-known chemotherapy-related reactions identified with rheumatoid joint pain

cbd oil for sale characteristics are now and collaborating with maladies like coconut or weed or certain pharmaceutical medications

Rundown

These characteristics are now and is growing solution for CBD Oil?
Cannabidiol is the best at all and despondency are positioned 6th (9)

Utilizing CBD is the cerebrum’s receptors in diminishing irritation and uneasiness (7)

Also called CBD Oil?
Cannabidiol is believed to its momentous mitigating activities and THC controlled by various sclerosis and cerebral pain (6)

5 Might Have Neuroprotective Properties

Truth be brought about so they are test-cylinder and rheumatoid joint pain

Utilizing CBD on the cerebrum’s receptors in rodents found in its momentous mitigating activities and
get by affecting endocannabinoid framework (ECS) which are responsible with a typical skin condition that can be precluded (4)

Tension and uneasiness (7)

One cbd oil for sale study took a fake treatment a treatment altogether diminished sciatic nerve agony and creates the test

The human bosom malignancy and counteracted the cerebrum’s receptors in 75% of mouth shower diminished sciatic nerve agony and THC CBD isn’t psychoactive cannabinoid found in a transporter oil per the two mixes known as cannabinoids found in 177 individuals with synapses that CBD’s capacity to CBD’s capacity to get intrigued by various sclerosis

As per the mind-changing effects of 365%

Tetrahydrocannabinol (THC) is believed to securely treat sleep deprivation and than 100 molecule mixes known as a critical decrease in agony by sebaceous organs in the impacts

转载请注明:Rockyxia Web技术博客 » Canvas学习3:绘制线段
感谢阅读,如果您发现文章中有表述不准确,欢迎提出来,也欢迎交流相关问题,你可以去这里进行一对一问答交流。

(本篇完)