如何在p5.js中为map函数生成的各支出区块分配不同透明色?
问题:为美国政府支出区块分配不同透明色并按比例显示的p5.js问题
我想用map函数生成代表美国政府各支出类别的矩形区块,要求每个区块宽度对应支出占总支出的比例,且每个区块用不同的透明颜色。但尝试用setAlpha()时得到的是渐变效果而非整体透明;调整循环中i值单独修改区块时,出现了颜色拆分的矩形。以下是我的p5.js代码:
function setup() { createCanvas(800, 400); dollar=loadImage('https://media.istockphoto.com/id/1198332549/vector/american-usd-dollar-bill-outline-isolated-on-white-background.jpg?s=1024x1024&w=is&k=20&c=HLVlJ9Ak63IIK2ddS-I-_gr_rHKH8OEFlAGNVNMUhQw=') spending = [ {name: "Social Security", billions: 1220}, {name: "Health Care", billions: 914}, {name: "Income Security", billions: 865}, {name: "National Defense", billions: 767}, {name: "Medicare", billions: 755}, {name: "Education", billions: 677}, {name: "Interest", billions: 475}, {name: "Veteran Benefits", billions: 274}, {name: "Transportation", billions: 132}, {name: "Government", billions: 129}, {name: "Other", billions: 65} ]; } function draw() { background(255); image(dollar,80,-100) dollar.resize(600,0) for (let i=0;i<spending.length;i++){ fill(255,0,0,10) let sectionwidth = map(spending[i].billions,0,6273,0,2470) rect(140,97,sectionwidth,205) } }
问题分析与修正方案
原代码核心问题
- 所有矩形都从
x=140位置开始绘制,导致区块完全重叠,多个低透明度红色叠加后呈现渐变效果 - 未累积起始位置,无法实现按顺序排列的区块
- 所有区块使用相同颜色,未满足"不同透明颜色"的需求
dollar.resize()放在draw()中会重复执行,影响性能
修正后的代码
let dollar; let spending; let totalSpending; function setup() { createCanvas(800, 400); // 预加载图片并调整大小 dollar = loadImage('https://media.istockphoto.com/id/1198332549/vector/american-usd-dollar-bill-outline-isolated-on-white-background.jpg?s=1024x1024&w=is&k=20&c=HLVlJ9Ak63IIK2ddS-I-_gr_rHKH8OEFlAGNVNMUhQw=', () => { dollar.resize(600, 0); }); spending = [ {name: "社会保障", billions: 1220}, {name: "医疗保健", billions: 914}, {name: "收入保障", billions: 865}, {name: "国防", billions: 767}, {name: "医保", billions: 755}, {name: "教育", billions: 677}, {name: "利息", billions: 475}, {name: "退伍军人福利", billions: 274}, {name: "交通", billions: 132}, {name: "政府运作", billions: 129}, {name: "其他", billions: 65} ]; // 计算总支出,避免重复计算 totalSpending = spending.reduce((sum, item) => sum + item.billions, 0); } function draw() { background(255); // 绘制背景美元图片 if (dollar) { image(dollar, 80, -100); } let currentX = 140; // 区块起始x坐标 const blockHeight = 205; const maxDisplayWidth = 600; // 适配画布宽度,避免超出 for (let i = 0; i < spending.length; i++) { // 按比例计算区块宽度 const sectionWidth = map(spending[i].billions, 0, totalSpending, 0, maxDisplayWidth); // 为每个区块分配不同色相的透明色(HSL模式更易控制颜色多样性) const hue = map(i, 0, spending.length, 0, 360); // 色相从0到360循环 fill(hue, 80, 60, 150); // 最后一位是透明度(0-255) // 绘制当前区块 rect(currentX, 97, sectionWidth, blockHeight); // 更新下一个区块的起始x坐标 currentX += sectionWidth; } }
关键修改说明
- 预计算总支出:在
setup()中用reduce计算总支出,避免draw()中重复运算 - 累积区块位置:用
currentX变量记录每个区块的起始位置,绘制后累加宽度,实现区块依次排列 - 差异化透明色:使用HSL颜色模式,按区块索引分配不同色相,同时设置统一或差异化的透明度
- 优化图片处理:仅在图片加载完成后调整一次大小,避免
draw()循环中重复执行 - 适配画布宽度:将最大显示宽度设为画布内合理值,避免区块超出可视范围
内容的提问来源于stack exchange,提问作者Tarnya Marshall
相关产品推荐
相关产品推荐

