p5.js 圆弧的用法

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

在 p5.js 中,arc() 函数用于绘制圆弧,它是创建各种圆形图形和动画的基础。圆弧本质上是椭圆的一部分,由中心点、宽度、高度、起始角度和结束角度等参数定义。通过灵活运用 arc() 函数可以轻松创建饼图、仪表盘、时钟等常见 UI 组件,以及各种创意图形效果。

arc() 的基础语法

基础语法

arc() 函数的完整语法如下:

js 复制代码
arc(x, y, w, h, start, stop, [mode], [detail])

核心参数解释:

  • x, y:圆弧所在椭圆的中心点坐标

  • w, h:椭圆的宽度和高度,如果两者相等,则绘制的是圆形的一部分

  • start, stop:圆弧的起始角度和结束角度,默认以弧度(radians)为单位

可选参数:

  • mode :定义圆弧的填充样式,可选值为OPEN(开放式半圆)、CHORD(封闭式半圆)或PIE(闭合饼图)

  • detail:仅在 WebGL 模式下使用,指定组成圆弧周长的顶点数量,默认值为 25

角度单位与转换

在 p5.js 中,角度可以使用弧度或角度两种单位表示:

  • 默认单位是弧度:0 弧度指向正右方(3 点钟方向),正角度按顺时针方向增加

  • 使用角度单位 :可以通过 angleMode(DEGREES) 函数将角度单位设置为角度

两种单位之间的转换关系:

  • 360 度 = 2π 弧度

  • 180 度 = π 弧度

  • 90 度 = π/2 弧度

p5.js 提供了两个辅助函数用于单位转换:

  • radians(degrees):将角度转换为弧度

  • degrees(radians):将弧度转换为角度

举个例子(基础示例)

举个例子讲解一下如何使用 arc() 函数绘制不同角度的圆弧。

js 复制代码
function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES); // 使用角度单位
}

function draw() {
  background(220);
  
  // 绘制不同角度的圆弧
  arc(100, 100, 100, 100, 0, 90); // 90度圆弧
  arc(250, 100, 100, 100, 0, 180); // 180度圆弧
  arc(100, 250, 100, 100, 0, 270); // 270度圆弧
  arc(250, 250, 100, 100, 0, 360); // 360度圆弧(整圆)
}

这段代码会在画布上绘制四个不同角度的圆弧,从 90 度到 360 度不等。注意,当角度为 360 度时,实际上绘制的是一个完整的圆形。

三种圆弧模式:OPEN、CHORD 与 PIE

arc() 函数的第七个参数mode决定了圆弧的填充方式,有三种可选值:

  • OPEN(默认值):仅绘制圆弧本身,不填充任何区域

  • CHORD:绘制圆弧并连接两端点形成闭合的半圆形区域

  • PIE:绘制圆弧并连接两端点与中心点形成闭合的扇形区域

这三种模式不需要手动定义,p5.js 已经在全局范围内定义好了这些常量。

举个例子:

js 复制代码
function setup() {
  createCanvas(400, 200);
  angleMode(DEGREES);
}

function draw() {
  background(220);
  
  // 绘制不同模式的圆弧
  arc(100, 100, 100, 100, 0, 270, OPEN);
  arc(220, 100, 100, 100, 0, 270, CHORD);
  arc(340, 100, 100, 100, 0, 270, PIE);
}

这段代码会在画布上绘制三个 270 度的圆弧,分别展示 OPENCHORDPIE 三种模式的效果。可以明显看到,OPEN 模式只绘制弧线,CHORD 模式连接两端点形成闭合区域,而 PIE 模式则从两端点连接到中心点形成扇形。

如何选择合适的模式

选择圆弧模式时,应考虑以下因素:

  • 视觉效果需求 :需要纯弧线效果时选择 OPEN,需要闭合区域时选择 CHORDPIE

  • 应用场景 :饼图通常使用 PIE 模式,仪表盘可能使用 CHORD 模式,而简单装饰线条可能使用 OPEN 模式

  • 填充与描边需求:不同模式对填充和描边的处理方式不同,需要根据设计需求选择

值得注意的是,arc() 函数绘制的默认是填充的扇形区域。如果想要获取纯圆弧(没有填充区域),可以使用 noFill() 函数拒绝 arc() 函数的填充。

做几个小demo玩玩

简易数字时钟

在这个示例中,我将使用 arc() 函数创建一个简单的数字时钟,显示当前的小时、分钟和秒数。

js 复制代码
let hours, minutes, seconds;

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES); // 使用角度单位
}

function draw() {
  background(220);
  
  // 获取当前时间
  let now = new Date();
  hours = now.getHours();
  minutes = now.getMinutes();
  seconds = now.getSeconds();

  // 绘制时钟边框
  stroke(0);
  strokeWeight(2);
  noFill();
  arc(width/2, height/2, 300, 300, 0, 360);

  // 绘制小时刻度
  strokeWeight(2);
  for (let i = 0; i < 12; i++) {
    let angle = 90 - i * 30;
    let x1 = width/2 + 140 * cos(radians(angle));
    let y1 = height/2 + 140 * sin(radians(angle));
    let x2 = width/2 + 160 * cos(radians(angle));
    let y2 = height/2 + 160 * sin(radians(angle));
    line(x1, y1, x2, y2);
  }

  // 绘制分钟刻度
  strokeWeight(1);
  for (let i = 0; i < 60; i++) {
    let angle = 90 - i * 6;
    let x1 = width/2 + 150 * cos(radians(angle));
    let y1 = height/2 + 150 * sin(radians(angle));
    let x2 = width/2 + 160 * cos(radians(angle));
    let y2 = height/2 + 160 * sin(radians(angle));
    line(x1, y1, x2, y2);
  }

  // 绘制小时指针
  let hourAngle = 90 - (hours % 12) * 30 - minutes * 0.5;
  let hourLength = 80;
  let hx = width/2 + hourLength * cos(radians(hourAngle));
  let hy = height/2 + hourLength * sin(radians(hourAngle));
  line(width/2, height/2, hx, hy);

  // 绘制分钟指针
  let minuteAngle = 90 - minutes * 6;
  let minuteLength = 120;
  let mx = width/2 + minuteLength * cos(radians(minuteAngle));
  let my = height/2 + minuteLength * sin(radians(minuteAngle));
  line(width/2, height/2, mx, my);

  // 绘制秒针
  stroke(255, 0, 0);
  let secondAngle = 90 - seconds * 6;
  let secondLength = 140;
  let sx = width/2 + secondLength * cos(radians(secondAngle));
  let sy = height/2 + secondLength * sin(radians(secondAngle));
  line(width/2, height/2, sx, sy);
  
  // 显示当前时间文本
  noStroke();
  fill(0);
  textSize(24);
  text(hours + ":" + nf(minutes, 2, 0) + ":" + nf(seconds, 2, 0), 50, 50);
}

关键点解析:

  1. 获取当前时间:使用Date()对象获取当前的小时、分钟和秒数

  2. 角度计算:根据时间值计算指针的旋转角度,注意将角度转换为 p5.js 使用的坐标系(0 度指向正上方)

  3. 刻度绘制:使用循环绘制小时和分钟刻度,每个小时刻度间隔 30 度,每个分钟刻度间隔 6 度

  4. 指针绘制:根据计算的角度和长度绘制小时、分钟和秒针,注意秒针使用红色以区分

  5. 时间文本显示:使用text()函数在画布左上角显示当前时间

饼图

在这个示例中,我将创建一个简单的饼图,展示不同类别数据的比例。

js 复制代码
let data = [30, 10, 45, 35, 60, 38, 75, 67]; // 示例数据
let total = 0;
let lastAngle = 0;

function setup() {
  createCanvas(720, 400);
  angleMode(DEGREES); // 使用角度单位
  noStroke(); // 不绘制边框
  total = data.reduce((a, b) => a + b, 0); // 计算数据总和
}

function draw() {
  background(100);
  pieChart(300, data); // 调用饼图绘制函数
}

function pieChart(diameter, data) {
  lastAngle = 0; // 重置起始角度
  for (let i = 0; i < data.length; i++) {
    // 设置圆弧的灰度值,map函数将数据映射到0-255的灰度范围
    let gray = map(i, 0, data.length, 0, 255);
    fill(gray);
    
    // 计算当前数据点的角度范围
    let startAngle = lastAngle;
    let endAngle = lastAngle + (data[i] / total) * 360;
    
    // 绘制圆弧
    arc(
      width / 2,
      height / 2,
      diameter,
      diameter,
      startAngle,
      endAngle,
      PIE // 使用PIE模式创建扇形
    );
    
    lastAngle = endAngle; // 更新起始角度为下一个数据点做准备
  }
}

关键点解析:

  1. 数据准备:定义示例数据数组data,并计算数据总和total

  2. 颜色设置:使用map()函数将数据索引映射到 0-255 的灰度范围,实现渐变效果

  3. 角度计算:根据每个数据点的值与总和的比例计算对应的角度范围

  4. 圆弧绘制:使用PIE模式绘制每个数据点对应的扇形,形成完整的饼图

这个饼图示例可以通过添加标签、交互效果或动态数据更新来进一步增强功能。

描边效果

在 p5.js 中,我们可以通过以下函数定制圆弧的描边效果:

  • stroke(color):设置描边颜色

  • strokeWeight(weight):设置描边宽度

  • strokeCap(cap):设置描边端点样式(可选值:BUTT, ROUND, SQUARE)

  • strokeJoin(join):设置描边转角样式(可选值:MITER, ROUND, BEVEL)

以下示例展示了如何定制圆弧的描边效果:

js 复制代码
function setup() {
  createCanvas(400, 200);
  angleMode(DEGREES);
}

function draw() {
  background(220);
  
  // 示例1:粗红色描边
  stroke(255, 0, 0);
  strokeWeight(10);
  arc(100, 100, 100, 100, 0, 270);
  
  // 示例2:带圆角端点的描边
  stroke(0, 255, 0);
  strokeWeight(10);
  strokeCap(ROUND);
  arc(220, 100, 100, 100, 0, 270);
  
  // 示例3:带阴影效果的描边
  stroke(0, 0, 255);
  strokeWeight(15);
  strokeCap(SQUARE);
  arc(340, 100, 100, 100, 0, 270);
  
  // 恢复默认设置
  noStroke();
}

关键点解析:

  1. 颜色设置:使用stroke()函数设置不同颜色的描边

  2. 宽度设置:使用strokeWeight()函数调整描边粗细

  3. 端点样式:使用strokeCap()函数设置描边端点的样式(圆角效果特别适合圆弧)

  4. 阴影效果:通过增加描边宽度并偏移绘制位置可以创建简单的阴影效果

填充效果

在 p5.js 中,我们可以通过以下函数定制圆弧的填充效果:

  • fill(color):设置填充颜色

  • noFill():禁用填充效果

  • colorMode(mode):设置颜色模式(RGB、HSB 等)

  • alpha():设置颜色透明度

以下示例展示了如何定制圆弧的填充效果:

js 复制代码
function setup() {
  createCanvas(400, 200);
  angleMode(DEGREES);
  colorMode(HSB, 360, 100, 100); // 使用HSB颜色模式
}

function draw() {
  background(220);
  
  // 示例1:单色填充
  fill(120, 100, 100); // 绿色
  arc(100, 100, 100, 100, 0, 270);
  
  // 示例2:渐变填充
  noFill();
  stroke(0, 0, 100);
  strokeWeight(10);
  for (let i = 0; i < 360; i += 10) {
    fill(i, 100, 100);
    arc(220, 100, 100, 100, i, i+10);
  }
  
  // 示例3:透明填充
  fill(240, 100, 100, 50); // 半透明蓝色
  arc(340, 100, 100, 100, 0, 270);
  
  // 恢复默认设置
  noFill();
  stroke();
}

关键点解析:

  1. 颜色模式:使用colorMode()函数切换到 HSB 模式,方便创建渐变效果

  2. 单色填充:直接使用fill()函数设置单一填充颜色

  3. 渐变填充:通过循环绘制多个小角度的圆弧,每个使用不同的色相值实现渐变效果

  4. 透明度设置:在fill()函数中添加第四个参数(0-100)设置透明度

旋转圆弧

在 p5.js 中创建圆弧动画非常简单,主要通过以下方法实现:

  • **draw()**函数:每秒自动执行约 60 次,用于更新动画帧

  • 变量控制:使用变量控制圆弧的参数(如位置、大小、角度等)

  • frameRate(fps):设置动画帧率(可选)

  • millis():获取当前时间(毫秒),用于精确控制动画时间

圆弧动画效果示例:

js 复制代码
let angle = 0;

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

function draw() {
  background(220);
  
  // 绘制旋转的红色圆弧
  stroke(255, 0, 0);
  strokeWeight(10);
  arc(width/2, height/2, 300, 300, angle, angle + 90);
  
  // 更新角度值,实现旋转效果
  angle += 2; // 调整这个值可以改变旋转速度
  
  // 恢复默认设置
  noStroke();
}

关键点解析:

  1. 角度变量 :使用 angle 变量控制圆弧的起始角度

  2. 角度更新 :在每次 draw() 调用时增加angle值,实现旋转效果

  3. 速度控制:通过调整每次增加的角度值(这里是 2 度)控制旋转速度

弧度与角度的转换技巧

在 p5.js 中,arc()函数默认使用弧度作为角度单位,但我们通常更习惯使用角度。以下是一些转换技巧:

  • 角度转弧度 :使用 radians(degrees) 函数将角度转换为弧度

  • 弧度转角度 :使用 degrees(radians) 函数将弧度转换为角度

  • 设置角度单位 :使用 angleMode(DEGREES) 函数将全局角度单位设置为角度,这样 arc() 函数就可以直接使用角度值

  • 常见角度值 :记住一些常用角度的弧度值,如 90 度 = PI/2,180 度 = PI,270 度 = 3PI/2,360 度 = 2PI

圆弧绘制的常见问题与解决方案

在使用 arc() 函数时,可能会遇到以下问题:

  1. arc () 函数中的 bug :当 start_angle == end_angle 时,可能会出现意外绘制效果。例如,当 start_angle == end_angle == -PI/2 时会绘制一个半圆,这不符合预期。解决方案是避免 start_angleend_angle 相等。

  2. 起始角度的位置 :在 p5.js 中,0 弧度(或 0 度,如果使用 angleMode(DEGREES))指向正右方(3 点钟方向),而不是数学上的正上方。这可能导致方向与预期不符。

  3. 描边宽度的影响 :较宽的描边会使圆弧看起来比实际大。这是因为描边会向路径的两侧扩展。如果需要精确控制大小,可以考虑将arc()的尺寸适当减小,或者使用 shapeMode() 函数调整坐标系。

  4. 浮点精度问题 :在进行角度计算时,尤其是涉及到除法和循环时,可能会遇到浮点精度问题。建议使用 nf() 函数(如 nf(value, 2, 0) )来格式化显示的数值,避免显示过多的小数位。


以上就是本文的全部内容啦,如果想了解更多 p5.js 的玩法可以关注 《P5.js中文教程》

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

相关推荐
任小栗18 分钟前
Vue 3 面试题全套题库
前端·javascript·vue.js
前端程序猿-秦祥21 分钟前
uniapp 报错 Not found ... at view.umd.min.js:1的问题
前端·uni-app·安卓
SixHateSeven24 分钟前
🤯 当本地开发遇上生产环境:一个Shell脚本的救赎
前端·shell
LaoZhangAI30 分钟前
ChatGPT Agent 完全使用指南:2025年7月最新功能详解
前端·后端
北京_宏哥31 分钟前
Python零基础从入门到精通详细教程8-数据类型高级应用 - 上篇
前端·python·面试
全体起立刘sir31 分钟前
代码调用浏览器麦克风api;根据说的话跳转相应的页面;(vue2环境下)
前端
鹏程十八少31 分钟前
2. Android 自定义view 高级UI实战:打造丝滑3D循环滚轮时间选择器
前端
FogLetter32 分钟前
从React状态管理到Zustand:轻量级全家桶开发实践
前端·react.js
李蚊子32 分钟前
前端开发范式的革命性转变:从编码者到意图架构师
前端·javascript·人工智能
WildBlue40 分钟前
🥳React性能优化三剑客:memo、useMemo、useCallback大揭秘
前端·react.js·前端框架