Skip to content
This repository was archived by the owner on Mar 3, 2025. It is now read-only.

Commit ba2c12c

Browse files
committed
[Feat] Export Path
1 parent c32057c commit ba2c12c

File tree

8 files changed

+105
-6
lines changed

8 files changed

+105
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Adobe XD Flutter Code Generate - Plugin
2-
<a href="https://github.com/thize/xd-to-flutter/releases"><img src="https://img.shields.io/badge/Xd%20to%20Flutter-v3.1.1-blue"/></a>
2+
<a href="https://github.com/thize/xd-to-flutter/releases"><img src="https://img.shields.io/badge/Xd%20to%20Flutter-v3.2.0-blue"/></a>
33

44
⚠️ **If you encounter an issue or have any feedback which you think could improve Plugin, please open an issue [here](https://github.com/thize/xd-to-flutter/issues)**
55

main.js

100755100644
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,7 @@ module.exports = {
2020
TODO:
2121
! Android Adaptive icon
2222
! Mask
23-
! Grid
23+
! Repeat Grid
24+
! List View
25+
! Styled Widget
2426
*/

src/generate_path.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const scenegraph = require("scenegraph");
2+
const clipboard = require("clipboard");
3+
const { changeOutputUiText } = require("./ui/components/output_ui");
4+
const { formatDart } = require("./widgets/util/format_dart");
5+
const { fix } = require("./util");
6+
7+
function onTapGeneratePath() {
8+
const item = scenegraph.selection.items[0];
9+
const pathData = item.pathData;
10+
const lb = item.localBounds;
11+
const movs = [];
12+
const letters = new Set();
13+
pathData.split(' ').forEach((e) => {
14+
if (e.match(/^[A-Za-z]+$/)) {
15+
movs.push(new Mov(e));
16+
letters.add(e);
17+
} else {
18+
let value = parseFloat(e);
19+
movs[movs.length - 1].values.push(value);
20+
}
21+
});
22+
// var letterStr = '';
23+
// letters.forEach((letter) => {
24+
// letterStr += `${letter} - `;
25+
// });
26+
// console.log(`Types = ${letterStr}`);
27+
movs.forEach((e) => {
28+
for (var i = 0; i < e.values.length; i++) {
29+
e.values[i] = fix((e.values[i] - (i % 2 == 0 ? lb.x : lb.y)));
30+
}
31+
});
32+
let dartCode = `Path path = Path()`;
33+
movs.forEach((e) => {
34+
const t = e.type;
35+
const v = e.values;
36+
if (t == 'M') {
37+
// [x, y]
38+
dartCode += `..moveTo(${nmn(v[0])}, ${nmn(v[1])})`
39+
} else if (t == 'L') {
40+
// [x, y]
41+
dartCode += `..lineTo(${nmn(v[0])}, ${nmn(v[1])})`
42+
} else if (t == 'C') {
43+
// [x1, y1, x2, y2, x3, y3]
44+
dartCode += `..cubicTo(${nmn(v[0])}, ${nmn(v[1])}, ${nmn(v[2])}, ${nmn(v[3])}, ${nmn(v[4])}, ${nmn(v[5])})`
45+
}
46+
});
47+
changeOutputUiText('Success');
48+
dartCode = formatDart(dartCode + ';');
49+
// console.log(`dartCode = ${dartCode}`);
50+
clipboard.copyText(dartCode);
51+
}
52+
53+
exports.onTapGeneratePath = onTapGeneratePath;
54+
55+
function nmn(value) {
56+
const element = document.getElementById('numbersMethodName');
57+
let methodName = element != null ? element.value : element;
58+
methodName = methodName ? methodName : '';
59+
if (methodName == '') return value;
60+
return `${methodName}(${value})`;
61+
}
62+
63+
class Mov {
64+
constructor(type) {
65+
this.values = [];
66+
this.type = type;
67+
}
68+
}

src/ui/components/export_buttons_ui.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ function exportButtonsUi() {
88
const components = buildRadio('Components');
99
const textStyles = buildRadio('TextStyles');
1010
const switchs = artboards + components + '<br>' + colors + textStyles;
11-
12-
const exportContent = title + exportSelectionButton() + exportSingleColorButton();
11+
const exportContent = title + exportSelectionButton() + exportSingleColorButton() + exportPathButton();
1312
const exportAllContent = titleAll + switchs + exportAllButton();
1413
return exportContent + '<hr>' + exportAllContent;
1514
}
@@ -29,6 +28,10 @@ function exportSelectionButton() {
2928
return buttonUi('selectionButton', 'Selected Item', false);
3029
}
3130

31+
function exportPathButton() {
32+
return buttonUi('pathButton', 'Selected Path', false);
33+
}
34+
3235
function exportSingleColorButton() {
3336
return buttonUi('singleColorButton', 'Selected Item Color', false);
3437
}

src/ui/main_panel_ui.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const { exportButtonsUi, exportIconButtons } = require("./components/export_butt
77
const { exportWithCheckBoxsUi } = require("./components/export_with_checkboxs_ui");
88
const { getFolderPath, changeProjectFolder } = require('../project_folder');
99
const { onTapGenerate } = require("../generate");
10+
const { onTapGeneratePath } = require("../generate_path");
1011
const { exportAppIcon } = require("../icon/functions");
1112
const { numbersMethodName } = require("./components/numbers_method_name");
1213
const { exportColor } = require("../color");
@@ -39,15 +40,19 @@ function show(event) {
3940

4041
let oldItemsLengh;
4142
function update() {
43+
4244
const items = scenegraph.selection.items;
4345
const singleColorButton = document.getElementById('singleColorButton');
4446
const isToActiveSingleColorButton = items.length == 1 && (items[0].children.length == 0 || items[0].constructor.name == 'Artboard');
4547
_changeButtonState(singleColorButton, isToActiveSingleColorButton);
4648
const selectionButton = document.getElementById('selectionButton');
49+
const pathButton = document.getElementById('pathButton');
4750
const iosIconButton = document.getElementById('iosIconButton');
4851
const androidIconButton = document.getElementById('androidIconButton');
4952
const isToActiveSelectionButton = items.length > 0;
5053
_changeButtonState(selectionButton, isToActiveSelectionButton);
54+
const isToActivePathButton = items.length == 1 && items[0].constructor.name == 'Path';
55+
_changeButtonState(pathButton, isToActivePathButton);
5156
const isToActiveIosIconButton = items.length == 1;
5257
_changeButtonState(iosIconButton, isToActiveIosIconButton);
5358
const isToActiveAndroidIconButton = items.length == 1;
@@ -72,6 +77,12 @@ function buildTaps() {
7277
}, function () {
7378
changeOutputUiText(`Select something`, 'red');
7479
});
80+
let pathButton = document.getElementById('pathButton');
81+
pathButton.onclick = _checkActive(pathButton, function () {
82+
onTapGeneratePath();
83+
}, function () {
84+
changeOutputUiText(`Select one path`, 'red');
85+
});
7586
let exportAllButton = document.getElementById('exportAllButton');
7687
exportAllButton.onclick = _checkActive(exportAllButton, function () {
7788
let exportAllRadio = document.querySelector('input[name="exportAllRadio"]:checked');

src/util.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ function _isSvgLine(item) {
2323

2424
function isSvgFolder(item) {
2525
let onlySvg = true;
26+
if (item.name.includes('svg_')) return onlySvg;
2627
item.children.forEach(child => {
2728
if (onlySvg) {
2829
// if (child instanceof Group) {
@@ -179,7 +180,6 @@ function applyRegex(str) {
179180
index++;
180181
}
181182
let fix = str.substring(ini, end);
182-
console.log('fix height');
183183
fix = fix.replace(new RegExp(`height: ${methodName}\(.*\)`, 'gm'), (value) => {
184184
return value.replace(`${methodName}(`, '').replace(')', '');
185185
});

src/widgets/svg.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,27 @@ class SvgWidget {
1515

1616
toDart() {
1717
const node = this.xdNode;
18+
if (node.name.includes('svg_')) return this.assetSvg();
1819
const path = new Path(node);
1920
path.shapes = this.shapes;
2021
return path.toString();
2122
}
2223

24+
assetSvg() {
25+
const node = this.xdNode;
26+
let height = node.height;
27+
height = height != null ? height : node.localBounds.height;
28+
height = height == 0 ? 1 : height;
29+
let width = node.width;
30+
width = width != null ? width : node.localBounds.width;
31+
width = width == 0 ? 1 : width;
32+
return `SvgPicture.asset(
33+
//TODO: ${node.name}
34+
'assets/${node.name.replace('svg_', '')}.svg',
35+
width: ${width},
36+
height: ${height},
37+
)`;
38+
}
2339

2440
addShapesFromGroup(xdNode) {
2541
xdNode.children.forEach(child => {

src/widgets/util/xd_alignment_to_dart_alignment.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ function xdAlignmentToDartAlignment(x, y) {
77
const align = `Alignment(${dx},${dy})`;
88
const dif = Math.abs(dx - dy);
99
if(dif < 0.02) return 'Alignment.center';
10-
console.log(`dif = ${dif}`);
1110
return nameAlignment[align] ? nameAlignment[align] : align;
1211
}
1312

0 commit comments

Comments
 (0)