雪梨小白的“码绘”起步——p5.js实现心形动态图形的绘制

2023-11-08

作为一个快乐的程序媛,尤其还是一个快乐的树莓程序媛,当然应该什么都会!所以这学期学院开了很多偏艺术类的课程让我们学习,然后就开始了互动媒体这门课的学习。这一次的作业要利用p5绘制动态图形,我自己还真的是活力满满的选了一个,emmmm……一点都不容易的,是真不把自己当小白,话不多说,就让我在ddl的这一天记录下雪梨小白的成果。(哈,我还是第一次在CSDN上发博客,搓手手)

平台选择以及p5.js库的配置

我是选择了WebStorm作为JavaScript语言的编译器(虽然我们老师课上墙裂推荐了Sublime Text,但我还是毅然决然了用了WebStorm,其实是主要原因是JetBrains公司出的IDE界面真的简洁美观、用户友好到飞起了啊有木有)

在这里插入图片描述
对我来说,配环境导入库这种事情,其实远比让我敲代码难,从我开始做作业到我完成,有一半的时间都折在了百度上搜索“如何在WebStorm中使用p5.js”,真实暴风哭泣,这时候我的愚蠢就显现出来了,后来在同学的帮助下终于解决了这个问题。

Step 1

新建一个Empty Project,在这个项目下,新建一个js文件(我的叫“SketchWork.js”,我们的码绘代码都要写在这里),再新建一个html用于js文件的呈现(就简单的叫index.html了)。
在这里插入图片描述

Step 2

这个时候要打开p5.js的官网啦(p5js.org),依次根据页面信息选择:下载——单一文件——CDN,把下图的链接Copy下来。
在这里插入图片描述

Step 3

向我们的html文件中标签组内加入几行代码,完成对js文件的引用。

<script src="SketchWork.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js" type="text/javascript"></script>

好啦,阶段性胜利,可以进入到正式的绘制阶段了。

动态图形的分析

让我们先来看看,我要临摹的这张图。
在这里插入图片描述
乍一看还挺好看,就是有点麻烦。

图像外观分析

看动态gif图,我有一个很好的办法,用Ps打开gif可以看到每一帧的图像,所以我就把90张图老老实实地看了一遍。
根据我的观察,这个图像外观上是6层正方体以不同数量整齐堆叠的,有前后两层,由两种颜色组成这些正方形。(如图更清晰)
在这里插入图片描述
所以这直接决定了我们选用box()函数来绘制这些小方块。

运动分析

我还真的是十分的相信我自己的能力,关键是,这个可爱的图像,它动就动了,它还是不匀速的运动,它要先加速转起来,然后再减速停下来。而最最重要的是,心形的每一层在转动的时候彼此与彼此的转速也不一样,按照我在Ps里一帧帧切换的观察来看,应该是这样的:
(我计了一下时,每次循环大致是2.5s完成)

层名 单词循环内圈数 单词循环内转过的角度
1st 4 rounds 8PI
2nd 4 rounds 8PI
3rd 3 rounds 6PI
4th 1.5 rounds 3PI
5th 1 rounds 2PI
6th 0.5 rounds PI

*除第六层为匀速运动外,其余各层都是匀角加速运动(我自己默认了这一点,因为如果算变速运动,我可能头就要掉了)
这个时候我就想起了我难忘的大学物理(真的是无语凝噎啊,过了这么久居然在码绘中用到了刚体的旋转),按照我的思路,每一层在绕轴旋转的时候,应该是都以这样的运动规律在进行:
在这里插入图片描述前一阶段先做角加速度为正的运动,后一阶段做角加速度为负的减速运动。两个阶段加起来的旋转角度与我们之前观察到的总旋转角度一致。
在这里插入图片描述
依照上述的公式就可以求解出每层的角加速度,并且列出我们的旋转代码啦。

代码实现

终于写完了分析,我一边写还一边在画分析图表,差点哭出声,那么我们就开始实现吧。
首先要先创建一块画布:

function setup() {
    createCanvas(400,400,WEBGL);
}

