[p5.js作品教程]Reverse Phi Illusion视错觉实现

效果展示:传送门

一、实现步骤

具体详解可见B站up主设计师深海的《一动不动》。这里我就简单叙述一下。

简单来说,分为三步:

  1. 绘制三个一模一样的图像,并排排列;

  2. 将三个图像按照左中右的顺序,实现颜色的依次变化,如下所示。
    灰度值变化

  3. 将三个图像按照中左右的顺序依次叠加,其中左边图像向左偏离中间图像若干像素,右边图像向右偏离中间图像若干像素。如此,便可实现视错觉现象。如下所示。
    视错觉实现

二、代码实现

1. 基本框架搭建

var backColor =127;

function setup() {
    createCanvas(320,320);
    background(backColor);
}

function draw() {
    translate(width/2,height/2);
    background(backColor);
}

2. 创建Graphics类

综上,我们可以知道,在Graphics类中有以下几种属性:

  • 中心坐标
  • 颜色
  • 镂空圆形的大小(指具有边界但没有填充的圆形)
  • 等边三角形长度

在Graphics类中有以下几种方法:

  • 绘制图形
  • 改变颜色

故Graphics类的创建如下所示。

function Graphics(tempX,tempY) {
    // 中心坐标
    this.x = tempX;
    this.y = tempY;

	// 三角形中心到各个顶点的边长
    this.l = 50;
    
    // 圆形半径大小
    this.r = 100;
    
    // 设置颜色,范围(0~255)
    this.black = 255;
    
    // 绘制三角形,通过自建类来实现
    this.triangle = new Triangle(tempX,tempY,this.l);

    // 定义绘制图形方法
    this.display = function() {
        push();
        stroke(this.black);
        strokeWeight(50); // 设置圆形线条粗细
        fill(this.black,0); // 使圆形填充完全透明
        ellipse(this.x,this.y,this.r*2,this.r*2);
        pop();
        
        this.triangle.display(this.black);
    }

    // 定义改变颜色方法
    this.changeColor = function(tempC){
    	this.black = tempC;
    }
}

// 自建圆角三角形类
function Triangle(tempX,tempY,tempL) {
    this.x = tempX;
    this.y = tempY;
    this.l = tempL;

    this.display = function(tempC){
        push();
        
        fill(tempC);
        strokeJoin(ROUND); // 使连接处圆滑过渡
        strokeWeight(10);
        stroke(tempC);
        
        // 用自定义形状绘制等边圆角三角形
        beginShape();
        vertex(this.x,this.y-this.l);
        vertex(this.x+sqrt(3)*this.l/2,this.y+this.l/2);
        vertex(this.x-sqrt(3)*this.l/2,this.y+this.l/2);
        endShape(CLOSE);
        
        pop();
    }
}

其中等边三角形的三个点坐标计算如下所示。由于p5js的y轴正方向与正常坐标系的y轴正方向相反,故计算时需要注意一下。
三角形顶点计算
Graphics类的声明如下所示。我以第二个图形为中心图形,其余两个图形分别以它作为中心左右偏移三个像素。

var graphics = [];
function setup() {
	...

	// 创建组合图形
    graphics[0] = new Graphics(0,-3);
    graphics[1] = new Graphics(0,0);
    graphics[2] = new Graphics(0,3);
}  

3. 设置灰度值改变机制

​我以累计帧数对某个数的取模值作为变量与正弦函数一起来实现灰度值的循环变化。其中有两个map映射,依次为

  • map(count,0,changeRate-1,0,TWO_PI)+0/0.25*PI/0.5*PI

  • map(sin(x),-1,1,0,255)

​其中第一个映射是将累计帧数取模后的值从 [0,changeRate-1] => [0,2 π \pi π],以实现正弦函数的周期变化,后面加的0/0.25*PI/0.5*PI是为了实现三个图形在同一时间的不同值。第二个map映射是将正弦值从[-1,1]=>[0,255]以实现正弦值与灰度值的转换。

​ 此后,将组合图形按照中左右次序依次显示便可实现视错觉效果。

​ 部分代码如下所示。

function draw() {
    ...
    var changeRate = 20;
    var count = frameCount % changeRate;
    var angle = PI / 2;

    push();
    angleMode(RADIANS);
    // 旋转某个角度
    rotate(angle);

    var c = map(sin(map(count,0,changeRate-1,0,TWO_PI)+0.5*PI),-1,1,0,255);
    graphics[2].changeColor(c);
    graphics[2].display();

    c = map(sin(map(count,0,changeRate-1,0,TWO_PI)),-1,1,0,255);
    graphics[0].changeColor(c);
    graphics[0].display();

    c = map(sin(map(count,0,changeRate-1,0,TWO_PI)+1/2*0.5*PI),-1,1,0,255);
    graphics[1].changeColor(c);
    graphics[1].display();

    pop();
}

4. 简单的改进

​我们已经实现了在某个方向的视错觉现象,接着我们可以将其改变为任一方向。故我们通过鼠标的位置来控制视错觉现象的“运动方向”。

​首先,定义一个计算某个向量与y轴的夹角函数。因为初始时刻,三角形的朝向为向上,故其方向向量为[0,-1] (p5js中以向下为正方向)。定义代码如下所示。由于 a r c c o s ( x ) ∈ [ 0 , π ] arccos(x)\in[0,\pi] arccos(x)[0,π],故需要对计算出来的角度进行进一步的处理,使 a r c c o s ( x ) ∈ [ − π , π ] arccos(x)\in[-\pi,\pi] arccos(x)[π,π]

function calAngle(x,y) {
    var angle = acos(y/sqrt(x*x+y*y));

    if (x < 0){
        angle = -angle;
    }else {
        angle = angle;
    }
    return angle;
}

​ 在draw代码中,将原先的angle声明与定义代码替换成以下代码,便可实现图像向着鼠标的位置“运动”。实现效果如B站视频[processing]Reverse Phi Illusion视错觉现象实现所示。

var angle = calAngle(mouseX-width/2,height/2-mouseY);
// var angle = PI / 2;

想要完整项目源码的小伙伴,可以关注公众号【p5js艺术小站】,后台回复 “视错觉” 来获取呀~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hzxwonder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值