You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

p5.js中translate后绘制偏移:星空位置异常问题求助

问题与解决建议

问题描述

制作日食背景下的星空效果时,星星位置偏移至右下角,推测与translate函数有关。需求为:通过滑块控制月亮遮挡太阳时,日光逐渐变暗,星空效果显现。

问题根源

translate(width/2, height/2)将画布坐标系原点移至中心,但星星的x、y坐标是基于**原坐标系(左上角为原点)**生成的(random(width)、random(height))。绘制星星时,坐标系已经偏移,导致所有星星的位置都被额外加上了width/2和height/2,最终集中到右下角。

解决方法

方法一:生成星星时使用中心坐标系

直接在星星构造函数中生成以画布中心为原点的坐标,配合translate后的坐标系,星星会均匀分布在整个画布:

// 修改Star类的constructor
constructor() { 
    this.x = random(-width/2, width/2);
    this.y = random(-height/2, height/2);
    this.size = random(.25,3);
    this.t = random(TAU);
}

方法二:用push()/pop()隔离坐标系变换

将太阳和月亮的绘制代码用push()和pop()包裹,这样坐标系变换仅作用于太阳月亮,星星绘制仍使用原坐标系:

function draw() {
  val = slider.value();
  background(color(204,30,map(abs(val),0,80,10,80)));

  // 包裹坐标系变换,避免影响星星绘制
  push();
  translate(width/2,height/2);
  fill('yellow');
  circle(0,0,80);
  fill('white');
  circle(val,0,80);
  pop(); // 重置坐标系到原状态
    
  for (var i = 0; i < stars.length; i++) {
    stars[i].draw();   
  }
}

另外,代码中存在小错误:slider.style('border-radius', '50&');里的&需改为%,否则圆角样式不生效。

修改后的完整代码

JavaScript

let slider ;
let val ;
var stars = [];

function setup() {
  createCanvas(600, 600);
  slider = createSlider(-80,0,-80);
  slider.position(10,10);
  slider.style('width', '100px');
  slider.style('border-radius', '50%'); // 修正符号错误
  colorMode(HSB);
  
  for (var i = 0; i < 100; i++) {
    stars[i] = new Star();
  }
}

function draw() {
  val = slider.value();
  // 根据滑块值动态调整背景亮度
  background(color(204,30,map(abs(val),0,80,10,80)));
  
  // 用push/pop隔离坐标系变换
  push();
  translate(width/2,height/2);
  fill('yellow');
  circle(0,0,80);
  fill('white');
  circle(val,0,80);
  pop();
    
  for (var i = 0; i < stars.length; i++) {
    stars[i].draw();   
  }
}

// star class //
class Star {
    constructor() { 
        // 方法一:基于中心的坐标(使用方法一时保留这段)
        this.x = random(-width/2, width/2);
        this.y = random(-height/2, height/2);
        // 方法二:原坐标系坐标(使用方法二时启用这段)
        // this.x = random(width);
        // this.y = random(height);
        this.size = random(.25,3);
        this.t = random(TAU);
    }
    
    draw() {
        this.t += 0.1;
        var scale = this.size + sin(this.t) * 2;
        noStroke();
        fill('white'); // 补充白色填充,让星星更清晰
        ellipse(this.x, this.y, scale, scale);
    }
}

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.2/p5.js"></script>

内容的提问来源于stack exchange,提问作者K-PopCorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:34:51