I am trying to find a pattern to convert Sketch shape points(json format) to svg path, as we know sketch files are just zip files, unzipping you will get json files. here are sample json codes
{
"_class": "triangle",
"do_objectID": "BE50CDBE-491C-4402-98EA-71E9C7B9F61B",
"booleanOperation": -1,
"frame": {
"_class": "rect",
"do_objectID": "0B39EF6D-9AD4-409B-85FA-D09B2B8A0692",
"constrainProportions": false,
"height": 56.86153846153846,
"width": 66,
"x": 0,
"y": 0
},
"isFixedToViewport": false,
"isFlippedHorizontal": false,
"isFlippedVertical": false,
"isLocked": false,
"isVisible": true,
"layerListExpandedType": 1,
"name": "Triangle",
"nameIsFixed": false,
"resizingConstraint": 63,
"resizingType": 0,
"rotation": 0,
"shouldBreakMaskChain": false,
"userInfo": {
"com.animaapp.stc-sketch-plugin": {
"kModelPropertiesKey": {}
}
},
"clippingMaskMode": 0,
"hasClippingMask": false,
"edited": false,
"isClosed": true,
"pointRadiusBehaviour": 1,
"points": [
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.49999999999999944, 0}",
"curveMode": 1,
"curveTo": "{0.49999999999999944, 0}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.49999999999999944, 0}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.99999999999999889, 1}",
"curveMode": 1,
"curveTo": "{0.99999999999999889, 1}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.99999999999999889, 1}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0, 1}",
"curveMode": 1,
"curveTo": "{0, 1}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0, 1}"
}
],
"isEquilateral": false
}
this gives a Triangle with its svg path code
<polygon id="Triangle" points="33 0 66 56.8615385 0 56.8615385"></polygon>
for my understanding getting 33(x value)
is done as follows, since above frame origin is at 0,0 (frame->x, frame->y)
i thought to get its actual position is to take frame->width
(since width corresponds to x axis) which is 66 times first x point in points, which is 0.49999999999999944
, resulting to (32.99999999 approx 33
), and first y point
taking frame->height(56.86153846153846 times the first y point in points which is 0)
resulting to the first point be 33 0
second point the same, to get x is taking frame->width(66)
times second x point in points which is 0.99999999
resulting to 66
, same with its corresponding y (56.86153846153846 times 1) which is 56.86153846153846
, resulting to second point be 66 56.86153846153846
goes the same to third point..
Starts confusing if frame->x and frame->y has numbers greater than 0
consider this..
{
"_class": "triangle",
"do_objectID": "BB3FB5DE-F0A8-4AAD-8009-14F908023F19",
"booleanOperation": -1,
"frame": {
"_class": "rect",
"do_objectID": "316A9A7C-D0BF-4D71-BC65-1A0301846F20",
"constrainProportions": true,
"height": 32.49230769230769,
"width": 37.56923076923076,
"x": 14.21538461538461,
"y": 22.33846153846153
},
"isFixedToViewport": false,
"isFlippedHorizontal": false,
"isFlippedVertical": false,
"isLocked": false,
"isVisible": true,
"layerListExpandedType": 1,
"name": "Triangle",
"nameIsFixed": false,
"resizingConstraint": 63,
"resizingType": 0,
"rotation": -180,
"shouldBreakMaskChain": false,
"userInfo": {
"com.animaapp.stc-sketch-plugin": {
"kModelPropertiesKey": {
"constraints": {
"scaleFactor": 1,
"model_version": 0.1,
"aspectRatio": {
"multiplier": 37.56923,
"enabled": 1,
"model_version": 0.1,
"modelID": "constraint_dd3b6146-988c-411d-94e1-cb5ec2a60bc8",
"model_class": "ADModelConstraint",
"constant": 32.49231
},
"modelID": "viewConstraints_7f13ceae-6706-4965-b3af-3cde627fd97c",
"model_class": "ADModelViewConstraints",
"automatic": 1
}
}
}
},
"clippingMaskMode": 0,
"hasClippingMask": false,
"edited": false,
"isClosed": true,
"pointRadiusBehaviour": 1,
"points": [
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.4999999999999995, 0}",
"curveMode": 1,
"curveTo": "{0.4999999999999995, 0}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.4999999999999995, 0}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.999999999999999, 1.0000000000000009}",
"curveMode": 1,
"curveTo": "{0.999999999999999, 1.0000000000000009}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.999999999999999, 1.0000000000000009}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0, 1.0000000000000009}",
"curveMode": 1,
"curveTo": "{0, 1.0000000000000009}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0, 1.0000000000000009}"
}
],
"isEquilateral": false
}
its corresponding svg path is
<polygon id="Triangle" transform="translate(33.000000, 38.584615) rotate(180.000000) translate(-33.000000, -38.584615) " points="33 22.3384615 51.7846154 54.8307692 14.2153846 54.8307692"></polygon>
Now if i do my math as above, i don't get points="33 22.3384615 51.7846154 54.8307692 14.2153846 54.8307692"
as above svg code shows. This is only for triangle, if is a custom shape path like facebook icon, it confuses alot!. Sample sketch logo,
its corresponding Sketch json code is as follows.
{
"_class": "group",
"do_objectID": "4AA67C64-14B8-433F-8569-9BF7BAEC2914",
"booleanOperation": -1,
"frame": {
"_class": "rect",
"do_objectID": "1FB80667-369B-4F79-9D8E-76ABD9065B12",
"constrainProportions": true,
"height": 50,
"width": 50,
"x": 0,
"y": 0
},
"isFixedToViewport": false,
"isFlippedHorizontal": false,
"isFlippedVertical": false,
"isLocked": false,
"isVisible": true,
"layerListExpandedType": 0,
"name": "Facebook",
"nameIsFixed": true,
"resizingConstraint": 63,
"resizingType": 0,
"rotation": 0,
"shouldBreakMaskChain": false,
"userInfo": {
"com.animaapp.stc-sketch-plugin": {
"kModelPropertiesKey": {
"constraints": {
"scaleFactor": 1,
"model_version": 0.1,
"aspectRatio": {
"constant": 50,
"enabled": 1,
"multiplier": 50,
"modelID": "constraint_c03c7307-1fe6-4ded-9d49-e35c2e25c117",
"model_class": "ADModelConstraint",
"model_version": 0.1
},
"modelID": "viewConstraints_b34c9514-3166-464d-a3dd-f968c4f6144b",
"model_class": "ADModelViewConstraints",
"automatic": 1
}
}
}
},
"clippingMaskMode": 0,
"hasClippingMask": false,
"hasClickThrough": false,
"layers": [
{
"_class": "oval",
"do_objectID": "DA55B46C-1069-46DC-AAD6-78DCC03F4B3C",
"booleanOperation": -1,
"frame": {
"_class": "rect",
"do_objectID": "58627B0B-C1B7-4C33-BF5C-2B0F6F0DBC8E",
"constrainProportions": true,
"height": 50,
"width": 50,
"x": 0,
"y": 0
},
"isFixedToViewport": false,
"isFlippedHorizontal": false,
"isFlippedVertical": false,
"isLocked": false,
"isVisible": true,
"layerListExpandedType": 0,
"name": "Oval",
"nameIsFixed": false,
"resizingConstraint": 63,
"resizingType": 0,
"rotation": 0,
"shouldBreakMaskChain": false,
"userInfo": {
"com.animaapp.stc-sketch-plugin": {
"kModelPropertiesKey": {
"constraints": {
"scaleFactor": 1,
"model_version": 0.1,
"aspectRatio": {
"constant": 32,
"enabled": 1,
"multiplier": 32,
"modelID": "constraint_5868769e-cc0b-4eec-a4af-d965ce1b6520",
"model_class": "ADModelConstraint",
"model_version": 0.1
},
"modelID": "viewConstraints_9d4aa04f-2445-427e-9182-b1ce723cefd2",
"model_class": "ADModelViewConstraints",
"automatic": 1
}
}
}
},
"clippingMaskMode": 0,
"hasClippingMask": false,
"edited": false,
"isClosed": true,
"pointRadiusBehaviour": 1,
"points": [
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.77614237490000004, 1}",
"curveMode": 2,
"curveTo": "{0.22385762510000001, 1}",
"hasCurveFrom": true,
"hasCurveTo": true,
"point": "{0.5, 1}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{1, 0.22385762510000001}",
"curveMode": 2,
"curveTo": "{1, 0.77614237490000004}",
"hasCurveFrom": true,
"hasCurveTo": true,
"point": "{1, 0.5}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.22385762510000001, 0}",
"curveMode": 2,
"curveTo": "{0.77614237490000004, 0}",
"hasCurveFrom": true,
"hasCurveTo": true,
"point": "{0.5, 0}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0, 0.77614237490000004}",
"curveMode": 2,
"curveTo": "{0, 0.22385762510000001}",
"hasCurveFrom": true,
"hasCurveTo": true,
"point": "{0, 0.5}"
}
]
},
{
"_class": "shapePath",
"do_objectID": "C96926E4-56B4-4816-A68B-22789ACF9811",
"booleanOperation": -1,
"frame": {
"_class": "rect",
"do_objectID": "33C190C2-C868-48CC-B5A5-E033A65A5DC5",
"constrainProportions": false,
"height": 30,
"width": 14,
"x": 17,
"y": 10
},
"isFixedToViewport": false,
"isFlippedHorizontal": false,
"isFlippedVertical": false,
"isLocked": false,
"isVisible": true,
"layerListExpandedType": 1,
"name": "facebook [#176]",
"nameIsFixed": false,
"resizingConstraint": 63,
"resizingType": 0,
"rotation": 0,
"shouldBreakMaskChain": false,
"userInfo": {
"com.animaapp.stc-sketch-plugin": {
"kModelPropertiesKey": {}
}
},
"clippingMaskMode": 0,
"hasClippingMask": false,
"edited": true,
"isClosed": true,
"pointRadiusBehaviour": 0,
"points": [
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.68212824010914053, 1}",
"curveMode": 1,
"curveTo": "{0.68212824010914053, 1}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.68212824010914053, 1}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.68212824010914053, 0.55000000000000004}",
"curveMode": 1,
"curveTo": "{0.68212824010914053, 0.55000000000000004}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.68212824010914053, 0.55000000000000004}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.95536932371857075, 0.55000000000000004}",
"curveMode": 1,
"curveTo": "{0.95536932371857075, 0.55000000000000004}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.95536932371857075, 0.55000000000000004}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{1, 0.34999999999999998}",
"curveMode": 1,
"curveTo": "{1, 0.34999999999999998}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{1, 0.34999999999999998}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.68212824010914053, 0.34999999999999998}",
"curveMode": 1,
"curveTo": "{0.68212824010914053, 0.34999999999999998}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.68212824010914053, 0.34999999999999998}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.68212824010914053, 0.20109999999999956}",
"curveMode": 4,
"curveTo": "{0.68212824010914053, 0.2525999999999996}",
"hasCurveFrom": true,
"hasCurveTo": false,
"point": "{0.68212824010914053, 0.2525999999999996}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.82868836484116337, 0.14999999999999999}",
"curveMode": 4,
"curveTo": "{0.68475930617813163, 0.14999999999999999}",
"hasCurveFrom": false,
"hasCurveTo": true,
"point": "{0.82868836484116337, 0.14999999999999999}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.97446891444162931, 0.14999999999999999}",
"curveMode": 1,
"curveTo": "{0.97446891444162931, 0.14999999999999999}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.97446891444162931, 0.14999999999999999}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.97446891444162931, 0.0048499999999989992}",
"curveMode": 4,
"curveTo": "{0.97446891444162931, 0.0069999999999993175}",
"hasCurveFrom": true,
"hasCurveTo": false,
"point": "{0.97446891444162931, 0.0069999999999993175}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.45800038978756463, 0}",
"curveMode": 3,
"curveTo": "{0.84924965893587745, 0}",
"hasCurveFrom": true,
"hasCurveTo": true,
"point": "{0.72256870005847007, 0}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.29234067433248878, 0.23499999999999943}",
"curveMode": 4,
"curveTo": "{0.29234067433248878, 0.082849999999999119}",
"hasCurveFrom": false,
"hasCurveTo": true,
"point": "{0.29234067433248878, 0.23499999999999943}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.29234067433248878, 0.34999999999999998}",
"curveMode": 1,
"curveTo": "{0.29234067433248878, 0.34999999999999998}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.29234067433248878, 0.34999999999999998}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0, 0.34999999999999998}",
"curveMode": 1,
"curveTo": "{0, 0.34999999999999998}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0, 0.34999999999999998}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0, 0.55000000000000004}",
"curveMode": 1,
"curveTo": "{0, 0.55000000000000004}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0, 0.55000000000000004}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.29234067433248878, 0.55000000000000004}",
"curveMode": 1,
"curveTo": "{0.29234067433248878, 0.55000000000000004}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.29234067433248878, 0.55000000000000004}"
},
{
"_class": "curvePoint",
"cornerRadius": 0,
"curveFrom": "{0.29234067433248878, 1}",
"curveMode": 1,
"curveTo": "{0.29234067433248878, 1}",
"hasCurveFrom": false,
"hasCurveTo": false,
"point": "{0.29234067433248878, 1}"
}
]
}
]
}
its svg code is
<g id="Facebook">
<circle id="Oval" fill="#5B76AF" cx="25" cy="25" r="25"></circle>
<path d="M26.5497954,40 L26.5497954,26.5 L30.3751705,26.5 L31,20.5 L26.5497954,20.5 L26.5497954,17.578 C26.5497954,16.033 26.5866303,14.5 28.6016371,14.5 L30.6425648,14.5 L30.6425648,10.21 C30.6425648,10.1455 28.8894952,10 27.1159618,10 C23.4120055,10 21.0927694,12.4855 21.0927694,17.05 L21.0927694,20.5 L17,20.5 L17,26.5 L21.0927694,26.5 L21.0927694,40 L26.5497954,40 Z" id="facebook-[#176]" fill="#FFFFFF"></path>
</g>
I understand <circle />
comes from the first layer, which i have no trouble with it, the issue is second layer, path
which is f letter, as its sketch json points are mapped to <path d="M26.5497954,40 L26.5497954,26.5 L30.3751705,26.5 L31,20.5 L26.5497954,20.5 L26.5497954,17.578 C26.5497954,16.033 26.5866303,14.5 28.6016371,14.5 L30.6425648,14.5 L30.6425648,10.21 C30.6425648,10.1455 28.8894952,10 27.1159618,10 C23.4120055,10 21.0927694,12.4855 21.0927694,17.05 L21.0927694,20.5 L17,20.5 L17,26.5 L21.0927694,26.5 L21.0927694,40 L26.5497954,40 Z" id="facebook-[#176]" fill="#FFFFFF"></path>
which is something i am trying hard to crack.. Is there a pattern to turn sketch json points to svg path and how can i do it..
Thanks.
« PreviousNext ». The <path> element is the most powerful element in the SVG library of basic shapes. You can use it to create lines, curves, arcs and more. Paths create complex shapes by combining multiple straight lines or curved lines.
Upload your JSON data (widely used in software like MongoDB, GeoServer, CartoWeb and FeatureServer) and convert them by one click to SHP (Shapefile) format (widely used in software like ESRI ArcGIS and ArcView).
Make the entire pattern into a combined path by selecting all the squares and click Path > Union Place the shape to be filled underneath the squares. In the example below I used a heart shape.
Complete circles and ellipses are the only shapes that SVG arcs have trouble drawing. Because the start and end points for any path going around a circle are the same point, there are an infinite number of circles that could be chosen, and the actual path is undefined.
I don't have the full solution but a few good hints:
Coordinates
All layers seem to use a local coordinate system with x and y values between 0 and 1. So you need the layers size and position to calculate the coordinates used in SVG:
xsvg = frame.x + xlayer * frame.width
ysvg = frame.y + ylayer * frame.height
Commands
The mapping of commands is trickier as the Sketch system uses a model different from SVG. The main difference is: SVG uses commands to represent path segments (except for the starting M) while Sketch uses a list of points that are either sharp or soft corners. In order to derive the command, you need to look at two consecutive points. Let's call them p1 and p2:
p1.hasCurveFrom = false and p2.hasCurveTo = false:
That represents a straight line, thus the L command. The coordinate is taken from p2.point.
p1.hasCurveFrom = true and p2.hasCurveTo = true:
That represents a cubic spline, thus the C command. The three coordinates are taken from:
Further hints
The path starts with an M command to p.point of the first point.
The attribute "isClosed": true
obviously indicates a closed path. Therefore, the commands end with Z
to close the path.
There are probably many more subtleties that I don't know.
If you want to implement a full Sketch to SVG converter, you will also need to implement the different shape classes and not just triangle, oval and shapePath and you will need to take care of all the other attributes like isFlippedHorizontal, isFlippedVertical, rotation, cornerRadius, resizingType etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With