在p5中的setup()函数中,完成绘制之前的预设。
这里要敲黑板的是,因为我们用的是box()函数,这个函数在js的原有二维画布上是没有办法实现的,一定要在属性中加入WEBGL,要不然就什么都画不出来,还会报错:在这里插入图片描述
然后给画布一个背景颜色(写在draw()函数中):

function draw(){
    background(0);
}

然后在draw中写一个box()函数:
(在程序开头声明一下BoxSize作为盒子的大小)

function draw(){
    background(0);
    box(BoxSize);
}

在这里插入图片描述
画出来了一个小盒子,但它还是白色的,好像视图角度也不太对,让我们来修正一下。
在setup()中做一下颜色预设,把之前的两种颜色设定好,这里使用了color()函数。

function setup() {
    createCanvas(400,400,WEBGL);
    color1=color(252,68,106);
    color2=color(246,36,71);
}

再在draw()里面通过rotateX(),rotateY(),调整到我们需要的视角。
在这里插入图片描述
如我们所愿,只要绘制出了第一个,接下来每一层都可以通过translate()函数,改变位置再绘制,让我们来画一下中间这一层。(要注意的是box()的绘制以画布中央作为起始位置,translate()之后绘制的起始位置会随之改变,我在这里把画中间层的代码封装成了一个函数)

unction draw3rdline(){
    stroke(0);
    strokeWeight(linewidth);
    fill(color1);

    translate(0,0,1/2*gap);
    box(BoxSize);//Center Box

    //the right part
    translate(gap,0,0);
    box(BoxSize);

    translate(gap,0,0);
    box(BoxSize);

    translate(gap,0,0);
    box(BoxSize);

    //backside line
    translate(0,0,-gap);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    translate(-gap,0,0);
    box(BoxSize);

    //back to frontside
    translate(0,0,gap);
    box(BoxSize);

    translate(gap,0,0);
    box(BoxSize);

    translate(gap,0,0);
    box(BoxSize);
}

然后就是下面这个样子:
在这里插入图片描述
让我们努努力把别的层也写出来,需要注意的是需要在相邻层切换一下颜色(代码量较多,我就不全部贴上来了)
画完之后的效果图:
在这里插入图片描述
看起来就像成功了一样…
但我们还有最关键的地方需要处理,就是通过我们刚才公式的推导实现不同层之间加速减速旋转的效果,针对不同层设立变量,写出旋转公式,得到变化的旋转角度,这里要说明的是,为了使得各层旋转独立起来,我们把每一次变换绘制放进push(),pop()函数之间,确保每一层做的是独立的旋转运动。

var BoxSize=26;//盒子的大小
var gap=BoxSize+6;//下一个盒子绘制点的间隔
var linewidth=2;//盒子边框线宽
var color1;
var color2;

var t;//变化的时间
var tset;//每次循环的时间

//每一层的角加速度、角速度、角度
var agularvelocity1stmax;//最大角速度
var angularacceleration1st;//角加速度
var theta1st;//角度
var agularvelocity2ndmax;
var angularacceleration2nd;
var theta2nd;
var agularvelocity3rdmax;
var angularacceleration3rd;
var theta3rd;
var agularvelocity4thmax;
var angularacceleration4th;
var theta4th;
var agularvelocity5thmax;
var angularacceleration5th;
var theta5th;

(上面有些变量刚刚忘了贴)

