如何将Adobe Illustrator贝塞尔坐标导入Processing的bezier()函数?
我之前做过类似的字体动画项目,刚好踩过这些坑,给你梳理几个靠谱的解决方案:
解决方案:从AI导出贝塞尔曲线数据到Processing实现动画
一、先搞定AI端的完整贝塞尔数据导出
Adobe Point Exporter确实只能导出锚点坐标,漏掉了关键的曲线控制点信息,咱们可以用AI的内置JavaScript脚本来导出完整数据,步骤如下:
- 打开你的AI字体文件,选择
文件 > 脚本 > 其他脚本,新建一个.jsx文件,粘贴下面的代码:
// AI脚本:导出路径的贝塞尔锚点及控制点数据 var doc = app.activeDocument; var output = []; for (var i = 0; i < doc.pathItems.length; i++) { var path = doc.pathItems[i]; var pathData = { name: path.name, points: [] }; for (var j = 0; j < path.pathPoints.length; j++) { var pt = path.pathPoints[j]; pathData.points.push({ anchor: {x: pt.anchor[0], y: pt.anchor[1]}, leftDir: {x: pt.leftDirection[0], y: pt.leftDirection[1]}, rightDir: {x: pt.rightDirection[0], y: pt.rightDirection[1]}, isSmooth: pt.smooth }); } output.push(pathData); } // 将数据导出为JSON文件 var saveFile = File.saveDialog("保存贝塞尔数据", "JSON files (*.json)"); if (saveFile) { var writer = new File(saveFile); writer.open("w"); writer.write(JSON.stringify(output)); writer.close(); alert("数据导出成功!"); }
- 运行脚本后,会生成一个包含所有锚点、左右控制点的JSON文件,完美满足Processing的需求。
二、Processing中解析数据并使用bezier()绘制
拿到JSON文件后,咱们可以用Processing的JSONObject来读取数据,然后把AI的路径转换成bezier()需要的四段式坐标(起点、控制点1、控制点2、终点)。注意AI的y轴是向上的,Processing是向下的,记得做坐标翻转:
import processing.data.*; JSONObject fontData; ArrayList<BezierSegment> segments; void setup() { size(800, 600); fontData = loadJSONObject("font_data.json"); segments = new ArrayList<BezierSegment>(); // 解析JSON中的路径点,转换为bezier段 JSONArray paths = fontData.getJSONArray("output"); for (int i = 0; i < paths.size(); i++) { JSONObject path = paths.getJSONObject(i); JSONArray points = path.getJSONArray("points"); for (int j = 0; j < points.size() - 1; j++) { JSONObject currPt = points.getJSONObject(j); JSONObject nextPt = points.getJSONObject(j+1); // AI坐标转Processing坐标(翻转y轴) float startX = currPt.getJSONObject("anchor").getFloat("x"); float startY = height - currPt.getJSONObject("anchor").getFloat("y"); float ctrl1X = currPt.getJSONObject("rightDir").getFloat("x"); float ctrl1Y = height - currPt.getJSONObject("rightDir").getFloat("y"); float ctrl2X = nextPt.getJSONObject("leftDir").getFloat("x"); float ctrl2Y = height - nextPt.getJSONObject("leftDir").getFloat("y"); float endX = nextPt.getJSONObject("anchor").getFloat("x"); float endY = height - nextPt.getJSONObject("anchor").getFloat("y"); segments.add(new BezierSegment(startX, startY, ctrl1X, ctrl1Y, ctrl2X, ctrl2Y, endX, endY)); } } } void draw() { background(255); stroke(0); noFill(); // 遍历所有bezier段,绘制并做动画处理(这里示例是控制点偏移) for (BezierSegment seg : segments) { // 给控制点加个简单的正弦动画 float animOffset = sin(frameCount * 0.02) * 10; bezier(seg.startX, seg.startY, seg.ctrl1X + animOffset, seg.ctrl1Y + animOffset, seg.ctrl2X - animOffset, seg.ctrl2Y - animOffset, seg.endX, seg.endY); } } // 自定义类存储bezier段数据 class BezierSegment { float startX, startY; float ctrl1X, ctrl1Y; float ctrl2X, ctrl2Y; float endX, endY; BezierSegment(float sx, float sy, float c1x, float c1y, float c2x, float c2y, float ex, float ey) { startX = sx; startY = sy; ctrl1X = c1x; ctrl1Y = c1y; ctrl2X = c2x; ctrl2Y = c2y; endX = ex; endY = ey; } }
三、用Geomerative库简化流程
如果你想用Geomerative,其实不需要手动导出坐标——直接把AI的字体路径导出为SVG格式(AI中选文件 > 导出 > SVG,注意选择SVG 1.1,不要勾选“压缩”),然后用Geomerative加载并获取贝塞尔数据:
import geomerative.*; RShape shape; void setup() { size(800, 600); RG.init(this); // 加载SVG文件(确保SVG和Processing sketch在同一文件夹) shape = RG.loadShape("font_path.svg"); // 关闭自动绘制,方便手动操作每个贝塞尔段 RG.setPolygonizer(RG.UNIFORM); } void draw() { background(255); stroke(0); noFill(); // 遍历每个路径的贝塞尔段 for (int i = 0; i < shape.countPaths(); i++) { RPath path = shape.getPath(i); for (int j = 0; j < path.countSegments(); j++) { RSegment seg = path.getSegment(j); if (seg.isBezier()) { RBezier bez = seg.toBezier(); // 获取四个控制点,同样做坐标翻转 float sx = bez.point1.x; float sy = height - bez.point1.y; float c1x = bez.point2.x; float c1y = height - bez.point2.y; float c2x = bez.point3.x; float c2y = height - bez.point3.y; float ex = bez.point4.x; float ey = height - bez.point4.y; // 动画处理示例:随机偏移锚点 float anim = sin(frameCount * 0.01 + j) * 5; bezier(sx + anim, sy + anim, c1x, c1y, c2x, c2y, ex - anim, ey - anim); } } } }
这个方法更省心,Geomerative会帮你解析SVG里的所有贝塞尔信息,你只需要专注于动画逻辑就行。
内容的提问来源于stack exchange,提问作者Koysun




