/
IllustratorToSwiftUIShape.js
316 lines (245 loc) · 9.81 KB
/
IllustratorToSwiftUIShape.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//
// IllustratorToSwiftUIShape.js
//
// Created by Jacob Brown on 10/21/20.
//
// -----------------------------------------------------------------------------
// --- Helpers for Writing to File ---------------------------------------------
// -----------------------------------------------------------------------------
var newLine = "\n";
var tab = "\t";
var tab2 = "\t\t";
var tab3 = "\t\t\t";
var tab4 = "\t\t\t\t";
var tab5 = "\t\t\t\t\t";
// -----------------------------------------------------------------------------
// --- Main --------------------------------------------------------------------
// -----------------------------------------------------------------------------
try {
// Create a text file for writing out the SwiftUI path data
var file = File.saveDialog('Convert Illustrator paths to SwiftUI shapes.', 'Path:*.swift');
file.open('w');
// Define some helpers
var aiSelection = app.activeDocument.selection
var aiSelectionLength = aiSelection.length
// Make sure an object is selected
if (aiSelectionLength == 0) {
throw "At least one path must be selected before running the script."
}
// Make sure only paths are selected
for(j=0; j<aiSelectionLength; j++) {
if (aiSelection[j].typename !== "PathItem") {
throw "Only paths may be selected. If any paths are grouped, ungroup them and try again."
};
};
writeHeaderToFile()
// Write out the SwiftUI view
writeViewToFile(aiSelectionLength);
// Get size of entire selection
app.executeMenuCommand("group");
var tempSelection = app.activeDocument.selection;
var maxWidth = Math.round(tempSelection[0].width*100)/100;
var maxHeight = Math.round(tempSelection[0].height*100)/100;
app.executeMenuCommand("ungroup");
// Write out the shape properties (e.g., size)
writeShapePropertiesToFile(maxWidth, maxHeight);
// Write out each of the paths
for(j=0; j<aiSelectionLength; j++) {
writeShapeElementsToFile(j, aiSelection[j]);
};
// Write out the preview block to the file
writePreviewToFile();
// Finish up
alert("Finished! File has been saved to your selected directory.");
} catch(e) {
// Alert user of the error
alert(e);
} finally {
// Finish up
file.close();
}
// -----------------------------------------------------------------------------
// --- Write Header to File ----------------------------------------------------
// -----------------------------------------------------------------------------
function writeHeaderToFile() {
file.write(
"//" + newLine +
"// ShapeView.swift" + newLine +
"//" + newLine +
"// Made Using SwiftyIllustrator" + newLine +
"// https://github.com/downtownjakebrown/SwiftyIllustrator.git" + newLine +
"//" + newLine + newLine +
"import SwiftUI" + newLine + newLine
);
}
// -----------------------------------------------------------------------------
// --- Write View To File in SwiftUI Format ------------------------------------
// -----------------------------------------------------------------------------
function writeViewToFile(itemCount) {
file.write(
"// MARK: - ShapeView" + newLine +
"struct ShapeView: View {" + newLine + newLine +
tab + "var body: some View {" + newLine +
tab2 + "ZStack {" + newLine
);
for (s=itemCount; s>0; s--) {
file.write(
tab3 + "ShapeElement" + s + "().stroke(lineWidth: 1.0)" + newLine
);
};
file.write(
tab2 + "}" + newLine +
tab + "}" + newLine +
"}" + newLine + newLine
);
}
// -----------------------------------------------------------------------------
// --- Write Shape Properties To File in SwiftUI Format ------------------------
// -----------------------------------------------------------------------------
function writeShapePropertiesToFile(maxWidth, maxHeight) {
file.write(
"// MARK: - ShapeProperties" + newLine +
"struct ShapeProperties {" + newLine +
tab + "static let size = CGSize(width: " + maxWidth + ", height: " + maxHeight + ")" + newLine +
"}" + newLine + newLine
);
};
// -----------------------------------------------------------------------------
// --- Write Path To File in SwiftUI Format ------------------------------------
// -----------------------------------------------------------------------------
function writeShapeElementsToFile(itemNumber, item) {
var points = item.pathPoints;
var length = points.length;
var shapeNumber = itemNumber + 1
// Write header
file.write(
"// MARK: - ShapeElement" + shapeNumber + newLine +
"fileprivate struct ShapeElement" + shapeNumber + ": Shape {" + newLine + newLine
);
// Write out max dimensions
file.write(
tab + "private let baseSize: CGSize = ShapeProperties.size" + newLine + newLine
);
// Write out openings
file.write(
tab + "func path(in rect: CGRect) -> Path {" + newLine + newLine +
tab2 + "let basePath = Path { path in" + newLine + newLine
);
// Write out anchor points
for(i=0; i<=length; i++) {
if (i==0) {
var anchorX = Math.round(item.pathPoints[0].anchor[0]*100)/100;
var anchorY = -Math.round(item.pathPoints[0].anchor[1]*100)/100;
file.write(
tab3 + "let anchorPoints = [" + newLine +
tab4 + "CGPoint(x: "+anchorX+", y: "+anchorY+")," + newLine
);
} else if (i < length) {
var anchorX = Math.round(item.pathPoints[i].anchor[0]*100)/100;
var anchorY = -Math.round(item.pathPoints[i].anchor[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+anchorX+", y: "+anchorY+")," + newLine
);
} else {
var anchorX = Math.round(item.pathPoints[0].anchor[0]*100)/100;
var anchorY = -Math.round(item.pathPoints[0].anchor[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+anchorX+", y: "+anchorY+")" + newLine +
tab3 + "]" + newLine + newLine
);
};
};
// Write out control1 points
for(i=0; i<length; i++) {
if (i==0) {
var control1X = Math.round(item.pathPoints[0].rightDirection[0]*100)/100;
var control1Y = -Math.round(item.pathPoints[0].rightDirection[1]*100)/100;
file.write(
tab3 + "let control1 = [" + newLine +
tab4 + "CGPoint(x: "+control1X+", y: "+control1Y+")," + newLine
);
} else if (i < (length-1)) {
var control1X = Math.round(item.pathPoints[i].rightDirection[0]*100)/100;
var control1Y = -Math.round(item.pathPoints[i].rightDirection[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+control1X+", y: "+control1Y+")," + newLine
);
} else {
var control1X = Math.round(item.pathPoints[i].rightDirection[0]*100)/100;
var control1Y = -Math.round(item.pathPoints[i].rightDirection[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+control1X+", y: "+control1Y+")" + newLine +
tab3 + "]" + newLine + newLine
);
};
};
// Write out control2 points
for(i=1; i<=length; i++) {
if (i==1) {
var control2X = Math.round(item.pathPoints[1].leftDirection[0]*100)/100;
var control2Y = -Math.round(item.pathPoints[1].leftDirection[1]*100)/100;
file.write(
tab3 + "let control2 = [" + newLine +
tab4 + "CGPoint(x: "+control2X+", y: "+control2Y+")," + newLine
);
} else if (i < (length)) {
var control2X = Math.round(item.pathPoints[i].leftDirection[0]*100)/100;
var control2Y = -Math.round(item.pathPoints[i].leftDirection[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+control2X+", y: "+control2Y+")," + newLine
);
} else {
var control2X = Math.round(item.pathPoints[0].leftDirection[0]*100)/100;
var control2Y = -Math.round(item.pathPoints[0].leftDirection[1]*100)/100;
file.write(
tab4 + "CGPoint(x: "+control2X+", y: "+control2Y+")" + newLine +
tab3 + "]" + newLine + newLine
);
};
};
// Create the path using above-defined points
file.write(
tab3 + "path.move(to: anchorPoints[0])" + newLine
);
for(i=0; i<length; i++) {
file.write(
tab3 + "path.addCurve(to: anchorPoints["+(i+1)+"], control1: control1["+i+"], control2: control2["+i+"])" + newLine
);
};
file.write(
tab3 + "path.closeSubpath()" + newLine + newLine +
tab2 + "}" + newLine + newLine +
tab2 + "let rectWidth = rect.size.width" + newLine +
tab2 + "let rectHeight = rect.size.height" + newLine + newLine +
tab2 + "let scaleFactor: CGFloat" + newLine +
tab2 + "let widthRatio = rectWidth/baseSize.width" + newLine +
tab2 + "let heightRatio = rectHeight/baseSize.height" + newLine +
tab2 + "if widthRatio < heightRatio {" + newLine +
tab3 + "scaleFactor = widthRatio" + newLine +
tab2 + "} else {" + newLine +
tab3 + "scaleFactor = heightRatio" + newLine +
tab2 + "}" + newLine + newLine +
tab2 + "let scaleTransform = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)" + newLine +
tab2 + "let moveTransform = CGAffineTransform(translationX: 0.5*rectWidth, y: 0.5*rectHeight)" + newLine +
tab2 + "let combinedTransform = scaleTransform.concatenating(moveTransform)" + newLine + newLine +
tab2 + "let modifiedPath = basePath.applying(combinedTransform)" + newLine +
tab2 + "return modifiedPath" + newLine + newLine +
tab + "}" + newLine +
"}" + newLine + newLine
);
};
// -----------------------------------------------------------------------------
// --- Write Preview Block File in SwiftUI Format ------------------------------
// -----------------------------------------------------------------------------
function writePreviewToFile() {
file.write(
"// MARK: - Preview" + newLine +
"#if DEBUG" + newLine +
"struct ShapeView_Previews: PreviewProvider {" + newLine +
tab + "static var previews: some View {" + newLine +
tab2 + "ShapeView()" + newLine +
tab + "}" + newLine +
"}" + newLine +
"#endif" + newLine
)
}