function drawtheheart(){
    tset=2.5;
    t=millis()/1000%(tset+0.1);

    angularacceleration1st=6*PI;
    agularvelocity1stmax=1/2*angularacceleration1st*tset/2;

    angularacceleration2nd=5.12*PI;
    agularvelocity2ndmax=1/2*angularacceleration2nd*tset/2;

    angularacceleration3rd=3.84*PI;
    agularvelocity3rdmax=1/2*angularacceleration3rd*tset/2;

    angularacceleration4th=1.92*PI;
    agularvelocity4thmax=1/2*angularacceleration4th*tset/2;

    angularacceleration5th=1.28*PI;
    agularvelocity5thmax=1/2*angularacceleration5th*tset/2;

    if(t<=1/2*tset)
    {
        theta1st=1/2*angularacceleration1st*t*t;
        theta2nd=1/2*angularacceleration2nd*t*t;
        theta3rd=1/2*angularacceleration3rd*t*t;
        theta4th=1/2*angularacceleration4th*t*t;
        theta5th=1/2*angularacceleration5th*t*t;
    }
    if(t>1/2*tset&&t<tset)
    {
        theta1st=agularvelocity1stmax*(t-1/2*tset)-1/2*angularacceleration1st*(t-1/2*tset)*(t-1/2*tset);
        theta2nd=agularvelocity2ndmax*(t-1/2*tset)-1/2*angularacceleration2nd*(t-1/2*tset)*(t-1/2*tset);
        theta3rd=agularvelocity3rdmax*(t-1/2*tset)-1/2*angularacceleration3rd*(t-1/2*tset)*(t-1/2*tset);
        theta4th=agularvelocity4thmax*(t-1/2*tset)-1/2*angularacceleration4th*(t-1/2*tset)*(t-1/2*tset)+PI*8;
        theta5th=agularvelocity5thmax*(t-1/2*tset)-1/2*angularacceleration5th*(t-1/2*tset)*(t-1/2*tset)+PI*8;
    }

    push();
    rotateY(theta1st);
    draw1stline();
    pop();

    push();
    rotateY(theta2nd);
    draw2ndline();
    pop();

    push();
    rotateY(theta3rd);
    draw3rdline();
    pop();

    push();
    rotateY(theta4th);
    draw4thline();
    pop();

    push();
    rotateY(theta5th);
    draw5thline();
    pop();

    push();
    rotateY(-0.38*PI*t);
    draw6thline();
    pop();

}

写完了之后,我真是感叹,也许自己学得最好的是物理。(嘤~)

    t=millis()/1000%(tset+0.1);

这一句我要强调下,一开始我是没有这个百分号的,利用一个循环去让t归零,但是这样做的结果就是,我的图形只转了一个循环就停下了,我找了很久为什么都没有解决,最后还是小黑狗同学指出%time可以实现循环(cue一下他,非常感激),之后我们就成功实现了让这个可爱的心,不停不停的转下去的效果。效果图如下(小糊~)
在这里插入图片描述

存留的一些问题与新发现

1.又非常愚蠢的在声明全局变量的时候,用函数赋值了。
在这里插入图片描述
以后不敢了,报错的时候搞得我一脸懵,还以为这个函数不让用。

2.其实translate()函数移动的原理我也不是很明白,有些在使用的时候都是看着效果调整的,再有就是旋转物体的旋转轴,我也找的不是很准,最后转起来了之后发现,没有绕着中心轴在转,我又吭哧吭哧用平移函数挪了半天,如果有哪位大佬知道使用详情,可以稍微指点我一下。

3.除此以外,我和另外一位同样选择了这个图像临摹的同学进行了交流,发现,大家的方法真的好不一样啊!!!莫非这就是逻辑的奥秘,他是用改变开始帧的方式,一帧一帧分配的。(总感觉我自己的方法非常笨重,待我之后再和他好好交流下)

拓展图形

在上述图形的基础上,我进行了颜色的变换、图形位置的编排、以及鼠标交互的制作。

鼠标拖拽改变色彩

这次最值得一提的是这个部分,重写了mouseDragged()函数,在鼠标按下左键拖拽时实现了色彩的变化:

function mouseDragged(){
    colorvalue=colorvalue+5;
    color1=color(0,colorvalue,2*colorvalue);
    color2=color(255,255,255);
    if (colorvalue > 255) {
        colorvalue = 0;
    }
}

再有就是进行缩放、平移,把心形们在画面上安排得明明白白,直接上炫酷的效果图咯:
在这里插入图片描述

心得小结

我大概是ddl狂魔,永远都在追逐ddl,这次终于在交报告前的半小时,完成了这篇博客…虽然很紧张很着急,但也确实很有收获,对我这个雪梨小白来说,每一次收获一点什么都是莫大的快乐哇。当然如果有幸这篇超超超冗长的博客能被人看到,发现我制作的还有什么不足或是错误,还希望大佬们帮我指正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

