-
-
Notifications
You must be signed in to change notification settings - Fork 85
Home
In application development, especially in web development. We tend to create a design prototype to get an idea of what a feature would look like before the dev team starts implementing it. The goal of xLayers.app is to enable designers easily share their sketches with developers who can then benefit from the code generation feature of xlayers.app.
The core project features reside inside src/app/editor/viewer/lib/.
At the root of the library we can find several UI components such as SketchDropZone
, SketchSettingContainer
, SketchEditorContainer
, SketchContainer
and SketchTreeView
... These are simple components that compose the final editor UI.
The SketchContainer
component is responsible for listening to the input file emitted by SketchDropZone
.
sketch-dropzone.component.ts
@Component({
...
template: `
...
<button color="primary" class="mat-headline" mat-button (click)="openFileBrowser()">BROWSE FILES</button>
<sketch-select-demo-files [error]="selectedDemoFileError" (changed)="openSelectedDemoFile($event)"></sketch-select-demo-files>
...
`
...
})
export class SketchDropzoneComponent implements OnInit, OnChanges {
...
@Output() changed: EventEmitter<File> = new EventEmitter();
...
onFileChange(inputEvent: any | File) {
let file;
if (!inputEvent.target) {
file = inputEvent as File;
} else {
const files = inputEvent.target.files || inputEvent.dataTransfer.files;
if (!files.length) {
return;
}
file = files[0];
}
if (file.name.endsWith('.sketch')) {
this.changed.emit(file);
}
}
}
And then delegate the file to the SketchService for processing.
sketch-container.component.ts
@Component({
...
template: `
...
<sketch-dropzone (changed)="onFileSelected($event)"></sketch-dropzone>
...
`
...
})
export class SketchContainerComponent implements OnInit {
constructor(private service: SketchService, private store: Store) {}
...
ngOnInit() {
this.store.select(UiState.currentPage).subscribe(currentPage => {
this.currentPage = currentPage;
});
}
...
async onFileSelected(file: File) {
try {
this.data = await this.service.process(file);
this.store.dispatch(new CurrentFile(this.data));
} catch (e) {
console.error(e);
}
}
...
}
sketch.service.ts
...
async process(file: File) {
this._data = await this.sketch2Json(file);
this.parseColors(this._data.pages);
return this._data;
}
...
A Sketch (*.sketch) file an archive file with the following content:
.
+-- pages/
| *.json
+-- previews/
| +--preview.png
+-- meta.json
+-- user.json
The meta.json
file is the entrypoint of the file that describes the sketch project. And referencing all pages files present under the pages folder by their hash in the "pagesAndArtboards" key.
{
...
"pagesAndArtboards": {
"*": {
"name": "String",
"artboards": {}
}
},
...
}
The page file include a root object defining the page information and a recursive tree of layers providing a bunch of data and properties (position, styles, dimensions...) about the actual design produced by SketchApp.
{
"_class": "String",
...
"frame": {
"_class": "String",
"constrainProportions": "Boolean",
"height": "Number",
"width": "Number",
"x": "Number",
"y": "Number"
},
...
"style": {
"_class": "style",
...
},
"layers": [{
"_class": "group",
...
"layers": [{
...
}]
}]
...
}
The previously parsed sketch file is then dispatched by the UIState
(NGXS instance) and handled to by SketchContainer
and TreeView
components.
The SketchContainer
and TreeView
will use the same layer hierarchy as the sketch file to render the design in xlayers.app. The SketchContainer
renders the design as a visual and on the TreeView
renders the layers hierarchy, on the sidebar.
.
+-- SketchContainer
| +-- TreeViwer
| ...
| +-- SketchPage
| +-- SketchLayer
| +-- SketchLayer
| ...
// TODO