【发布时间】:2021-06-30 00:41:09
【问题描述】:
我多次看到非常酷的动态排版示例。在这些例子中,每个字母都是一个助词。文本是一个粒子系统,它可能会受到重力甚至离心力等各种力的影响。这些系统是在 Processing 和 p5.js 中制作的。
我正在使用 p5.js 为充满文本的网络构建一个交互式屏幕,灵感来自这些动态排版示例。 当用户在文本上移动光标时,这开始在屏幕上弹跳。
我将草图从 Processing 翻译成 p5.js,我注意到这个问题与 setup() 函数中的文本间距有关。 在处理中,代码看起来像这样并且它运行正常。
我想重点介绍一下处理代码的这一部分:
void setup() {
size(640, 360);
//load the font
f = createFont("Arial", fontS, true);
textFont(f);
// Create the array the same size as the String
springs = new Spring[message.length()];
// Initialize Letters (Springs) at the correct x location
int locx = 40;
//initialize Letters (Springs) at the correct y location
int locy = 100;
for (int i = 0; i < message.length(); i++) {
springs[i] = new Spring(locx, locy, 40, springs, i, message.charAt(i));
locx += textWidth(message.charAt(i));
//boudaries of text just to make it a nice "go to head"
if (locx >= 360) {
locy+=60;
locx = 40;
}
}
}
你可以看到参数
springs[i] = new Spring(locx, locy, 40, springs, i, message.charAt(i));
locx += textWidth(message.charAt(i));
做它的工作,间隔字母。
但是,当我在 P5.js 中翻译这个草图时,我没有得到同样好的间距。 这是同一部分,但是是 p5.js 代码:
function setup() {
createCanvas(640, 360);
noStroke();
textAlign(LEFT);
// Create the array the same size as the String
springs = new Array(message.length);
// Initialize Letters (Springs) at the correct x location
var locx = 10;
//initialize Letters (Springs) at the correct y location
var locy = 120;
for (var i = 0; i < message.length; i++) {
springs[i] = new Spring(locx, locy, 40, springs, i, message.charAt(i));
locx += textWidth(message.charAt(i));
//boudaries of text just to make it a nice "go to head"
if(locx>= 390){
locy+= 60;
locx= 40;
}
}
}
结果显示
我确信,在 p5js 代码中,这部分存在问题:
springs[i] = new Spring(locx, locy, 40, springs, i, message.charAt(i));
locx += textWidth(message.charAt(i));
因为我试图通过乘以 locx 的值来修复它,如下所示:
springs[i] = new Spring(locx*5, locy, 40, springs, i, message.charAt(i));
然后我得到了
这似乎是正确的,但我确定它不是。
此时我不知道如何修复它,它一定是我不知道的 p5.js 的东西。 非常感谢任何帮助。
//编辑 正如评论中所建议的,您可以找到用 p5.js 编写的 Spring 类:
// Spring class
class Spring {
constructor (_x, _y, _s, _others, _id, letter_) {
// Screen values
this.x_pos = this.tempxpos = _x;
this.y_pos = this.tempypos = _y;
this.size = _s;
this.over = false;
this.move = false;
// Spring simulation constants
this.mass = 8.0; // Mass
this.k = 0.2; // Spring constant
this.damp =0.98; // Damping
this.rest_posx = _x; // Rest position X
this.rest_posy = _y; // Rest position Y
// Spring simulation variables
//float pos = 20.0; // Position
this.velx = 0.0; // X Velocity
this.vely = 0.0; // Y Velocity
this.accel = 0; // Acceleration
this.force = 0; // Force
this.friends = _others;
this.id = _id;
this.letter = letter_;
}
update() {
if (this.move) {
this.rest_posy = mouseY;
this.rest_posx = mouseX;
}
this.force = -this.k * (this.tempypos - this.rest_posy); // f=-ky
this.accel = this.force / this.mass; // Set the acceleration, f=ma == a=f/m
this.vely = this.damp * (this.vely + this.accel); // Set the velocity
this.tempypos = this.tempypos + this.vely; // Updated position
this.force = -this.k * (this.tempxpos - this.rest_posx); // f=-ky
this.accel = this.force / this.mass; // Set the acceleration, f=ma == a=f/m
this.velx = this.damp * (this.velx + this.accel); // Set the velocity
this.tempxpos = this.tempxpos + this.velx; // Updated position
if ((this.overEvent() || this.move) && !(this.otherOver()) ) {
this.over = true;
} else {
this.over = false;
}
}
// Test to see if mouse is over this spring
overEvent() {
let disX = this.x_pos - mouseX;
let disY = this.y_pos - mouseY;
let dis = createVector(disX, disY);
if (dis.mag() < this.size / 2 ) {
return true;
} else {
return false;
}
}
// Make sure no other springs are active
otherOver() {
for (let i = 0; i < message.length; i++) {
if (i != this.id) {
if (this.friends[i].over == true) {
this.velx = -this.velx;
return true;
}
}
}
return false;
}
//the springs collides with the edges of the screen
box_collision() {
if(this.tempxpos+this.size/2>width){
this.tempxpos = width-this.size/2;
this.velx = -this.velx;
} else if (this.tempxpos - this.size/2 < 0){
this.tempxpos = this.size/2;
this.velx = -this.velx;
}
if (this.tempypos+this.size/2>height) {
this.tempypos = height-this.size/2;
this.vely = -this.vely;
} else if (this.tempypos- this.size/2 < 0) {
this.tempypos = this.size/2;
this.vely = -this.vely;
}
}
//the springs collides with each other
collide() {
for (var i = this.id + 1; i < message.length; i++) {
var dx = this.friends[i].tempxpos - this.tempxpos;
var dy = this.friends[i].tempypos - this.tempypos;
var distance = sqrt(dx*dx + dy*dy);
var minDist = this.friends[i].size/2 + this.size/2;
if (distance < minDist) {
var angle = atan2(dy, dx);
var targetX = this.tempxpos + cos(angle) * minDist;
var targetY = this.tempypos + sin(angle) * minDist;
var ax = (targetX - this.friends[i].tempxpos) * 0.01;
var ay = (targetY - this.friends[i].tempypos) * 0.01;
this.velx -= ax;
this.vely -= ay;
this.friends[i].velx += ax;
this.friends[i].vely += ay;
}
}
}
//display the letter Particle
display() {
if (this.over) {
fill(255, 0, 0);
} else {
fill(255);
}
noStroke();
textSize(fontS);
//for debugging
// ellipse(this.tempxpos, this.tempypos, this.size, this.size);
text(this.letter, this.tempxpos, this.tempypos);
}
pressed() {
if (this.over) {
this.move = true;
} else {
this.move = false;
}
}
released() {
this.move = false;
this.rest_posx = this.x_pos;
this.rest_posy = this.y_pos;
}
}
您可以在这里找到 P5.js 编辑器的链接,其中包含以下代码: Spring text p5js code
注意:我必须修复 Spring 类,因为我没有意识到我的所有函数都在构造函数中初始化。现在组成类的函数在构造函数之外。我还没有弄清楚如何解决间距问题。
【问题讨论】:
-
Spring类在哪里定义? -
@Samathingamajig 该类在 setup() 和 draw() 函数之外定义。是一段很长的代码,如果对解决问题有用,我会编辑这篇文章。
-
是的,这很重要。另外,请为我们添加p5 web editor link链接(但不要从这篇文章中删除代码,只需在末尾添加此链接)
-
@Samathingamajig 我已经用代码添加了 Spring 类和 p5 网络编辑器链接。
标签: javascript processing p5.js