我就不信,你不知道这些 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]。

总结

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

相关推荐
gnip13 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart13 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.13 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu13 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss13 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师13 小时前
React面试题
前端·javascript·react.js
木兮xg13 小时前
react基础篇
前端·react.js·前端框架
ssshooter14 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘14 小时前
HTML--最简的二级菜单页面
前端·html
yume_sibai14 小时前
HTML HTML基础(4)
前端·html