p5.js码绘:未来风格/科技感的线库


前言

本文记载的是自己用p5.js绘制一些有科技感的线条/图形的过程


一、基本元素选定

1、颜色:

这里我选用了三种颜色作为基调色,分别是:

  • 青色 RBG(0,255,255).
  • 白色 RGB(255,255,255).
  • 黑色 RGB(0,0,0).

黑色作为背景色,青色和白色绘制线条,效果如下图:
在这里插入图片描述

2、元素:

为了表现科技感我查阅了一些相关的资料,也找了很多图片,这里放几张。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不难发现科技感的表现主要是从色调(多以蓝色、暗蓝色为主)、透明度(半透明)、几何元素(多为有棱角的几何形状)这三个方面来表现。从这些图片中提取一些共有的元素作为创作素材:

  • 网格/矩形
  • 粒子链
  • 电路图
  • 蜂巢结构

二、绘制线条

1.matrix1Line

函数原型: line_matrix1_0126(x0,y0,x1,y1,randness,res)
参数说明: x0,y0为线条的起点坐标,x1为终点横坐标,y1为线宽,randness为随机数限制因子,res为分段数(值越大线条越复杂)。该线条只能放置在水平方向。

function line_matrix1_0126(x0,y0,x1,y1,randness,res)
{
  var xp = x0;
  var yp = y0;
  for(var i=1;i<res;i++)
  {
    var t = i/res;
    var xt = lerpAB(x0,x1,t);
    var yt = lerpAB(y0,y1,t);
    var biasX = random(-randness,randness);
    var biasY = random(-randness,randness);
    var x = xt + biasX;
    var y = yt + biasY;
    let lineWeight=random(2,3);
    strokeWeight(lineWeight);
    line(xp,yp,x,yp);
    line(x,yp,x,y);
    stroke(0,255,255);
    line(xp,yp,xp,y);
    line(xp,y,x,y);
    stroke(255);
    xp = x;
    yp = y;
  }
}

静态效果
在这里插入图片描述
动态效果
在这里插入图片描述

2.matrix2Line

函数原型: line_matrix2_0126(x0,y0,x1,y1,radius,Freq,res)
参数说明:x0,y0为线条的起始坐标,x1,y1为线条的终点坐标,radius为线条宽度的一半,而Freq和res都与线条的复杂程度以及形状相关。

function line_matrix2_0126(x0,y0,x1,y1,radius,Freq,res)
{
  var theta = 0;
  var xp = x0 + radius * cos(theta);
  var yp = y0 + radius * sin(theta);

  for(var i=1;i<res;i++)
  {
    var t = i/res;
    var xt = lerpAB(x0,x1,t);
    var yt = lerpAB(y0,y1,t);
    theta = t*Freq;
    var x = xt + radius * cos(theta);
    var y = yt + radius * sin(theta);
    let lineWeight=random(0,3);
    strokeWeight(lineWeight);
    line(xp,yp,x,yp);
    line(x,yp,x,y);
    stroke(0,240,240);
    line(xp,yp,xp,y);
    line(xp,y,x,y);
    stroke(255);
    xp = x;
    yp = y;
  }
}

静态效果:
在这里插入图片描述
动态效果(Fre为0-width之间的随机数):
在这里插入图片描述

3.circuitryLine

函数原型: line_circuitry_0126(x0,y0,x1,y1,Amp,Freq,res,Wid)
参数说明:x0,y0,x1,y1分别为线条的起始横纵坐标和终点横纵坐标,Amp、Freq为偏移量控制因子,res为分段数,这三者都与线条最终复杂情况有关,Wid为线条宽度的一半。

function line_circuitry_0126(x0,y0,x1,y1,Amp,Freq,res,Wid)
{
  var xp = x0 + map(noise(0*Freq),0,1,-1,1);
  var yp = y0 + map(noise(0*Freq+10000),0,1,-1,1);
  for(var i=1;i<res;i++)
  {
    var t = i/res;
    var xt = lerpAB(x0,x1,t);
    var yt = lerpAB(y0,y1,t);
    theta = t*Freq;
    var x = xt + Amp * map(noise(t*Freq),0,1,-1,1);
    var y = yt + Amp * map(noise(t*Freq+10000),0,1,-1,1);
    fill(255);
    stroke(255);
    line(xp,yp,xp,y);
    line(xp,y,x,y);
    line(xp,yp,x,yp);
    line(x,yp,x,y);
    rect(xp,yp,8,8);
    rect(x-5,y-5,5,5);
    let w_size=30;
    let h_size=random(Wid,2*Wid);
    rect(xp+3*w_size/2-6,yp-h_size/2+1,3,3);
    rect(xp+w_size/2+1,yp+h_size/2-6,3,3);
    noFill();
    rect(xp+w_size/2+1,yp-h_size/2+1,5,20);
    rect(xp+3*w_size/2-11,yp+h_size/2-6,10,5);
    stroke(0,255,255);
    rect(xp+w_size/2,yp-h_size/2,w_size,h_size);
    xp = x;
    yp = y;
  }
}

