xxxxxxxxxx
173
let minMargin = 25; // 最小边距
let maxMargin; // 最大边距,将根据画布宽度动态计算
let formattedText;
let baseX, baseY;
let chars = [];
let butlerLightFont;
let gravity; // 初始重力加速度
let gravityIncrement = 0.01; // 每帧增加的重力
function preload() {
// 预加载字体文件
butlerLightFont = loadFont('Butler_Light.otf');
}
function setup() {
createCanvas(windowWidth, windowHeight); // 创建自适应画布
textAlign(CENTER, CENTER); // 设置文本对齐方式为水平居中和垂直居中
colorMode(HSL); // 使用HSL颜色模式
textFont(butlerLightFont); // 应用自定义字体
baseX = width / 2; // 基准x位置
baseY = height / 1.9; // 基准y位置
adjustForScreenSize(); // 根据屏幕尺寸调整参数
adjustText(); // 调整文本格式和字符大小
}
function draw() {
background(0); // 设置背景为黑色
gravity += gravityIncrement; // 增加重力加速度
let spring = 0.13; // 弹力系数
let damping = 0.9; // 阻尼系数
let interactionX = mouseX;
let interactionY = mouseY;
let influenceDistance = 100; // 鼠标影响的范围
let touchInfluenceDistance = 2; // 触摸影响的范围,缩小一半
let influenceStrength = 25; // 鼠标影响的力度
let touchInfluenceStrength = 3; // 触摸影响的力度,减小一半
// 如果是触摸设备且存在触摸点,使用第一个触摸点的坐标
if (touches.length > 0) {
interactionX = touches[0].x;
interactionY = touches[0].y;
influenceDistance = touchInfluenceDistance; // 使用触摸影响的范围
influenceStrength = touchInfluenceStrength; // 使用触摸影响的力度
}
for (let i = 0; i < chars.length; i++) {
let char = chars[i];
let distance = dist(interactionX, interactionY, char.x, char.y);
if (distance < influenceDistance) {
// 当鼠标或触摸点靠近字符时,字符向上移动并受到重力影响
char.vy -= influenceStrength;
} else {
// 处理自由落体效果
char.vy += gravity;
}
char.y += char.vy;
// 如果字符低于基准位置,则使用弹力系数让它回弹
if (char.y > char.baseY) {
char.y = char.baseY;
char.vy = -char.vy * spring;
}
// 阻尼效果,减少来回震动
char.vy *= damping;
// 根据与鼠标或触摸点的距离改变字符颜色
let distanceFactor = map(distance, 0, influenceDistance, 0, 1); // 从0到1的比例
let hue = 0; // 颜色为黑色时的色相
let saturation = map(distanceFactor, 0, 1, 0, 100); // 饱和度从0(黑色)到100
let lightness = map(distanceFactor, 0, 1, 30, 65); // 亮度从30(接近黑色)到70(接近白色)
fill(hue, saturation, lightness); // 设置字符颜色
text(char.char, char.x, char.y);
}
}
// 初始化字符信息
function setupChars() {
chars = []; // 清空已有字符数组
let lines = formattedText.split('\n');
let lineHeight = textAscent() + textDescent(); // 每行文字的高度
let letterSpacing = 0.009; // 字符间距
for (let i = 0; i < lines.length; i++) {
let currentLine = lines[i];
let y = baseY - (lines.length * lineHeight) / 2 + i * lineHeight;
let xOffset = -textWidth(currentLine) / 2;
for (let j = 0; j < currentLine.length; j++) {
let charWidth = textWidth(currentLine[j]);
let charX = baseX + xOffset + charWidth / 2 + letterSpacing * j;
chars.push({ char: currentLine[j], x: charX, y: y, baseY: y, vy: 0 });
xOffset += charWidth + letterSpacing; // 累加字符宽度和间距
}
}
}
// 格式化文本以适应指定宽度
function formatText(text, maxWidth) {
let words = text.split(' ');
let formattedText = '';
let currentLine = '';
for (let word of words) {
let testLine = currentLine + word + ' ';
let testWidth = textWidth(testLine);
if (testWidth > maxWidth && currentLine !== '') {
formattedText += currentLine + '\n';
currentLine = word + ' ';
} else {
currentLine = testLine;
}
}
formattedText += currentLine.trim();
return formattedText;
}
// 当窗口大小调整时,重新调整画布大小并重新设置字符位置
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
baseX = width / 2;
baseY = height / 2;
adjustForScreenSize(); // 重新调整作用力参数
adjustText(); // 重新调整文本和字符大小
}
// 根据画布大小调整文本大小和布局
function adjustText() {
let maxFontSize = 47;
let minFontSize = 22;
let newFontSize = map(width, 1000, 1800, minFontSize, maxFontSize); // 根据画布宽度调整字体大小
newFontSize = constrain(newFontSize, minFontSize, maxFontSize); // 限制字体大小在22到45之间
textSize(newFontSize); // 设置动态字体大小
// 计算最大边距,使文本区域保持一定宽度
maxMargin = width * 0.06; // 最大边距为画布宽度的6%
let textContent = "Liu Yingxin is a Chinese-born, New York-based artist and designer with an academic background that includes studies at the Central Academy of Fine Arts in traditional Chinese painting, the Royal College of Art, and Pratt Institute in visual communication. Her work transcends the boundaries of a single medium, emphasizing a concept-driven and problem-solving approach while exploring the fusion of various media and visual forms. Her creations navigate between the virtual and the real, as well as between online and physical spaces, aiming to foster new interactions between people and devices through innovative forms. Liu Yingxin underscores the importance of visual and conceptual elements in solving problems, with a human-centered focus on perception and cognition, striving to offer audiences profound experiences and reflective spaces in her art and design.";
let availableWidth = width - maxMargin * 2; // 计算可用宽度
availableWidth = constrain(availableWidth, minMargin * 2, width - maxMargin * 2); // 限制可用宽度
formattedText = formatText(textContent, availableWidth); // 重新格式化文本以适应新宽度
setupChars(); // 重新设置字符位置
}
// 根据屏幕尺寸调整作用力参数
function adjustForScreenSize() {
let screenFactor = (width - 800) / 800; // 计算屏幕大小因子
// 根据屏幕大小调整重力、弹力和阻尼
gravity = 0.5 + screenFactor * 0.5; // 重力加速度,屏幕越大,重力越强
gravityIncrement = 0.01 + screenFactor * 0.02; // 每帧增加的重力,屏幕越大,增加的重力越大
spring = 0.13 + screenFactor * 0.1; // 弹力系数,屏幕越大,弹力越强
damping = 0.9 - screenFactor * 0.3; // 阻尼系数,屏幕越大,阻尼越小
// 确保阻尼系数在合理范围内
damping = constrain(damping, 0.1, 0.9);
}