国庆节了,抖音上各种国庆头像生成器,有的在 Web 端使用,有的是使用微信小程序进行制作,这事咱 Processing 也能做嘛。说撸就撸一个,简单粗暴。
昨晚没写完,中午接着写完了下,代码已经开源。
开源地址:https://github.com/xiaocai-laoniao/Processing100DaysSketch
代码在 Day_027 文件夹中,已经加了详细的注释,如果大家有不明白的,可以留言~
实现思路
封面图的获取
首先从网上找几个大家常用的国庆头像封面图,下载下来,保存到 data 文件夹中,这里依次命名为 header1.png ~ header7.png, 一共 7 张 png 图。
功能划分
头像和封面图合成显示
第一部分头像和封面图合成预览区域,这块使用PGraphics
来解决,可以将之看成一个单独的图层,方便我们只将合成头像部分导出保存。
// 头像图层,包含头像和头像的框图封面
PGraphics avatarLayer;
void draw() {
background(200);
// 头像图层的绘制部分
avatarLayer.beginDraw();
avatarLayer.pushMatrix();
avatarLayer.background(200);
if (avatarImage != null) {
// 绘制头像
avatarLayer.image(avatarImage, 0, 0);
} else {
// 如果没选图像,默认一个矩形填充
avatarLayer.fill(100);
avatarLayer.noStroke();
avatarLayer.rect(0, 0, avatarSize, avatarSize);
}
// 获取当前选中的封面图数据
PImage currentSelectedCoverImage = coverImages[currentSelectedCoverIndex];
// 绘制头像封面
avatarLayer.image(currentSelectedCoverImage, 0, 0);
avatarLayer.popMatrix();
avatarLayer.endDraw();
...
}
头像的选择
这里涉及到一个文件选择器的使用,API 为selectInput
。
函数的用法为selectInput(prompt, callback)
,第一个参数是提示语,第二个参数是一个回调函数名称,也就是选择结束后要执行的函数。看下方代码,我们的回调函数为fileSelected
。
void keyPressed() {
if (key == 'c' || key == 'C') {
selectInput("选择头像文件(png/jpg/jpeg格式)", "fileSelected");
} else if (key == 's' || key == 'S') {
avatarLayer.save("NationalDayAvatar-" frameCount ".png");
println("保存头像成功");
}
}
void fileSelected(File selection) {
if (selection == null) {
println("[文件选择] 取消文件选择");
} else {
imageChoosedPath = selection.getAbsolutePath();
println("[文件选择] 选择文件 " imageChoosedPath);
String[] paths = split(imageChoosedPath, "/");
String fileName = paths[paths.length - 1];
// 检测下文件后缀是否是png/jpg/jpeg等格式
Boolean isValidImage = checkFileExtension(fileName);
if (isValidImage) {
// 加载读取头像文件
avatarImage = loadImage(imageChoosedPath);
// 进行resize
avatarImage.resize(avatarSize, avatarSize);
} else {
println("[文件选择] 文件选择非 png/jpg/jpeg 格式");
}
}
}
封面图预览的切换选择
思路是将封面图封装起来,用isSelected
标记是否选中,在绘制的时候加上红色边框。
// 绘制部分
void display() {
pushMatrix();
// 选中的情况下,在图像后面画一个框
if (this.isSelected) {
stroke(255, 0, 0);
strokeWeight(4);
noFill();
rect(this.x - 2, this.y - 2, coverSize 4, coverSize 4);
}
// 预览图显示
image(coverImg, this.x, this.y);
popMatrix();
}
切换的话,需要检测鼠标按压时是否在某个封面预览图区域里面,如果在,则标记为选中,同时取消上一个选中的封面。
代码语言:javascript复制void mousePressed() {
// 检测鼠标按压区域,是否在某个模版预览区域
for (int i = 0; i < covers.length; i ) {
Cover cover = covers[i];
if (cover.isIn()) {
covers[currentSelectedCoverIndex].isSelected = false;
currentSelectedCoverIndex = i;
cover.isSelected = true;
break;
}
}
}
整个思路比较简单,目前不支持头像选择后的缩放、裁剪等,所以建议选择一个正常形的头像,防止加载resize
之后发生变形。
最后
小菜祝大家国庆节快乐!
小菜与老鸟后期会不定期更新一些 Processing 绘制的代码思路分析,欢迎关注不迷路。
如果有收获,能一键三连么?