静态结果:
在这里插入图片描述
动态结果:
在这里插入图片描述
在这里插入图片描述

4.VspringLine

函数原型: line_Vspring_0126(x0,y0,x1,y1,res,Wid)
参数说明:x0,y0分别为线条的起点横纵坐标,x1为线条的终点横坐标,res为分段数,Wid为线宽的一半。该线条也只能放置在水平方向。

function line_Vspring_0126(x0,y0,x1,y1,res,Wid)
{
  strokeWeight(2);
  stroke(255);
  var xp=x0;
  var yp=y0;
  for(var i=1;i<res;i++)
  {
    var c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    var plenth=random(20,50);
    var wid=random(10,Wid);
    ellipse(xp,yp+wid,6,6);
    line(xp+3,yp+wid,xp+plenth,yp+wid);
    line(xp+plenth,yp+wid,xp+plenth+wid,yp);
    ellipse(xp,yp-wid,6,6);
    line(xp+3,yp-wid,xp+plenth,yp-wid);
    line(xp+plenth,yp-wid,xp+plenth+wid,yp);
    line(xp+plenth+wid,yp,xp+2*plenth+wid,yp);
    c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    line(xp+plenth+wid-2,yp-10,xp+2*plenth+wid+2,yp-10);
    line(xp+plenth+wid-2,yp+10,xp+2*plenth+wid+2,yp+10);
    c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    xp=xp+2*plenth+wid;
    line(xp,yp,xp+wid,yp+wid);
    ellipse(xp+wid+3,yp+wid,6,6);
    line(xp,yp,xp+wid,yp-wid);
    ellipse(xp+wid+3,yp-wid,6,6);
    xp=xp+wid+15;
    if(xp>x1){break;}
  }
}

静态效果:
在这里插入图片描述
动态效果:
在这里插入图片描述

5.beehiveLine

函数原型: line_beehive_0126(x0,y0,x1)
参数说明: x0,y0分别表示线条的起点坐标,x1表示线条终点的横坐标。同样该线条只能水平放置,垂直放置需稍做改动。

function line_beehive_0126(x0,y0,x1)
{
  strokeWeight(1);
  stroke(0,255,255); 
  let x=x0;
  let y=y0;
  let radius=20;
 
  for(x=x0;x<x1;x=x+3*radius)
  {
    var wid=random(1,3.5);
    strokeWeight(wid);
    noFill();
    var c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    beginShape();
    for(var i=0;i<7;i++)
    {
      vertex(x+radius*cos(i*PI/3),y+radius*sin(i*PI/3));
    }
    endShape(CLOSE);
    c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    beginShape();
    for(var i1=0;i1<7;i1++)
    {
      vertex(x+radius*cos(i1*PI/3)+3*radius/2,y+radius*sin(i1*PI/3)+radius*cos(60));
    }
    endShape(CLOSE);
    c1=random(0,2);
    if(c1>1){stroke(255);}
    else {stroke(0,255,255);}
    beginShape();
    for(var i2=0;i2<7;i2++)
    {
      vertex(x+radius*cos(i2*PI/3)+3*radius/2,y+radius*sin(i2*PI/3)-radius*cos(60));
    }
    endShape(CLOSE);
  }
}

静态效果:
在这里插入图片描述
动态效果:
在这里插入图片描述

6. particleChainLine

函数原型:line_particle_0126(x0,y0,x1,y1,Wid)
参数说明:x0,x1分别表示线条的起点和终点横坐标,y0表示线条的纵坐标中心,y1和Wid限制鼠标作用的范围

function line_particle_0126(x0,y0,x1,y1,Wid)
{
  let xp=round(random(0,x1));
  let yp=round(random(y0-Wid/4,y0+Wid/4));
  //let yp=950;
  if(mouseY<(y1-3*Wid)||mouseY>y1+(3*Wid))
  {system.origin=(createVector(xp,yp));}
  else{
    let addx=random(-Wid,Wid);
    let addy=random(-Wid,Wid);
    system.origin=(createVector(mouseX+addx,mouseY+addy));
  }
  //system.origin=(createVector(xp,yp));
  system.addParticle();
  system.run();
}

// A simple Particle class
let Particle = function(position) {
  this.acceleration = createVector(random(-0.02, 0.02), random(-0.01, 0.01));
  this.velocity = createVector(random(-1, 1), random(-1, 1));
  this.position = position.copy();
  this.lifespan = 255;
};
Particle.prototype.run = function() {
  this.update();
  this.display();
};

