p5.js:基于圆形和矩形面板的简单绘画系统

摘要
绘画的元素中,采用码绘对绘画材料与交互方式进行改进十分方便,比如可以加上动态效果,有规律的形状,绘画的基本元素不再使用基本像素等

设计思路
参考老师的案例,采用圆形面板来当绘制的panel,矩形面板的功能我也实现了一个自己的版本。采用上一次说的面向对象的方法,能够方便地改变每个元素的坐标,颜色等信息。

tips:
由于想象力有限,所以只能做出仅有的几个功能。

首先是定义一个绘制圆形的类:
它包括以下几个属性:

  1. 创建时的坐标
  2. 当前坐标
  3. 半径
  4. 旋转角度
  5. 旋转角度增加量
  6. 是否旋转
  7. 是否平移
  8. 是否被画笔画过

如果被画过,那么它的颜色就由笔刷面板来控制,代码:

function drawFcn(x,y,theta,angle,radius,rot,trans,painted)
{
//坐标
this.x=x;
this.y=y;
//初始坐标
this.initx=x;
this.inity=y;
//旋转角度
this.theta=theta;
//旋转角度增加量
this.angle=angle;
//半径
this.radius=radius;
//是否旋转
this.rotate=rot;
//是否平移
this.trans=trans;
//是否被画过
this.painted=painted;

this.draw_roundness=function()
{
  if(!this.painted)//如果没有
{
fill(p_RGB_R, p_RGB_G, p_RGB_B, opacity);//使用本身颜色
}
else if(this.painted)
{
fill(b_RGB_R, b_RGB_G, b_RGB_B,opacity);//使用笔刷颜色

}
push();
rotate(this.theta);
if(this.trans)//是否移动
{
  if(this.x<=this.initx+200&&this.x>=0)
  {
    if(!is_contrary)
  {
    this.x-=c_tran_speed;
  }
  else
  {
    this.x+=c_tran_speed;
  }
}
}
if(this.rotate)//是否旋转
{
  this.theta+=this.angle;
}
strokeWeight(c_stroke);

ellipse(this.x,this.y,this.radius,this.radius);
pop();

}
}

定义数组来保存对象并且随着Gui面板变量更新而更新(zoom是整体圆形的半径,radius是单个圆形的半径):

//更新、初始化圆形
function InitRoundnessList()
{ 
  var r = radius * zoom;//半径
  if(RoundList.length>seeds)
  {
    RoundList.length=seeds;
  }
  else if(RoundList.length<seeds)
  {
  for(var i = RoundList.length-1; i <seeds ; i++) 
  {
    RoundList[i]=new drawFcn(sqrt(i + 0.5) * zoom,0,0,0,r,false,false,false);
  }
  }

if(RoundList[0].initx!=sqrt(0.5) * zoom)
{
for(var i = 0; i <RoundList.length ; i++) 
  {
    RoundList[i].x=sqrt(i+0.5) * zoom;
  }
}

if(RoundList[0].radius!=r)
{
for(var i = 0; i <RoundList.length ; i++) 
  {
    RoundList[i].radius=r;
  }
}
}

绘制圆形:(每个圆形绘制前都旋转一定的角度,平移指定距离,角度可以由面板控制)

push();
for(var i = 0; i < RoundList.length; i++) {
  push();
  translate(center_x, center_y);
  rotate(i*angle);   
  RoundList[i].draw_roundness();
  pop();
  }
  pop();

这样就绘制出基础的panel:
在这里插入图片描述

定义笔刷:

//brush
var brush_type=['color','rotate','translate','eraser','rotate_down','translate_down'];
var brush_radius=30;//笔刷半径
var brush_radiusMax=50;
var b_RGB_R=255;
var b_RGB_G=255;
var b_RGB_B=255;
var BrRotatePower=1;旋转笔刷的旋转速度
var BrRotatePowerMax=3;
var BrRotatePowerStep=0.1;

这里定义了Gui中几种笔刷的类型和笔刷的颜色。

给panel上色,实际上就是把鼠标划过的圆形对应的painted设为true:

if('roundness'==panel_type)
{
  ellipse(mouseX-center_x,mouseY-center_y,brush_radius,brush_radius);
	for(var i=0;i<seeds;i++)
{
var pos=createVector(center_x+cos((i)*angle+RoundList[i].theta)*(RoundList[i].x),center_y+sin((i)*angle+RoundList[i].theta)*(RoundList[i].x));
var position=createVector(mouseX,mouseY);
var su=p5.Vector.sub(pos,position);
var length=su.mag();
if(length<=brush_radius)
{
  RoundList[i].painted=true;
}
}
}

绘制过的地方就可以用brush_gui来控制颜色

在这里插入图片描述

然后由roundness_gui控制参数可以达到其他效果:

在这里插入图片描述
让基础圆形向着远离圆心或者是向着圆心平移
因为旋转已经在类中定义好,所以代码和上色差不多:

if('roundness'==panel_type)
{
  ellipse(mouseX-center_x,mouseY-center_y,brush_radius,brush_radius);
for(var i=0;i<seeds;i++)
{
var pos=createVector(center_x+cos((i)*angle+RoundList[i].theta)*(RoundList[i].x),center_y+sin((i)*angle+RoundList[i].theta)*(RoundList[i].x));
var position=createVector(mouseX,mouseY);
var su=p5.Vector.sub(pos,position);
var length=su.mag();
if(length<=brush_radius)
{
  RoundList[i].trans=true;
}
}
}

效果:
在这里插入图片描述
围绕中心旋转:
在这里插入图片描述

这些基本上就是圆形面板的效果。
接下来是矩形面板:
同样的,定义一个绘制矩形的类:

function squaresFcn(x,y,xsize,ysize)
{
//方块坐标
this.x=x;
this.y=y;
//初始中心坐标
this.initx=x;
this.inity=y;
//方块长宽
this.xsize=xsize;
this.ysize=ysize;
//旋转角度
this.theta=0;
//旋转角度增加量
this.angle=0;
this.stroker = 0;
this.strokeg = 0;
this.strokeb = 0; 
this.stroke=1;
//颜色
this.r = random() * 255;
this.g = random() * 255;
this.b = random() * 255;
//确定是否旋转
this.rot=false;
//是否被上色
this.painted=false;
//是否平移
this.trans=false;
//画普通的方块
this.draw_square=function()
{
  push();
  if(!this.painted)
  {
  fill(this.r, this.g, this.b,opacity);
  }
else if(this.painted)
{
  fill(b_RGB_R, b_RGB_G, b_RGB_B,opacity);
}
if(this.trans)
{
if(s_is_tran_x)
{
if(this.x<=this.initx+s_tran_x&&this.x>=this.initx-s_tran_x)
{
  if(s_is_contrary)
  {
    this.x-=tran_speed;
  }
  else
  {
    this.x+=tran_speed;
  }
}
}
if(s_is_tran_y)
{
  if(this.y<=this.inity+s_tran_y&&this.y>=this.inity-s_tran_y)
  {
    if(s_is_contrary)
    {
      this.y-=tran_speed;
    }
    else
    {
      this.y+=tran_speed;
    }
  }
}
}
translate(s_center_x,s_center_y);
rotate(s_angle);
strokeWeight(stroke_weight);
stroke(stroke_r,stroke_g,stroke_b);
rect(this.x,this.y,this.xsize,this.ysize);
pop();
}
//画旋转的方块
this.draw_rotate=function()
{
if(this.trans){
  if(s_is_tran_x)
{
  if(this.x<=this.initx+s_tran_x&&this.x>=this.initx-s_tran_x)
  {
    if(s_is_contrary)
    {
      this.x-=tran_speed;
    }
    else
    {
      this.x+=tran_speed;
    }
  }
}
if(s_is_tran_y)
{
  if(this.y<=this.inity+s_tran_y&&this.y>=this.inity-s_tran_y)
  {   if(s_is_contrary)
      {
        this.y-=tran_speed;
      }
      else
      {
        this.y+=tran_speed;
      }
  }
}
  }
push();
translate(s_center_x,s_center_y);
translate(this.x,this.y);
rotate(this.theta);
this.theta+=BrRotatePower;
fill(s_RGB_R, s_RGB_G, s_RGB_B,opacity);
if(!this.painted)
{
  fill(this.r,this.g,this.b,opacity);
  
}
strokeWeight(stroke_weight);
stroke(stroke_r,stroke_g,stroke_b);
rect(0,0,this.xsize,this.ysize);
pop();
}

}

基础颜色设置成随机色,当单个矩形被画过时,同样的会被bursh面板操控颜色:
在这里插入图片描述
如果再被旋转笔刷刷过,就可以通过square面板控制颜色:
在这里插入图片描述
对应的,同样有平移的笔刷:
在这里插入图片描述

总结
这两种面板基本上是以一种类似像素画风的方法来绘制图片,不同的面板可以根据不同角度画出不一样的效果,采用不同的绘图元素,用动态的效果展示。

载体
采用的绘画材料和普通的护花方式不一样,可以自由控制动态效果等。

技法和理念
绘画,目的的是让看到的人获得一定的感受,这个绘画系统设计的就是基于有规律的基本面板形状,来表现出一种特别的感觉。
而手绘等传统的绘画方式是创作者基于自身的能力,随意发挥,而这个绘画系统目的就是让人能简单表现出一种想要的效果。

局限性
只能基于给定的基本形状进行扩展,不能像传统的基本像素组成的图案随意组合。

参考链接

0.1 用代码画画——搞艺术的学编程有啥用?
https://blog.csdn.net/magicbrushlv/article/details/77922119
1.1 开始第一幅“码绘”——以编程作画的基本方法
https://blog.csdn.net/magicbrushlv/article/details/77840565
2. 以编程的思想来理解绘画—— (一)用”一笔画“表现“过程美”
https://blog.csdn.net/magicbrushlv/article/details/82634189

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值