Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

canvas-前端的纸和笔 #1

Open
dk-plus opened this issue Apr 17, 2022 · 0 comments
Open

canvas-前端的纸和笔 #1

dk-plus opened this issue Apr 17, 2022 · 0 comments

Comments

@dk-plus
Copy link
Owner

dk-plus commented Apr 17, 2022

在一切谎言中,艺术是最真实的。

——福楼拜

先说我小时候的故事

四年级的时候,我得到了人生的第一台电脑——用CRT显示器的老古董,老表不要的送的(语言艺术

什么是CRT(阴极射线管)显示器,与液晶显示器的区别- 好文部- 作文范文,高中小学生字数作文,知识百科

拿到电脑后的我心情澎湃,想用它去画《猛兽侠》的黑猩猩队长,马上请教老表能不能画,怎么画(广西表妹《表哥我出来了哦》

超级帅气的猩猩队长!永远的黑猩猩!

他说当然能画!然后给我打开这个软件

WINDOWS系列工具--画图详细教程_多特软件

一顿操作后,我发现拿鼠标根本画不出黑猩猩队长,甚至画个圆都画不稳,最后我就放弃了。以至于后面很多年都没接触过电子绘画。

(理论上是能画出来的,毕竟位图都是像素,就像国足也存在理论上出线的可能)

直到2019年我大学毕业,刷起了ins,发现很多国外的画师,打开了新世界(别骂了,真的村通网

然后买了个数位板,接着顺理成章的成为了自由画师继续吃灰(这才是

到这里故事就讲完了,大家可以关掉页面了我们顺着windows画图开始进入正题——canvas。

canvas和windows画图

这两个东西非常像,概括起来就是:「画图」是用鼠标画,canvas是用代码画。

但「画图」的本质也是用代码画,只是你用鼠标和电脑交互,执行了对应的代码。

为什么拿「画图」来对比,不拿PS,因为它足够简单,很多功能都能一一对应。

canvas是纸

浏览器有个<canvas>标签,这个标签有两个属性,widthheight,就像纸有尺寸一样。

下面就是尺寸为300*300px的纸

<canvas id="canvas" width="300" height="300"></canvas>

打开「画图」,新建尺寸300*300,一样的。

canvas.context是笔盒

画画要用到哪些工具?铅笔、尺规、上色笔、橡皮擦,这些工具被集合到一个叫context的地方,你可以把它看做笔盒。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

对标画图,就是左侧的工具栏。

笔盒里有什么

现实中你能想象到的尺规,勾线笔,填色笔,橡皮擦它都有,计算机图像处理范畴的线性变化、混合模式它也有,我不打算做API搬运工,只想简单阐述一下。

勾线笔和填色笔

有了纸,我们还必须有笔才能写写画画。

笔分勾线笔和填色笔,前者用于勾勒轮廓,后者用于填充颜色至轮廓内。

  1. 默认勾线笔在「画图」中对应「铅笔」
  2. 填色笔对应「油漆桶」
  3. 「刷子」是线条较粗的勾线笔
  4. 「喷枪」是特殊勾线笔,也许我后面会出一篇专门的画笔制作记录
  5. 勾线和填色前,可以先「选取颜色」

至此,你应该能想象到哪些API对应上面的概念

ctx.stroke(); // 勾线
ctx.fill(); // 填色
ctx.strokeStyle = "white"; // 选取勾线笔颜色
ctx.fillStyle = "white"; // 选取填色笔颜色
ctx.lineWidth = 1; // 线条粗细

橡皮擦

有铅笔的地方就会有橡皮擦,这里所谓的橡皮擦就是清除矩形

ctx.clearRect(45, 45, 60, 60);

起笔、行笔、收笔

我们知道用勾线笔和填色笔能画出东西,也要知道画的步骤。

起笔、行笔、收笔,书法大家的必学之路! - 15练字网

我们拿书法的起笔、行笔、收笔来阐述以下步骤。

ctx.beginPath(); // 起笔
// 行笔
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath(); // 收笔

思考一下,如果写下一笔前,没有起笔这一步,写出来的字会怎样?

会连在一起是吧,就像楷书转行书一样。

image-20220403171810715

对标「画图」,就是按下鼠标,按住拖动鼠标,松开鼠标。

尺规

知道了画画的步骤,想要画出具体的形状,还需要借助尺规。

直线、三角形、圆、矩形、多边形、贝塞尔曲线都在这个尺规内,对应「画图」工具栏中底部的形状部分。

∵两点成线

∴直线只要两个点

ctx.moveTo(75, 50);
ctx.lineTo(100, 75);

∵三点成面

∴三个以上的点相互连接成一个多边形

ctx.moveTo(75, 50);
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);

圆形由圆弧组成,具体参数含义可以查看API,圆无非就是确定圆心、半径、弧度0~2π

ctx.arc(60, 65, 5, 0, Math.PI * 2, true)

矩形只要确定左上角坐标、宽、高即可

ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);

至于贝塞尔曲线,挖个坑,后面展开讲

quadraticCurveTo(cp1x, cp1y, x, y);
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

局部换笔

以前上学的时候,上课会用到黑笔、红笔、荧光笔做笔记,默认是用黑笔,遇到特殊的地方会用红笔或者荧光笔标记,标记后重新切回黑笔,这种局部换笔的操作在canvas里也有。

// 默认用黑笔
...
ctx.save();
// 切换成红笔
ctx.strokeStyle = 'red';
...
ctx.restore();
// 再回来黑笔
...

在「画图」中,就是切换工具,没啥好说的。

其他

还有很多API,我并不打算在这个基础篇中展开讲

  1. 变形,也就是平移、缩放、旋转、剪切,可以另开一篇线性代数相关
  2. 混合模式,就是你们在PS界面图层那块看到的,包括正片叠底效果,也可以另开一篇(这是今天挖的第几个坑来着

数据可视化

图形,本质上是数据的可视化显示。

我们要做的,是写一个通用逻辑,设计一个通用数据结构,然后用逻辑把数据变成图形。

我们简单设计一个数据结构吧,比如形状,它可以是矩形、三角形、圆等,相应的拥有自己独特的参数,比如圆的圆心、半径,三角形的三个顶点。

interface Shape {
	type: 'rect' | 'triangle' | 'circle' | 'line' | 'point';
	params: any;
}

再来写个通用逻辑,先判断Shape类型,调用相应的方法渲染图形

function renderShape(shape: Shape) {
  ctx.save();
  ctx.beginPath();
  
	if (shape.type === 'rect') {
    const {x, y, width, height} = shape.params
		ctx.strokeRect(x, y, width, height);
	}
	...
  
  ctx.stroke();
  ctx.closePath();
  ctx.restore();
}

最后,我们拿到一堆这样的数据,遍历它们,调用通用逻辑渲染即可

const data = [
	{
		type: 'rect',
		params: {
			x: 10,
			y: 10,
			width: 100,
			height: 100,
		},
	},
	{
		type: 'triangle',
		params: {
			p1: { x: 100, y: 150 },
			p2: { x: 200, y: 250 },
			p3: { x: 100, y: 250 },
		},
		...
	}
]

for(let s of data) {
  renderShape(s)
}

最终结果如图所示,这就是所谓的数据可视化(看起来很low,但它确实是

需要示例的朋友可以复制查看:https://codepen.io/dkplus/pen/gOoooBb?editors=0010

image-20220404235832830

つづく

以上,就是本篇的全部内容,我们认识了前端的纸和笔,对标了经典windows软件「画图」,也看到了如何使用通用数据结构和通用逻辑进行静态绘制。后面的篇章就会往动画的方向去写了。

最后就是引流时间了:欢迎关注公众号dkplus,一起探讨图像背后的各种技术细节!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant