
这次的案例也是与平面设计结合
灵感来源于周杰伦的一首歌《反方向的钟》,太喜欢了所以要为它写代码~
链接在最后
最终动态效果:
一开始是无声的2020年,时钟是顺时针旋转的,这时候可以自己大声说话试试,有随机文字出现的!
分别按a,b,c之后年代会改变为2000,2001,2005,时钟也变成逆时针旋转,这里有周董不同时间的音乐,如果歌曲的音量超出阈值,也有随机文字出现。
不管什么时候,点状的字体都会随时间消散~
知乎视频www.zhihu.com这个案例分4部分:字体,背景,钟,交互
注:代码是p5js写的
在所有之前,设置声音的部分
function preload() {
sound = loadSound('assets/clock.m4a');
sound2 = loadSound('assets/yequ.m4a');
sound3 = loadSound('assets/7.m4a');
}
function setup() {
input = new p5.AudioIn();
input.start();
}
function draw() {
let volume = input.getLevel();
a = map(volume, 0, 1, 3, 10);
}
一· 字体
1.1 会消散的字体


这里用到了一个“文字转化为点”
textToPoints(tet , x , y , fontSize , [options] );
先在set up中建一个数组
points = font1.textToPoints(play_year, 0, 0, 170, {
sampleFactor: 10,
simplifyThreshold: 0
});
· 然后写画点的函数,用到了上面数组里的数,并用x,y作为位置画了圆
· 这里a与音量有关,所以声音越大移动越大
· i求余数是为了给这些点创造些距离,不要太密~
function textPoints(a) {
for (let i = 0; i < points.length - 1; i++) {
let p = points[i];
if (i % 20 == 0) {
p.x += random(-0.1, 0.1) * a;
noStroke();
fill(255);
ellipse(p.x, p.y, 2.3);
}
}
}
最后在draw中调用就可以了
push();
translate(370, 347);
textPoints(a);
pop();
1.2 音量超出阈值后,随机出现的文字
太快了,截图无能,大家可以自己玩玩看( ・᷄ὢ・᷅ )
这里同样写一个函数,如果a超过了threshold就随机写字,这里给的是0.15
这里的文字我都选择歌词的一部分,大家可随意更改~
let texts = ["回到过去", "反方向的钟", "return to the past", "shuttle time", " time machine", "go backwards", "I love you"];
let threshold = 0.15;
function randomText(a) {
if (a > threshold) {
push();
fill(255);
noStroke();
textFont('font2');
textSize(18);
text(texts[int(random(texts.length - 1))], random(width), random(height));
ellipse(random(width), random(height), a * 50, a * 50);
pop();
}
}
同样的在draw中调用这个函数即可。
其他字体很常规啦,都是用text写的,就不多说了~
二· 钟

2.1 六边形钟的外形
用beginShape,endShape写出
//6边形钟
push();
translate(185, 92);
scale(0.75);
rotate(frameCount / -40 * t);
stroke(255);
strokeWeight(2);
fill(255, 30);
beginShape();
vertex(17, -79);
vertex(78, -25);
vertex(63, 55);
vertex(-15, 82);
vertex(-76, 28);
vertex(-61, -53);
endShape(CLOSE);
pop();
2.2 时针,分针,秒针用map()写出
这里引入了t,是为了后面与鼠标交互,让时钟反方向转起来~
let hr = hour();
let mn = minute();
let sc = second();
push();
translate(185, 92);
strokeWeight(2);
rotate(-90);
let secondAngle = map(sc, 0, 60, 0, 360);
stroke(246, 243, 233);
let minuteAngle = map(mn, 0, 60, 0, 360);
stroke(246, 243, 233);
let hourAngle = map(hr % 12, 0, 12, 0, 360);
push();
rotate(t * secondAngle);
stroke(255);
line(0, 0, 50, 0);
pop();
push();
rotate(t *minuteAngle);
stroke(100);
line(0, 0, 37.5, 0);
pop();
push();
rotate(t *hourAngle);
stroke(200);
line(0, 0, 25, 0);
pop();
stroke(255);
point(0, 0);
pop();
三· 背景
3.1 色块
这个很简单啦,就是画图形
function drawShapes() {
//浅蓝色五边形
push();
fill(92, 205, 245);
noStroke();
beginShape();
vertex(123, 68);
vertex(249, 68);
vertex(249, 121);
vertex(198, 186);
vertex(28, 186);
endShape();
pop();
//线
push();
stroke(92, 205, 245);
noFill();
strokeWeight(1);
for (let e = 0; e < 8; e++) {
line(323, 131 + 6 * e, 278 + 6 * e, 186);
}
pop();
//红色五边形
push();
fill(235, 55, 57);
noStroke();
beginShape();
vertex(244, 41 - h);
vertex(244, 52 - h);
vertex(187, 125 - h);
vertex(129, 125 - h);
vertex(192, 41 - h);
endShape();
pop();
//深蓝色五边形
push();
fill(35, 103, 246);
noStroke();
beginShape();
vertex(250, 90 - h);
vertex(309, 90 - h);
vertex(309, 102 - h);
vertex(244, 186 - h);
vertex(176, 186 - h);
endShape();
pop();
}
3.2 随机生成的小 x

