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

线条样式

前言

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

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

lineWidth 属性

js 复制代码
ctx.lineWidth = 整数;

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

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

js 复制代码
<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>

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

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

js 复制代码
<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>
js 复制代码
<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>

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

lineCap 属性

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

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

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

js 复制代码
<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>

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

lineJoin 属性

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

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

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

js 复制代码
<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>

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

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

setLineDash() 方法

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

js 复制代码
ctx.setLineDash(array);
// array 是一个数组组合

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

js 复制代码
<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>

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

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

总结

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

相关推荐
独泪了无痕6 小时前
Vue调试神器:Vue DevTools使用指南
vue.js·前端工程化
Moment7 小时前
Vibe Coding 时代,到底该选什么样的工具来提升效率❓❓❓
前端·后端·github
IT_陈寒8 小时前
SpringBoot性能飙升200%?这5个隐藏配置你必须知道!
前端·人工智能·后端
小时前端9 小时前
React性能优化的完整方法论,附赠大厂面试通关技巧
前端·react.js
Nicko9 小时前
Jetpack Compose BOM 2026.02.01 解读与升级指南
前端
小蜜蜂dry10 小时前
nestjs学习 - 控制器、提供者、模块
前端·node.js·nestjs
优秀稳妥的JiaJi10 小时前
基于腾讯地图实现电子围栏绘制与校验
前端·vue.js·前端框架
前端开发呀10 小时前
从 qiankun(乾坤) 迁移到 Module Federation(模块联邦),对MF只能说相见恨晚!
前端
没想好d10 小时前
通用管理后台组件库-10-表单组件
前端
好雨知时节t10 小时前
Pinia中defineStore的使用方法
vue.js