雪梨小白的“码绘”起步——p5.js实现心形动态图形的绘制 的相关文章

  • 开始第一张“码绘”——使用P5.JS画出旋转的爱心

    用P5 JS画出旋转的爱心 首先我们来看看想实现的原图 对这张图片进行观察可以发现图中一共有16颗相同的爱心在旋转 我们拿出其中一个爱心进行分析 我们可以发现 这个爱心是由27个正方体构成 此处应该注意的是 是正方体 而不是正方形 应该用b
  • 用P5 JS绘制动态绚丽烟花——动态篇

    上一节我们探究了绘制静态图像手绘与码绘的差异 但是万事万物 变化万千 有很多东西仅仅用静态是无法描述的 正如恩格斯所言 整个自然界 从最小的东西到最大的东西 从沙粒到太阳 从原生生物到人 都处于永恒的产生和消灭中 处于不断的流动中 处于无休
  • 雪梨小白的“码绘”起步——p5.js实现心形动态图形的绘制

    作为一个快乐的程序媛 尤其还是一个快乐的树莓程序媛 当然应该什么都会 所以这学期学院开了很多偏艺术类的课程让我们学习 然后就开始了互动媒体这门课的学习 这一次的作业要利用p5绘制动态图形 我自己还真的是活力满满的选了一个 emmmm 一点都
  • p5.j​​s createCanvas 未定义错误。未捕获的引用错误

    Problem 我正在尝试使用p5 js在我的简单应用程序中 并因此包含它 我尝试过的 如果我放置一个调试器并查看控制台 我确实会得到以下功能p5Color 例如 和其他 并且脚本会很好地加载到页面上 除了createCanvas不会自动完
  • 在 P5.js 中旋转网格内的对象

    我正在尝试使用合适的 OOP 方法来让对象在网格单元格内单独旋转 我当前的结果是围绕 0 0 参考点旋转所有对象 而不是每个对象在其自己的单元格内旋转 当然 需要的是一个正确的翻译函数 但是当我尝试在innerSquare函数中应用它时tr
  • 尝试使图像在点击时触发功能 - p5.js

    我正在做一个带有交互式画布的艺术课项目 我的目标是让小动物在被点击时发出声音并 移动 我尝试在不创建类的情况下执行此操作 因为由于某种原因我无法在类中使用图像 我正在尝试尽可能轻松地做到这一点 我所说的 移动 是指我试图让背景图像出现在它们
  • 如何让p5.js在特定位置创建画布[重复]

    这个问题在这里已经有答案了 我现在在 HTML CSS 方面确实有 1 小时的经验 并且对编程 例如 Java 脚本 有更深入的理解 所以 如果我对如何在这里做某事的想法为零 请原谅我 我想创建我的 p5 画布 它也遵守我的 CSS 规则
  • 如何将 p5js 与 Webpack 一起使用

    我想写一个基于的库p5js https github com processing p5 js 所以在我的 Javascript 项目中我有Webpack作为开发依赖项安装 我将其写在start js import p5 from p5 p
  • 如何在javascript中获取频率值?

    我是一名意大利学生 我正在使用 p5 的库来创建一个网络吉他调音器 我想知道是否有办法获取麦克风输入的频率 图书馆链接 https p5js org reference libraries p5 sound https p5js org r
  • P5.js curveVertex 函数在某个点闭合

    我创建了一个噪声函数 它与一个圆函数配对 创建一个看起来很酷的随机噪声圆 我的问题是curveVertex除了第一个和最后一个顶点的连接之外 P5 js 中的函数工作正常 我的代码是 let start Array 50 fill 0 do
  • 如何将 p5.js 画布放置在 div 容器内? [复制]

    这个问题在这里已经有答案了 到目前为止 我已经得到了 p5 js 画布大小 可以使用以下命令对其父 div 容器大小做出反应document getElementById divName offsetWidth and offsetHeig
  • p5.j​​s 中的上下移动(并使用 WASD)

    在p5中如何使用键盘让角色移动 我的意思是 不仅仅是向左和向右 我还想使用 WASD 键 我用过这个 形状作为占位符 https editor p5js org TheDiamondfinderYT present 8ZqV2LsVB ht
  • 如何在合并排序期间“暂停”以可视化 JS p5js

    我正在使用 p5 js 开发排序可视化工具 我需要知道是否可以减慢合并排序 以便可以更慢地绘制它 我目前正在尝试使用下面的睡眠功能来减慢它们的合并功能 但我得到 未捕获的类型错误 a slice 不是函数 我只是犯了一个愚蠢的错误 还是我错
  • 如何将 p5.js 画布放入 html div 中

    我正在尝试将 p5 js 添加到网页中某一部分的背景 我是 javascript 新手 不知道如何将这两个部分绑定在一起 您需要在设置中添加代码 确保 html 中的脚本标记中也包含该函数 请注意 您不要在 parent 中添加 var m
  • 如何用圆圈替换光标,而不是在 p5.js 中将其绘制到画布上?

    问题 我正在尝试使用 p5 js 创建一个简单的绘图应用程序 我想在光标位置显示一个代表画笔大小的圆圈 而不是标准光标图像 可能的解决方案1 使用替换光标cursor p5 的原生函数 为什么它不起作用 The p5光标功能 https p
  • 使用处理的二次曲线上的点 (p5.js)

    我使用这个公式来计算二次曲线上的点 cPx2 1 t 1 t x1 2 1 t t qcX t t x2 cPy2 1 t 1 t y1 2 1 t t qcY t t y2 当我设置 t 10 并迭代曲线时 我得到 看起来它不仅获得了曲线
  • 在 p5js 中将画布导出为 GIF/PNG

    I use 原子编辑器 我要实现20 秒 GIF用我的画布 saveFrames 有一个限制 我猜 即使我输入 它也可以将 png 文件保存为短 gif 3 5 秒 saveFrames aa png 15 22 我发现了 CCapture
  • 为什么在处理.org java pdf 导出时只显示一个框?

    下面是我的代码 在运行时它显示了我想要的多个框 但是当我尝试导出时 它只在该帧位置显示一个框 我尝试在特定帧生成输出 但它有同样的问题 import processing pdf int ofs 500 boolean record voi
  • “未捕获的引用错误:窗口未定义”p5.js Web Worker

    我有一个 javascript 代码 我将网络工作者与 p5 js 库一起使用 它不允许我使用 p5 的任何功能 所以我必须使用importScripts p5 js 在使用 p5 的任何函数之前导入 p5 js 库的函数 onmessag
  • 在画布中的鼠标位置放大/缩小

    我正在尝试使用 p5 js 实现缩放功能 当前缩放级别以及 x 和 y 位置存储在controls view目的 默认位置或 0 0 位置位于左上角 问题是调整放大 缩小时的 x 和 y 位置值 以便无论视图的当前位置是什么 它都会停留在缩

