forked from adamplouff/scriptui-battlestyle
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathConvert_Illustrator_To_Arrays.html
More file actions
288 lines (236 loc) · 12.4 KB
/
Convert_Illustrator_To_Arrays.html
File metadata and controls
288 lines (236 loc) · 12.4 KB
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Converter</title>
<style>
body { padding: 5px 15px; }
h1, h2, p, li {
font-size: 14px;
font-family: Arial, sans-serif;
line-height: 130%;
}
h1 { font-size: 24px; }
h2 { font-size: 20px; }
div {
display: inline-block;
padding: 20px;
border: solid 1px #CCC;
width: 800px;
box-sizing: border-box;
}
textarea {
width: 794px;
height: 250px;
}
#input textarea {
width: 752px;
height: 100px;
}
li + li { margin-top: 10px; }
code {
font-size: 12px;
padding: 2px 5px;
background-color: #e7f3f7;
border-radius: 4px;
color: #1395ce;
}
.buttonMain {
padding: 15px;
}
#credit { font-size: 12px; }
a { color: #1395ce; }
</style>
</head>
<body>
<h1 id="color-output">Convert SVG code from Illustrator to vector and color arrays</h1>
<div id="input">
<p><label for="svg-input">Enter the copied SVG code from Adobe Illustrator:</label></p>
<p><textarea id="svg-input" placeholder="Paste SVG code from Illustrator here"></textarea></p>
<p><button onclick="getArrayOfShapes(); getArrayOfColors()" class="buttonMain">Convert to Arrays</button> <button onclick="clearFields()">Clear</button></p>
</div>
<h2>Vector Path Array <button onclick="copyToClipboard('arraysVector')">Copy to clipboard</button></h2>
<p><textarea id="arraysVector" placeholder="Vector path array will appear here."></textarea></p>
<h2>Color Array <button onclick="copyToClipboard('arraysColor')">Copy to clipboard</button></h2>
<p><textarea id="arraysColor" placeholder="Color array will appear here."></textarea></p>
<div id="instructions">
<h2>Instructions:</h2>
<p>This tool is for converting copied SVG paths from Adobe Illustrator into arrays for use in the <a href="https://github.com/AutomotionTools/battleButtons" title="BattleButtons on GitHub">BattleButtons toolkit</a>.</p>
<ol>
<li>In Illustrator, ensure that your icon is made up of straight lines only (BattleButtons doesn't support curved vectors), with fill colors only (no strokes).</li>
<li>If the icon should have padding around it, draw a rectangle around the bounds of your icon (using the Rectangle Tool). This will be excluded from the arrays, but ensures that the padding is observed in the co-ordinates.<br />
(If the padding isn't observed after doing this, ensure that this rectangle has a fill color before copying.)</li>
<li>Select the icon and the padding rectangle, and then copy.</li>
<li>Paste the resulting code into the SVG input field above.</li>
<li>Copy the generated vector path array to the variable for your button: <code>var icon = PASTE_HERE;</code></li>
<li>Copy the generated color array to the variable for your button's colors: <code>var icon_Color = PASTE_HERE;</code></li>
</ol>
<h2>Common issues</h2>
<ul>
<li>If your illustration contains any compound paths, they will not get converted. Ensure that you release these paths before copying.</li>
<li>Each of the shapes within your illustration must be a single path – this means that you can't have cut-outs (for example, the center of the letter 'O'). To resolve this, you can split your shape into multiple paths, or create a hairline gap between the centre and edge of the shape.</li>
<li>If you have any squares or rectangles in your shape, Illustrator will process these differently and they won't get converted. You can resolve this by adding an additional vertex point anywhere along the shape's path.</li>
<li>Ensure that the bottom-most rectangle in your icon selection is a 'Rectangle' (drawn with the Rectangle Tool), rather than a rectangular path. The correct type will have a highlighted center point when selected in Illustrator.</li>
</ul>
<h2>Limitations:</h2>
<ul>
<li>If all paths copied from Illustrator are pure black (i.e. using the color code <code>#000000</code>), this tool will quietly fail. The current workaround is to re-color one or all of these paths, and then replace the value in the generated color array.</li>
</ul>
</div>
<p id="credit">© <a href="https://rob-barrett.com" title="Rob Barrett Design">Rob Barrett</a></p>
<script>
let arrayOfClasses = [];
function getArrayOfShapes() {
let inputString = document.getElementById('svg-input').value;
inputString = removeBreaksAndSpaces(inputString);
// Regex to match class and points attributes for polygons
const regex = /<\s*(\w+)\s+class="(cls-\d+)"[^>]*\s+points="([^"]+)"/g;
// Find all matches
let matches;
let resultClasses = [];
let resultPoints = [];
// Now, extract class and points from the string
while ((matches = regex.exec(inputString)) !== null) {
// Only process polygons (because <rect> doesn't have points)
if (matches[1] === "polygon") {
resultClasses.push(matches[2]);
resultPoints.push(matches[3]);
}
}
arrayOfClasses = resultClasses;
let arrayOfShapes = resultPoints.join("\",\n\t\"");
arrayOfShapes = 'vecToPoints([\n\t"' + arrayOfShapes + '"\n\t]);';
document.getElementById('arraysVector').value = arrayOfShapes;
};
function removeBreaksAndSpaces(str) {
// Split by line-break into an array
str = str.split(/\r?\n|\r|\n/g);
// Trim whitespace from each array item
for (let i = 0; i < str.length; i++) {
str[i] = str[i].trim();
}
// Rejoin the array
str = str.join("");
return str;
}
function getArrayOfColors() {
let inputString = document.getElementById('svg-input').value;
inputString = removeBreaksAndSpaces(inputString);
// Remove any spaces before "{fill" or "{opacity" – this is required for Windows
inputString = inputString.replace(/ {fill/g, '{fill');
inputString = inputString.replace(/ {opacity/g, '{opacity');
// Placeholder for array
let arrayOfColors = [];
// Regex to match the content inside the <style> tag
const styleRegex = /<style.*?>(.*?)<\/style>/s;
// Apply the regex to the input string
const matches = inputString.match(styleRegex);
// Extract the content of the <style> tag (matches[1] is the captured content)
let styleContent = matches[1];
// Split styleContent by ".c" (can't split by "." because of opacities)
styleContent = styleContent.split(".c");
// Remove the first array item
styleContent.shift();
// Add "c" to the start of each item
for (let i = styleContent.length - 1; i >= 0; i--) {
styleContent[i] = "c" + styleContent[i];
}
// Loop backwards through the array. If an item ends in a comma, replace that comma with the {} from the next item
for (let i = styleContent.length - 1; i >= 0; i--) {
let item = styleContent[i];
let lastCharacter = item.slice(-1);
if (lastCharacter == ",") {
// Remove the comma
item = item.slice(0, -1);
// Get the color/opacity info from the next item
let nextItem = styleContent[i + 1];
let nextInfo = nextItem.split("{");
nextInfo = "{" + nextInfo[1];
// Add the next item's color/opacity info to this item
item += nextInfo;
styleContent[i] = item;
}
}
// Sort the array alphanumerically
styleContent.sort();
// Loop through the array. Remove the ";}" string, then split each item by the "{" character
for (let i = styleContent.length - 1; i >= 0; i--) {
let item = styleContent[i];
item = item.slice(0, -2);
item = item.split("{");
styleContent[i] = item;
}
// Loop through the array backwards. If the [0]-index matches that of the next item, append the [1]-index with that of the next item, then remove the next item
for (let i = styleContent.length - 2; i >= 0; i--) { // Start from the penultimate item
let item = styleContent[i];
let itemNext = styleContent[i + 1];
if (item[0] == itemNext[0]) {
item[1] += "," + itemNext[1]
styleContent.splice(i + 1, 1); // Remove the next item
}
styleContent[i] = item;
}
// Loop through the array. Split the [1]-index by "," or ";"
for (let i = styleContent.length - 1; i >= 0; i--) {
let item = styleContent[i];
let contents = item[1];
contents = contents.split(/[;,]/g);
// Remove "fill:" from the first item of the contents
contents[0] = contents[0].slice(5);
// Convert named colors to hex values
contents[0] = standardize_color(contents[0]);
// Remove "opacity:" from the second item of the contents
if (contents.length > 1) contents[1] = contents[1].slice(8);
item[1] = contents;
styleContent[i] = item;
};
// Run through the arrayOfClasses and find the matching class in styleContent. When a match is found, add that style to arrayOfColors
arrayOfClasses.forEach(cls => {
// Find the corresponding style from styleContent
let match = styleContent.find(item => item[0] === cls);
if (match) {
let thisStyle = match[1];
if (thisStyle.length == 1) {
thisStyle = '"' + thisStyle[0].toUpperCase() + '"';
} else {
thisStyle = '["' + thisStyle[0].toUpperCase() + '", ' + thisStyle[1] + ']';
}
arrayOfColors.push(thisStyle);
}
});
// Loop through arrayOfColors. If all items match, keep only the first
let allItemsMatch = true;
for (let i = 0; i < arrayOfColors.length - 1; i++) {
let item = arrayOfColors[i];
let itemNext = arrayOfColors[i + 1];
if (item !== itemNext) allItemsMatch = false;
}
if (allItemsMatch) arrayOfColors = [arrayOfColors[0]];
arrayOfColors = "[" + arrayOfColors.join(", ") + "];";
document.getElementById('arraysColor').value = arrayOfColors;
}
// Function to convert a named color to its hex value
function standardize_color(str){
let ctx = document.createElement('canvas').getContext('2d');
ctx.fillStyle = str;
return ctx.fillStyle;
}
// Function to copy text to the clipboard
function copyToClipboard(input_id) {
var copyText = document.getElementById(input_id);
// Select the text field
copyText.select();
copyText.setSelectionRange(0, 99999); // For mobile devices
// Copy the text inside the text field
navigator.clipboard.writeText(copyText.value);
}
// Function to empty all textareas
function clearFields() {
document.getElementById('svg-input').value = "";
document.getElementById('arraysVector').value = "";
document.getElementById('arraysColor').value = "";
}
</script>
</body>
</html>