p5.js 椭圆的用法:从基础到创意应用

点赞 + 关注 + 收藏 = 学会了

椭圆是圆形的 "灵活亲戚"------ 它可以是胖的、瘦的、横的、竖的,是创作中非常实用的图形元素。p5.js 的 ellipse() 函数能轻松绘制各种椭圆,这篇教程将带你从零基础掌握它的用法,并通过实例学会创意应用。

认识 ellipse ():椭圆的 "身份证"

什么是 ellipse ()?

ellipse() 是 p5.js 专门用于绘制椭圆的函数。椭圆可以理解为 "被拉伸的圆",当它的宽度和高度相等时,就变成了正圆形(这也是为什么 circle() 其实是 ellipse() 的特殊形式)。

在创作中,椭圆的用途非常广泛:可以画月亮、鸡蛋、叶子、人脸、按钮,甚至是抽象艺术中的基础元素。

核心参数:4 个数字定形状

ellipse() 函数的基本语法只有 4 个必要参数,非常简单:

js 复制代码
ellipse(x, y, w, h)

参数解释:

  • x:椭圆中心点的水平位置(左右位置,越大越靠右)
  • y:椭圆中心点的垂直位置(上下位置,越大越靠下)
  • w:椭圆的宽度(水平方向的最大距离)
  • h:椭圆的高度(垂直方向的最大距离)

举个例子:ellipse(200, 150, 100, 60) 表示在画布(200,150)的位置,画一个宽 100、高 60 的椭圆。

宽高比决定形状

椭圆的 "胖瘦" 由宽度(w)和高度(h)的比例决定:

  • w > h 时:横向椭圆(比如躺着的鸡蛋)
  • w < h 时:纵向椭圆(比如竖着的鸡蛋)
  • w = h 时:正圆形(和 circle() 效果一样)

第一个椭圆

从最基础的代码开始,绘制一个简单的椭圆,感受参数的作用。

js 复制代码
function setup() {
  // 创建一个400×400的画布
  createCanvas(400, 400);
  // 灰色背景(220是浅灰色,0是黑,255是白)
  background(220);
}

function draw() {
  // 画一个椭圆:中心(200,200),宽200,高100(横向椭圆)
  ellipse(200, 200, 200, 100);
  
  // 再画一个小椭圆:中心(200,200),宽80,高150(纵向椭圆)
  fill(255, 200, 0); // 填充黄色
  ellipse(200, 200, 80, 150);
}

在浅灰色画布上,有一个黑色边框的横向椭圆(像压扁的圆),中间叠加了一个黄色的纵向椭圆(像拉长的圆)。

  • fill(255, 200, 0) 用来设置椭圆内部的颜色(这里是黄色,RGB 值)
  • 两个椭圆中心点相同(200,200),但宽高不同,形成了交叉的效果

进阶:给椭圆 "化妆"(样式设置)

和圆一样,我们可以通过 p5.js 的样式函数给椭圆设置颜色、边框等,让它更符合创作需求。

常用样式函数:

  • fill(r, g, b):设置填充色(RGB 值,0-255),noFill() 取消填充
  • stroke(r, g, b):设置边框色,noStroke() 取消边框
  • strokeWeight(weight):设置边框粗细(数值越大边框越粗)
js 复制代码
function setup() {
  createCanvas(400, 300);
  background(255); // 白色背景
  noLoop(); // 只绘制一次,不重复刷新
}

function draw() {
  // 1. 无填充、红色粗边框椭圆
  stroke(255, 0, 0); // 红色边框
  strokeWeight(5); // 边框粗5像素
  noFill(); // 不填充内部
  ellipse(100, 100, 120, 80);
  
  // 2. 蓝色填充、无边框椭圆
  noStroke(); // 取消边框
  fill(0, 0, 255); // 蓝色填充
  ellipse(250, 100, 100, 100); // 宽高相等,其实是圆形
  
  // 3. 绿色填充、黑色细边框椭圆
  stroke(0); // 黑色边框
  strokeWeight(2); // 细边框
  fill(0, 255, 0); // 绿色填充
  ellipse(175, 220, 180, 90);
}

在白色画布上有三个不同样式的椭圆,分别展示了 "纯边框"、"纯填充"、"填充 + 边框" 三种效果。

改变椭圆的 "定位方式"

默认情况下,ellipse(x, y, w, h) 中的 x, y 是椭圆的中心点。但通过 ellipseMode() 函数,我们可以改变这个规则,让定位更灵活。

ellipseMode () 的两种常用模式:

  • ellipseMode(CENTER):默认模式,x, y 是中心点(推荐新手先掌握这个)
  • ellipseMode(CORNER)x, y 是椭圆左上角的坐标(类似矩形的定位方式)
js 复制代码
function setup() {
  createCanvas(400, 200);
  background(240);
  noLoop();
  
  // 画参考线(方便观察)
  stroke(200);
  line(0, 100, 400, 100); // 水平线
  line(200, 0, 200, 200); // 垂直线
  
  // 1. 默认模式(CENTER):x,y是中心点
  fill(255, 150, 150, 150); // 半透明粉色
  ellipseMode(CENTER);
  ellipse(200, 100, 100, 60);
  text("CENTER模式", 150, 40);
  
  // 2. CORNER模式:x,y是左上角
  fill(150, 150, 255, 150); // 半透明蓝色
  ellipseMode(CORNER);
  ellipse(200, 100, 100, 60);
  text("CORNER模式", 150, 180);
}

粉色椭圆以交叉点(200,100)为中心,蓝色椭圆以交叉点为左上角,清晰展示了两种定位方式的区别。

让椭圆 "动起来":简单动画示例

椭圆的参数(位置、大小、颜色)可以通过变量控制,结合 draw() 函数的自动刷新特性,就能做出动画效果。

摇摆的椭圆(模拟钟摆)

js 复制代码
let angle = 0; // 角度变量,控制摇摆

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

function draw() {
  background(135, 206, 235); // 天空蓝背景
  
  // 计算椭圆的x坐标(用正弦函数实现左右摇摆)
  let x = 200 + sin(angle) * 100;
  // y坐标固定在150
  let y = 150;
  
  // 画摇摆的椭圆
  fill(255, 215, 0); // 金黄色
  noStroke();
  ellipse(x, y, 80, 50);
  
  // 角度增加,让动画持续(0.05控制速度)
  angle = angle + 0.05;
}
  • sin(angle) 会生成 -1 到 1 之间的波动值,乘以 100 后,x 坐标会在 100 到 300 之间摇摆
  • 每次 draw() 执行时,angle 增加 0.05,实现连续动画
  • 背景色在每次刷新时重绘,避免留下轨迹

呼吸效果(大小变化)

js 复制代码
let size = 50; // 初始大小
let growing = true; // 是否在变大

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

function draw() {
  background(0); // 黑色背景
  
  // 画一个紫色椭圆,中心在画布中间
  fill(128, 0, 128); // 紫色
  noStroke();
  ellipse(200, 200, size, size * 0.7); // 高度是宽度的70%
  
  // 控制大小变化(呼吸效果)
  if (growing) {
    size = size + 1; // 变大
    if (size > 200) growing = false; // 最大200,开始变小
  } else {
    size = size - 1; // 变小
    if (size < 50) growing = true; // 最小50,开始变大
  }
}

紫色椭圆在黑色背景上像呼吸一样反复变大、变小,宽高比保持不变(始终是横向椭圆)。

综合案例:漂浮的气球束

用椭圆制作一组更直观的漂浮气球,每个气球都是典型的椭圆形状,搭配绳子和飘动效果。

  1. 造型设计
    • 每个气球都是典型的纵向椭圆(高度略大于宽度),符合真实气球的形态
    • 加入白色高光椭圆(半透明),增强气球的立体感
    • 用棕色线条作为绳子,所有绳子汇聚到一个节点,形成 "束" 的效果
  2. 椭圆参数应用
    • 不同气球通过w(宽度)和h(高度)参数控制大小,体现多样性
    • 高光部分使用小比例椭圆,位置偏移主气球中心,模拟光线反射
    • 绳子节点用圆形椭圆(w=h)表示,展示椭圆与圆的关系
  3. 动画效果
    • 利用sin()cos()函数让气球产生自然的左右、上下浮动(类似真实气球飘动)
    • 每个气球设置不同的摆动速度(speed参数),避免动作单调
    • 浮动幅度控制在合理范围(±15 像素),保持整体协调
  4. 代码技巧
    • 用对象数组balloons存储多个气球的属性,方便批量管理和绘制
    • 通过循环遍历数组绘制所有气球,减少重复代码
    • 用透明度(RGBA 的第四个参数)处理高光,增强视觉层次感
js 复制代码
// 存储多个气球的属性
let balloons = [];

function setup() {
  createCanvas(500, 600);

  // 初始化5个气球,设置不同位置、大小和颜色
  balloons = [
    {x: 150, y: 300, w: 80, h: 100, color: [255, 99, 71], swing: 0, speed: 0.03},
    {x: 220, y: 250, w: 70, h: 90, color: [60, 179, 113], swing: 1, speed: 0.02},
    {x: 300, y: 280, w: 90, h: 110, color: [70, 130, 180], swing: 2, speed: 0.04},
    {x: 180, y: 320, w: 60, h: 80, color: [255, 165, 0], swing: 3, speed: 0.025},
    {x: 350, y: 310, w: 75, h: 95, color: [147, 112, 219], swing: 4, speed: 0.035}
  ];
}

function draw() {
  background(240); // 浅灰色背景

  // 绘制气球束的绳子交汇点
  let ropeX = 250;
  let ropeY = 400;
  fill(139, 69, 19); // 棕色
  ellipse(ropeX, ropeY, 10, 10); // 绳子结

  // 循环绘制每个气球
  for (let i = 0; i < balloons.length; i++) {
    let b = balloons[i];

    // 更新气球的摆动位置(左右浮动)
    b.swing += b.speed;
    let floatX = sin(b.swing) * 15; // 左右摆动幅度
    let floatY = cos(b.swing * 0.8) * 10; // 上下浮动幅度

    // 绘制气球(椭圆主体)
    fill(b.color);
    noStroke();
    ellipse(b.x + floatX, b.y + floatY, b.w, b.h);

    // 绘制气球高光(增加立体感)
    fill(255, 255, 255, 150); // 半透明白色
    ellipse(b.x + floatX - b.w/6, b.y + floatY - b.h/6, b.w/4, b.h/4);

    // 绘制连接绳子
    stroke(139, 69, 19);
    strokeWeight(2);
    line(b.x + floatX, b.y + floatY + b.h/2, ropeX, ropeY);
  }

  // 绘制地面
  fill(184, 134, 11); // 泥土色
  rect(0, height - 50, width, 50);
}

以上就是本文的全部内容啦,想了解更多 P5.js 用法欢迎关注 《P5.js中文教程》

可以➕我 green bubble 吹吹水咯

点赞 + 关注 + 收藏 = 学会了

相关推荐
climber112120 分钟前
【Python Web】一文搞懂Flask框架:从入门到实战的完整指南
前端·python·flask
Watermelo61721 分钟前
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
前端·javascript·vue.js·数据挖掘·数据分析·流程图·数据可视化
门前云梦23 分钟前
ollama+open-webui本地部署自己的模型到d盘+两种open-webui部署方式(详细步骤+大量贴图)
前端·经验分享·笔记·语言模型·node.js·github·pip
Micro麦可乐23 分钟前
前端拖拽排序实现详解:从原理到实践 - 附完整代码
前端·javascript·html5·拖拽排序·drop api·拖拽api
Watermelo61724 分钟前
Web Worker:让前端飞起来的隐形引擎
前端·javascript·vue.js·数据挖掘·数据分析·node.js·es6
Micro麦可乐29 分钟前
前端与 Spring Boot 后端无感 Token 刷新 - 从原理到全栈实践
前端·spring boot·后端·jwt·refresh token·无感token刷新
Heidi__29 分钟前
前端数据缓存机制详解
前端·缓存
讨厌吃蛋黄酥31 分钟前
前端路由双雄:Hash vs History,谁才是React项目的真命天子?
前端·react.js·设计
VillenK33 分钟前
vban2.0中table的使用—action封装
前端·vue.js
Hilaku41 分钟前
AVIF vs. JPEG XL:2025年,我们该为网站选择哪种下一代图片格式?
前端·javascript·html