随机推荐

  • C++中前置声明的应用与陷阱

    前置声明的使用 有一定C 开发经验的朋友可能会遇到这样的场景 两个类A与B是强耦合关系 类A要引用B的对象 类B也要引用类A的对象 好的 不难 我的第一直觉让我写出这样的代码 A h include B h class A B b publ
  • Vue CLI创建新项目,并运行

    1 准备工作 创建项目之前 我们需要知道在哪里创建 第一种 找到创建的文件 打开cmd方法 第二种方法 1 打开需要创建vue项目的文件下 按住shift 鼠标右键 2 点击 此处打开Powershell命令 2 安装vue cli脚手架
  • html 下拉列表对齐,HTML下拉元素宽度未与兄弟姐妹对齐

    你应该使用display inline block而不是float left in list item css 并且应该添加display table row 进入 子列表项目 dark blue 31394C light gray E6E
  • Altium Designer 报错整理-软件安装失败

    一 软件安装问题 安装问题描述一 关于软件安装 安装到进行到最后一步 显示Optimizing startup performance please wait 然后就一直卡住停留在这一步 无法进行下一步 尝试的办法 低版本 安装问题依旧 管
  • IDEA下载安装及配置

    IntelliJ IDEA 的安装 配置与使用 根据尚硅谷进行整理 仅仅只做笔记 根据尚硅谷进行整理 仅仅只做笔记 根据尚硅谷进行整理 仅仅只做笔记 一 IDEA 的下载地址 下载地址 https www jetbrains com ide
  • git命令学习(三)

    merge和rebase的区别 git工作流 git stash 使用场景举例 一个分支还没提交时 要切换到下一个分支 可将前一个分支放在git栈中 git stash git checkout B 处理B分支 git checkout A
  • openlayers3开发教程_开始

    openlayers3开发教程 开始 openlayers官方网站 https openlayers org 在旧版本处查看 Latest v3 v3 20 1 released 2016 12 12 docs API examples o
  • switch手柄可以连电脑吗_你想要的手柄:既能连switch又能连PC!

    您好 我是Manta科技资讯 首先 聊一聊任天堂switch 任天堂switch主机模式下是通过DOCK底座将游戏主机与电视连接以实现无缝切换 这个DOCK底座有2个USB接口 很多小伙伴不知道用它来干嘛 其实DOCK底座能够拓展很多额外的
  • kettle plugin 插件开发

    http wiki pentaho com display COM PDI Plugin Loading svn source pentaho org svnkettleroot plugins S3CsvInput
  • HDU - 1716 排列2(暴力;next_permutation)

    Ray又对数字的列产生了兴趣 现有四张卡片 用这四张卡片能排列出很多不同的4位数 要求按从小到大的顺序输出这些4位数 Input 每组数据占一行 代表四张卡片上的数字 0 lt 数字 lt 9 如果四张卡片都是0 则输入结束 Output
  • Win11打不开Windows安全中心

    1 打开Windows PowerShell ISE 在搜索框内搜索windows powershell ise 然后右击以管理员身份运行 2 依次执行如下3个命令即可 中途出现部署失败的红色提示可以无视 整个过程几分钟 复制回车 Set
  • bootstrap-table动态合并相同行和列的方法

    先看看效果 var getData ctx demo table list table bootstrapTable dataType json method post cache false url getData columns che
  • 详解JPEG编码格式

    参考文章1 参考文章2 MJPEG是一种视频压缩格式 其中的每一帧图像都使用JPEG编码 实际上 M J P E G
  • JS逆向-百度翻译sign

    前言 本文是该专栏的第36篇 后面会持续分享python爬虫干货知识 记得关注 有粉丝留言 近期需要做个翻译功能 考虑到百度翻译语言语种比较全面 但是它的参数被逆向加密了 对于这种情况需要怎么处理呢 所以本文以它为例 废话不多说 跟着笔者直
  • uniapp实现小程序云开发

    打开微信开发者工具 填写你的appid 勾选使用云开发 对应的uniapp里也要配置上你的appid喔 在这个文件manifest json 我在App vue页面 不一定是在这个页面 可以视你的情况而定 里调用 了wx cloud ini
  • JavaScript算法之动态规划

    动态规划的基本概念 动态规划 Dynamic Programming DP 是运筹学的一个分支 是求解决策过程最优化的过程 动态规划算法通常用于求解具有某种最优性质的问题 在这类问题中 可能会有许多可行解 每一个解都对应于一个值 我们希望找
  • pyqt5 tableWidget入门,和treewidget联动功能

    1 成品 最近在做项目的过程中需要用到QTreeWidget和QTableWidget联动 上一篇文章介绍了 QTreeWidget的基本用法 这里介绍一下QTableWidget的基本用法 及我在项目中的使用 先看看最终成品 要实现以上图
  • Visual Studio 2017 、2019安装Windows SDK失败的解决办法(改盘符引起)

    如果是改盘符出错就请往下看 如果不是就别往下看了 这是血泪踩出来的坑 希望有所帮助 我是手残把电脑盘符改了 然后vs就开始疯狂报错 百试无果 百度不出 果断放弃 刚开始是安装的2017 卸载完后安装的2019 安好后就开始报 fatal e
  • vue(vue-cli3)根据不同环境打包

    配置环境 在项目根目录下创建两个文件 env test NODE ENV production VUE APP ENV test env build NODE ENV production VUE APP ENV production 修改
  • 雪梨小白的“码绘”起步——p5.js实现心形动态图形的绘制

    作为一个快乐的程序媛 尤其还是一个快乐的树莓程序媛 当然应该什么都会 所以这学期学院开了很多偏艺术类的课程让我们学习 然后就开始了互动媒体这门课的学习 这一次的作业要利用p5绘制动态图形 我自己还真的是活力满满的选了一个 emmmm 一点都