// Method to update position
Particle.prototype.update = function(){
  this.velocity.add(this.acceleration);
  //this.velocity = createVector(random(0, 5), random(0, 5));
  this.position.add(this.velocity);
  this.lifespan -= 1 ;
};
// Method to display
Particle.prototype.display = function() {
  stroke(255,255,255,this.lifespan);
  strokeWeight(2);
  fill(0,255,255,this.lifespan);
  ellipse(this.position.x, this.position.y, 12, 12);
};
// Is the particle still useful?
Particle.prototype.isDead = function(){
  return this.lifespan < 0;
};
let ParticleSystem = function(position) {
  this.origin = position.copy();
  this.particles = [];
};
ParticleSystem.prototype.addParticle = function() {
  this.particles.push(new Particle(this.origin));
};
ParticleSystem.prototype.run = function() {
  for (let i = this.particles.length-1; i >= 0; i--) {
    let p = this.particles[i];
    p.run();
     for(let j = this.particles.length-1; j >= 0; j--){
      let q = this.particles[j];
      const d = dist(p.position.x, p.position.y,q.position.x,q.position.y);
      if(d < 60&&d>30){
          let wid=random(0,1.5);
          strokeWeight(wid);
          stroke(0,255,255);
          line(p.position.x, p.position.y,q.position.x,q.position.y);
                    }
    }
    if (p.isDead()) {
      this.particles.splice(i, 1);
    }
  }
};

静态效果:
在这里插入图片描述
动态效果:
在这里插入图片描述

7.fallingstarLine

函数原型: line_particle_1_0126(x0, y0, d, angle, time)
参数说明: 其中x0,y0表示线条的终点坐标,d表示粒子运动的距离(需要结合translate使用),angle表示线条与水平线的夹角,time表示线条每次存在的时间。

function line_particle_1_0126(x0, y0, d, angle, time)
{
  push();
  let dx=d*cos(angle);
  let dy=d*sin(angle);
   //translate((0.1*dx*millis())%1000, (0.1*dy*millis())%1000);
  system_1.origin=(createVector(x0, y0));
  system_1.angle=angle;
  if (millis()/1000-system_1.staytime<time) {
    system_1.addParticle();
  }
  system_1.run();
  pop();
}

// A simple Particle class
let Particle_1 = function(position,angle) {
  
  this.d=random(-5,0);
  this.angle=angle;
  this.acceleration = createVector(0.01*this.d*random(cos(this.angle-PI/3),cos(this.angle+PI/3)), 0.01*this.d*random(sin(this.angle-PI/3),sin(this.angle+PI/3)));
  this.velocity=createVector(this.d*cos(this.angle),this.d*sin(this.angle));
  this.position = position.copy();
  this.lifespan = 255;
  this.size=random(1, 10);
  this.c1=random(0, 3);
};
Particle_1.prototype.run = function() {
  this.update();
  this.display();
};

// Method to update position
Particle_1.prototype.update = function() {
  //this.acceleration = createVector(random(-0.05, 0), random(-0.03, 0.03));
  this.velocity.add(this.acceleration);
  this.position.add(this.velocity);
  this.lifespan -= 1 ;
};

// Method to display
Particle_1.prototype.display = function() {
  c1=random(0, 3);
  if (this.c1>1&&this.c1<2) {
    fill(0, 255, 255, this.lifespan);
    stroke(0, 255, 255, this.lifespan);
  } else if (this.c1<=1) {
    fill(255, 255, 255, this.lifespan);
    stroke(255, 255, 255, this.lifespan);
  } else {
    fill(255, 255, 255, this.lifespan);
    stroke(0, 255, 255, this.lifespan);
  }

  ellipse(this.position.x, this.position.y, this.size, this.size);
};

// Is the particle still useful?
Particle_1.prototype.isDead = function() {
  return this.lifespan < 0;
};

let ParticleSystem_1 = function(position) {
  this.angle=0;
  this.origin = position.copy();
  this.particles = [];
  this.staytime=0;
  //this.lock=false;
};

ParticleSystem_1.prototype.addParticle = function() {
  this.particles.push(new Particle_1(this.origin,this.angle));
};

ParticleSystem_1.prototype.run = function() {
  if (millis()/1000-this.staytime>5) {
    this.staytime=millis()/1000;
  }
  for (let i = this.particles.length-1; i >= 0; i--) {
    let p = this.particles[i];
    p.run();
    if (p.isDead()) {
      this.particles.splice(i, 1);
    }
  }
};

静态效果:
在这里插入图片描述
动态效果:
在这里插入图片描述

三、总结

以上是当前实现的所有线条,在设计这些线条时加入了先前提到的带有科技感的元素图形,但是有些线条在设计之前没有考虑周全导致使用起来有摆放位置的限制,还需要继续改进。

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值