手绘与码绘静态对比
前言
在互动媒体的课程上,我了解了P5.js这项技术,并且学会了运用它进行简单的网页绘图。可能有很多人认为,绘画是一种艺术形式,必须要拿起画笔才能产生好的作品,而代码听起来和绘画毫无关系,代码写出来的图案又怎么能吸引人呢?所以现在我想对手绘和码绘产生的静态图片来进行对比,分析两者的优劣之处。
流程目录
手绘内容
因为接触P5也没有多久,第一次不打算尝试太复杂的图案,于是相应的手绘也比较简单,我就用水笔简单画了一个Q版小人。为了方便用代码画出她,我手绘时用的也只是一些多边形,椭圆等基本图形。
码绘内容
编写过程
首先我们来介绍P5.js的基本构架:setup和draw函数,setup函数用来生成画布,而draw函数则用来在画布上绘画。来看一段基础代码:
function setup() {
// put setup code here
createCanvas(640,480);
}
function draw() {
background(221,160,221);
}
效果:
这样我们就生成了一个长640,宽480的画布并给它赋予了颜色。
P5.js中可以根据RGB数值来给背景,线条,图形指定不同颜色,接下来对这一类代码的解释会放在码绘过程中。
在码绘最开始,我们要找到手绘小人身上比较直观的基本图形,即各种各样的多边形和不同的圆形,P5并没有直接生成多边形的代码,所以我们先来画圆,小人的身体由圆形(包括椭圆)组成的部分有脸部,衣服的袖子和双手。
P5自带的画圆函数是ellipse(x,y,r1,r2),x和y指定圆心坐标,r1和r2指定椭圆的长宽,绘制时注意先后顺序,后写的代码会覆盖前面的代码。
完成脸部和手之后,我们来考虑要如何画出头发和衣服那样的多边形,我在搜索一番之后发现P5可以绘制“自定义图形”,即根据指定点连接线段,代码如下:
fill(90,10,90);
beginShape();
vertex(270, 110);
vertex(290, 140);
vertex(315, 135);
vertex(310, 100);
endShape(CLOSE);
endShape(CLOSE)意味着它会帮你自动连接第一个和最后一个点,fill则指定了图形的填充颜色。
多次重复运用这个方法,我们就可以构造出小人的基本形状:
虽然有些图形锯齿看起来非常违和,也有自定义图形覆盖不到位的问题,但是基本上已经画出了小人的头发,腿部和衣物。
剩下的部分就是光环,眼睛和红晕等点缀部分,运用上面讲的椭圆画法和自定义图形就可以轻松实现啦。
顺带一提,光环部分可以用线条来代替图形:
stroke(255,250,165);
strokeWeight(3);
noFill();
这三行代码就可以指定一个没有填充,宽度为3且有颜色的线条样式。
最终结果
最终实现的小人已经成功还原了手绘图像, 相比黑白手绘还增添了很多色彩:
这里给出踏得网的代码链接,可以自己尝试修改:
http://wow.techbrood.com/fiddle/42530
手绘与码绘对比
经过这次尝试,我总结出了手绘和码绘的一些不同:
一.思路
编程作图时,首先要考虑图像能否用几个固定的形状和一些自定义图形表现出来,再决定是否画某样东西,绘制几何形状较多的图画比较容易。手绘作图时,可以完全按照自己的想法绘画而不用担心形状难以控制。
二.技术
手绘作图需要基本的绘画天赋和一些后天的练习,才能画出自己想要的东西,包括形体的描绘和上色方法;而编程绘图上手比较简单,不需要太多艺术方面的技术,代码可以创造出各种各样的形状和颜色,但代码的前后关系和图形的运用也有一定的技术需求。
三.创作体验
编程作图在颜色使用方面非常便利,直线和圆的绘制比手绘要简单很多,但是画图时很难一次性估算出合适的坐标,需要反复尝试,比较繁琐,绘制复杂图像时,代码过多,如果不好好利用注释很容易找不到后来所需要的坐标,图形的前后覆盖也会无法实现。手绘作图需要控制线条,但是绘制的形状不受限制,总体来说效率要比编程高,但是上色又需要额外考虑。
四.创作偏好
接触绘画比较早且经过练习的人会喜欢手绘多过编程,但对没有绘画基础的人来说,编程作画会成为很有趣的体验。创作手绘时想象力会得到充分展示,图像大多丰富多彩且有个性,而编程绘画更有几何感,所有绘画使用的基本图形大多相似。
完整代码
这里给出Q版小人的完整js代码:
function setup() {
// put setup code here
createCanvas(640,480);
angleMode(DEGREES);
}
function draw() {
background(221,160,221);
strokeWeight(0);
//呆毛
fill(208,32,144);
beginShape();
vertex(280, 100);
vertex(240, 120);
vertex(270, 130);
endShape(CLOSE);
//腿
fill(255,245,238);
beginShape();
vertex(340, 200);
vertex(230,