基于函数值在Openframeworks中绘制不同颜色及大小的圆形
嘿,你已经搞定了JSON读取和基础绘制这两步,接下来调整圆形的颜色和大小其实核心就是把你的函数值映射到OpenFrameworks能直接用的视觉参数范围,我给你一步步拆解具体方案:
核心工具:ofMap() 数据映射
你的函数值大概率是自定义范围(比如0-1000、-50到50),但画布尺寸、颜色分量都是固定范围(比如半径5-50像素,颜色RGB值0-255),OpenFrameworks的ofMap()就是专门干这个转换的,能帮你把任意范围的数值线性映射到目标区间,还能自动限制超出范围的值。
一、根据函数值调整圆形大小
假设你从JSON里拿到的单个函数值存在float funcValue变量里,先确定这个值的全局最小/最大值(可以从所有JSON数据里统计,或者预先设定),然后映射到你想要的半径范围:
// 示例:把funcValue从[minVal, maxVal]映射到[5, 50]的半径范围 // 最后一个true开启clamp,避免极端值导致半径异常 float radius = ofMap(funcValue, minVal, maxVal, 5, 50, true);
之后画圆时直接用这个radius即可:ofDrawCircle(x, y, radius);
二、根据函数值调整圆形颜色
这里给你三种常用的颜色映射方案,按需选择:
1. 灰度映射(简单直接)
把函数值直接转换成0-255的灰度值:
float gray = ofMap(funcValue, minVal, maxVal, 0, 255, true); ofSetColor(gray); // 等价于ofSetColor(gray, gray, gray)
2. 双色渐变(视觉层次丰富)
定义两个极端颜色,根据函数值比例做线性插值,比如从蓝色过渡到红色:
// 先定义两个基准颜色:最小值对应浅蓝,最大值对应浅红 ofColor colorMin = ofColor(0, 128, 255); ofColor colorMax = ofColor(255, 64, 64); // 把函数值映射到0-1的比例值 float colorRatio = ofMap(funcValue, minVal, maxVal, 0.0f, 1.0f, true); // 线性插值得到最终颜色 ofColor currentColor = colorMin.getLerped(colorMax, colorRatio); ofSetColor(currentColor);
3. 自定义分段颜色(规则明确)
如果需要按阈值区分颜色(比如低数值绿、中数值黄、高数值红),直接用条件判断:
if(funcValue < 20){ ofSetColor(0, 255, 0); // 绿色 }else if(funcValue < 60){ ofSetColor(255, 255, 0); // 黄色 }else{ ofSetColor(255, 0, 0); // 红色 }
完整整合示例代码
假设你已经把JSON里的函数值和对应坐标分别存在vector<float> funcValues和vector<ofVec2f> positions里,完整代码如下:
ofApp.h 声明变量
class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); vector<float> funcValues; vector<ofVec2f> positions; float minVal, maxVal; // 函数值的全局最小/最大值 };
ofApp.cpp 实现逻辑
//-------------------------------------------------------------- void ofApp::setup(){ // 这里假设你已经完成JSON读取,把数据存入funcValues和positions // 统计函数值的最小/最大值(动态数据建议每次刷新后重新计算) minVal = *min_element(funcValues.begin(), funcValues.end()); maxVal = *max_element(funcValues.begin(), funcValues.end()); } //-------------------------------------------------------------- void ofApp::update(){ } //-------------------------------------------------------------- void ofApp::draw(){ ofBackground(255); // 白色背景 for(int i=0; i<funcValues.size(); i++){ float val = funcValues[i]; ofVec2f pos = positions[i]; // 计算半径 float radius = ofMap(val, minVal, maxVal, 5, 50, true); // 计算渐变颜色 ofColor colorMin = ofColor(0, 128, 255); ofColor colorMax = ofColor(255, 64, 64); float ratio = ofMap(val, minVal, maxVal, 0.0f, 1.0f, true); ofColor currentCol = colorMin.getLerped(colorMax, ratio); // 绘制圆形 ofSetColor(currentCol); ofDrawCircle(pos.x, pos.y, radius); } }
额外小提示
- 如果JSON数据是实时更新的,记得在数据刷新时重新计算
minVal和maxVal,避免映射失效 - 想要非线性的大小/颜色变化?可以给
ofMap()的结果套个数学函数,比如float radius = 5 + pow(ofMap(val, minVal, maxVal, 0, 1, true), 2) * 45;,让小值的半径变化更平缓,大值变化更明显 - 试试
ofNoFill()画空心圆,配合ofSetLineWidth()调整线条粗细,能实现完全不同的视觉效果
内容的提问来源于stack exchange,提问作者Akira
相关产品推荐
相关产品推荐

