likes
comments
collection
share

我就不信,你不知道这些 Canvas 线条属性

作者站长头像
站长
· 阅读数 18

线条样式

前言

“唰”,“唰”,“唰”,还记得学习素描的时候,我们会用不同的笔来绘制各种各样的线条,有粗有细,有虚有实,有深有浅,有平行有相交。这一节我们将拿起画笔,就单纯的画画线,打打底子。那么在 Canvas 中,是通过什么属性或者方法来定义线条的样式呢?

为了本文讲解,本文中所有的 Canvas 上下文用 ctx 对象来表示

lineWidth 属性

ctx.lineWidth = 整数;

Linewidth 属性取值为整数,默认为1,单位 px。

这个属性前面的文章也用过,没有做任何的讲解,但是我想大家应该看了就知道这就是线宽的设置,通过文本意义应该一目了然。

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 10;
  ctx.strokeStyle = "hotpink";
  ctx.moveTo(20, 30);
  ctx.lineTo(180, 30);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.moveTo(20, 70);
  ctx.lineTo(180, 70);
  ctx.stroke();

  ctx.beginPath();
  ctx.moveTo(20, 120);
  ctx.lineTo(180, 120);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

我们结合图和代码来看一下,第二条线和第三条线为啥线宽是一样的 5px 呢?那是因为在每一次绘制的时候,Canvas 会检测整个代码定义的样式,如果在新的路径中没有定义样式,则会延用原来定义样式。

我们再来看一下这种情况:

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 10;
  ctx.strokeStyle = "hotpink";
  ctx.moveTo(20, 30);
  ctx.lineTo(180, 30);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.moveTo(20, 70);
  ctx.lineTo(180, 70);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineWidth = 15;
  ctx.moveTo(20, 120);
  ctx.lineTo(180, 120);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 10;
  ctx.strokeStyle = "hotpink";
  ctx.moveTo(20, 30);
  ctx.lineTo(180, 30);
  ctx.stroke();

  ctx.lineWidth = 5;
  ctx.moveTo(20, 70);
  ctx.lineTo(180, 70);
  ctx.stroke();

  ctx.lineWidth = 15;
  ctx.moveTo(20, 120);
  ctx.lineTo(180, 120);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

当我们删掉 ctx.beginPath(); 时,三条线变成了一样的线宽,怎么回事呢?那是因为在同一个路径中,Canvas 会使用最后一次定义的样式,也就是说想使用不同的样式时,需要以开始一条新路(ctx.beginPath)径来重新定义线条的样式属性。

lineCap 属性

lineCap 属性用于显示线条开始处与结尾处线帽样式;

ctx.lineCap = "Butt";
// 取值为: 
// "Butt": 默认值,无线帽
// "Round": 圆形线帽
// "Square": 方形线帽

对应的属性值大小写都可以,我们来用实际对比代码来看看这几个属性值有啥区别:

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 1;
  ctx.strokeStyle = "#cccccc";
  ctx.moveTo(10, 0);
  ctx.lineTo(10, 150);
  ctx.moveTo(180, 0);
  ctx.lineTo(180, 150);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineWidth = 20;
  ctx.lineCap = "butt";
  ctx.strokeStyle = "hotpink";
  ctx.moveTo(10, 30);
  ctx.lineTo(180, 30);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineCap = "round";
  ctx.moveTo(10, 70);
  ctx.lineTo(180, 70);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineCap = "square";
  ctx.moveTo(10, 120);
  ctx.lineTo(180, 120);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

我们可以从图片与代码中看到,"round" 和 "square" 的长度比 "butt" 更长,要长多少?从代码中我们能看到,长一个 lineWidth 的长度,两头平分,总结一下:有线帽的比没线帽的长一个线宽的长度

lineJoin 属性

在 Canvas 中,lineJoin 属性定义两个线条交接处的样式。

ctx.lineJoin = "miter";
// 取值为: 
// "miter": 默认值,尖角
// "round": 圆角
// "bevel": 斜角

我们具体来看看 lineJoin 属性分别有什么区别:

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 20;
  ctx.strokeStyle = "hotpink";

  ctx.beginPath();
  ctx.lineJoin = "miter";
  ctx.moveTo(10, 20);
  ctx.lineTo(180, 20);
  ctx.lineTo(180, 40);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineJoin = "round";
  ctx.moveTo(10, 70);
  ctx.lineTo(180, 70);
  ctx.lineTo(180, 100);
  ctx.stroke();

  ctx.beginPath();
  ctx.lineJoin = "bevel";
  ctx.moveTo(10, 120);
  ctx.lineTo(180, 120);
  ctx.lineTo(180, 140);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

从上图及代码中我们可以总结出三者的区别:

  • mitter: 线条直接延伸交于点,为默认值;
  • round:交接处是一个圆角,圆角所在圆直径等于线宽;
  • bevel:交接处是一个斜角,斜角所在正方形的对角线长等于线宽。

setLineDash() 方法

在 Canvas 中,用setLineDash() 方法来设置线条虚实样式。

ctx.setLineDash(array);
// array 是一个数组组合

我们来看看具体怎么使用:

<template>
  <canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>
</template>

<script setup>
import {ref, onMounted} from "vue";
const cnv = ref();

const drawLine = () => {
  const ctx = cnv.value.getContext('2d');

  ctx.lineWidth = 2;
  ctx.strokeStyle = "hotpink";

  ctx.beginPath();
  ctx.moveTo(10, 20);
  ctx.lineTo(180, 20);
  ctx.setLineDash([2, 2]);
  ctx.stroke();

  ctx.beginPath();
  ctx.moveTo(10, 60);
  ctx.lineTo(180, 60);
  ctx.setLineDash([5, 5]);
  ctx.stroke();

  ctx.beginPath();
  ctx.moveTo(10, 80);
  ctx.lineTo(180, 80);
  ctx.setLineDash([10, 5]);
  ctx.stroke();

  ctx.beginPath();
  ctx.moveTo(10, 120);
  ctx.lineTo(180, 120);
  ctx.setLineDash([20, 5, 5, 5]);
  ctx.stroke();
}

onMounted(() => {
  drawLine();
});
</script>

我就不信,你不知道这些 Canvas 线条属性

从上面的图我们可以总结出参数的规则:

  • setLineDash() 方法接受一个整数数组;
  • 数组索引偶数为实线长度,奇数为虚线间隔距离;
  • 如果设置虚线绘制,即使使用 beginPath()方法也不能重置绘制的线为实线,需手动设置参数为[] 或 [num, 0]。

总结

本节内容很简单,主要就是针对线条的样式的设定,样式的设定给单调的线条有增多各种展示与应用的可能性。

转载自:https://juejin.cn/post/7275176987357855755
评论
请登录