先建一个数组,再写2个函数,最后在draw中调用,搞定!
//数组,随机位置
function setup() {
for (var i = 1; i < width; i += 75) {
for (var n = 1; n < height; n += 75) {
let x = random(width);
let y = random(height);
let v = random(20, 50);
snowlocs.push([x, y, v]);
}
}
}
//画出
function draw() {
for (var i = 0; i < snowlocs.length; i++) {
var x, y, v;
[x, y, v] = snowlocs[i];
drawXDad(x, y, v);
}
}
//让 x 转起来
function drawXDad(x, y, v) {
push();
translate(x, y);
rotate(frameCount / -v * t);
drawX();
pop();
}
//一个 x 的函数
function drawX() {
let i = 0;
push();
strokeWeight(2);
stroke(35, 103, 246);
line(i, 10 + i, 10 + i, i);
line(i, i, 10 + i, 10 + i);
pop();
}
四· 交互部分
其实就是切歌的部分,跟之前一篇案例【视觉系编程1—在p5js中用磁带播放周董的歌】
是一样的,特别好用,我又使用了这个效果
需要注意的是,会消散的文字的代码,虽然在set up里写过了,但是还需要在这里复制一下,不然年代就不会改变了!
function keyPressed() {
if (key == 'A' || key == "a") play_song_ids = 1;
else if (key == 'B' || key == "b") play_song_ids = 2;
else if (key == 'C' || key == "c") play_song_ids = 3;
firstSong();
secondSong();
thirdSong();
//把set up里的复制到这里来
points = font1.textToPoints(play_year, 0, 0, 170, {
sampleFactor: 10,
simplifyThreshold: 0
});
}
//3首歌,跟上一次几乎一样
function firstSong() {
let result = false;
if (play_song_ids == 1) {
if (!sound.isPlaying()) {
sound.play();
}
t = 1;
bc = 60;
i = 5;
play_year = "2000"
result = true;
} else {
sound.stop();
result = false;
}
return result;
}
function secondSong() {
let result = false;
if (play_song_ids == 2) {
if (!sound2.isPlaying()) {
sound2.play();
}
t = 1;
bc = 100;
i = 5;
play_year = "2001"
result = true;
} else {
sound2.stop();
result = false;
}
return result;
}
function thirdSong() {
let result = false;
if (play_song_ids == 3) {
if (!sound3.isPlaying()) {
sound3.play();
}
t = 1;
bc = 180;
i = 5;
play_year = "2005"
result = true;
} else {
result = false;
sound3.stop();
}
return result;
}
这样就写完了~
按a,b,c一起回到过去吧hhh...(´・ω・`)
链接在这里:https://editor.p5js.org/nancy2721/present/-OIPl5-9a
时间是一个很有意思也很哲学的话题,大家可以以此为主题进行创作~