查找将草图形状路径点(json 格式)转换为 svg 路径的模式或公式
Finding a pattern or formula to convert Sketch shape path points(json format) to svg path
我正在尝试找到一种将 Sketch 形状点(json 格式)转换为 svg 路径的模式,因为我们知道 sketch 文件只是 zip 文件,解压缩你会得到 json 文件。
这是示例 json 代码
{
"_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
}
这给出了一个三角形及其 svg 路径代码
<polygon id="Triangle" points="33 0 66 56.8615385 0 56.8615385"></polygon>
根据我的理解 getting 33(x value)
是按如下方式完成的,因为上面的框架原点在 0,0 (frame->x, frame->y)
我想得到它的实际位置是 frame->width
(因为宽度对应于 x轴)是 66 times first x point in points, which is 0.49999999999999944
,结果是 (32.99999999 approx 33
),first y point
取 frame->height(56.86153846153846 times the first y point in points which is 0)
结果是第一个点是 33 0
第二点相同,得到 x 需要 frame->width(66)
次 second x point in points which is 0.99999999
得到 66
,与其 corresponding y (56.86153846153846 times 1) which is 56.86153846153846
相同,得到第二点 66 56.86153846153846
第三点也是一样..
如果 frame->x 和 frame->y 的数字大于 0 则开始混淆
考虑这个..
{
"_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
}
其对应的svg路径为
<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>
现在,如果我按照上面的方法进行数学计算,我不会得到 points="33 22.3384615 51.7846154 54.8307692 14.2153846 54.8307692"
如上面的 svg 代码所示。这仅适用于三角形,如果是自定义形状路径,如 facebook 图标,它会混淆很多!。草图标志示例,
其对应的Sketchjson代码如下
{
"_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}"
}
]
}
]
}
它的svg代码是
<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>
我知道<circle />
来自第一层,我没有遇到问题,问题是第二层,path
是f字母,作为它的草图json点映射到 <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>
这是我正在努力破解的东西..有没有一种模式可以将草图 json 指向 svg 路径,我该怎么做..
谢谢。
我没有完整的解决方案,但有一些好的提示:
坐标
所有图层似乎都使用局部坐标系,x 和 y 值在 0 和 1 之间。所以你需要图层大小和位置来计算 SVG 中使用的坐标:
xsvg = frame.x + xlayer * frame.width
ysvg = frame.y + y层 * frame.height
命令
由于 Sketch 系统使用不同于 SVG 的模型,因此命令映射更加棘手。主要区别在于:SVG 使用命令来表示路径段(起始 M 除外),而 Sketch 使用尖点或软点列表 corners。为了导出命令,您需要查看两个连续的点。我们称它们为 p1 和 p2:
p1.hasCurveFrom = false 和 p2.hasCurveTo = false:
代表一条直线,因此L命令。坐标取自p2.point.
p1.hasCurveFrom = true 和 p2.hasCurveTo = true:
表示三次样条,因此 C 命令。三个坐标取自:
- p1.curveFrom
- p2.curveTo
- p2.point
进一步提示
路径从第一个点的M命令开始到p.point。
属性"isClosed": true
显然表示一条封闭路径。因此,命令以 Z
结尾以关闭路径。
可能还有很多我不知道的细微之处。
如果您想实现一个完整的 Sketch 到 SVG 转换器,您还需要实现不同的形状 类 而不仅仅是 三角形、oval 和 shapePath 并且您需要处理所有其他属性,例如 isFlippedHorizontal、isFlippedVertical 、rotation、cornerRadius、resizingType 等
我正在尝试找到一种将 Sketch 形状点(json 格式)转换为 svg 路径的模式,因为我们知道 sketch 文件只是 zip 文件,解压缩你会得到 json 文件。 这是示例 json 代码
{
"_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
}
这给出了一个三角形及其 svg 路径代码
<polygon id="Triangle" points="33 0 66 56.8615385 0 56.8615385"></polygon>
根据我的理解 getting 33(x value)
是按如下方式完成的,因为上面的框架原点在 0,0 (frame->x, frame->y)
我想得到它的实际位置是 frame->width
(因为宽度对应于 x轴)是 66 times first x point in points, which is 0.49999999999999944
,结果是 (32.99999999 approx 33
),first y point
取 frame->height(56.86153846153846 times the first y point in points which is 0)
结果是第一个点是 33 0
第二点相同,得到 x 需要 frame->width(66)
次 second x point in points which is 0.99999999
得到 66
,与其 corresponding y (56.86153846153846 times 1) which is 56.86153846153846
相同,得到第二点 66 56.86153846153846
第三点也是一样..
如果 frame->x 和 frame->y 的数字大于 0 则开始混淆
考虑这个..
{
"_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
}
其对应的svg路径为
<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>
现在,如果我按照上面的方法进行数学计算,我不会得到 points="33 22.3384615 51.7846154 54.8307692 14.2153846 54.8307692"
如上面的 svg 代码所示。这仅适用于三角形,如果是自定义形状路径,如 facebook 图标,它会混淆很多!。草图标志示例,
其对应的Sketchjson代码如下
{
"_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}"
}
]
}
]
}
它的svg代码是
<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>
我知道<circle />
来自第一层,我没有遇到问题,问题是第二层,path
是f字母,作为它的草图json点映射到 <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>
这是我正在努力破解的东西..有没有一种模式可以将草图 json 指向 svg 路径,我该怎么做..
谢谢。
我没有完整的解决方案,但有一些好的提示:
坐标
所有图层似乎都使用局部坐标系,x 和 y 值在 0 和 1 之间。所以你需要图层大小和位置来计算 SVG 中使用的坐标:
xsvg = frame.x + xlayer * frame.width
ysvg = frame.y + y层 * frame.height
命令
由于 Sketch 系统使用不同于 SVG 的模型,因此命令映射更加棘手。主要区别在于:SVG 使用命令来表示路径段(起始 M 除外),而 Sketch 使用尖点或软点列表 corners。为了导出命令,您需要查看两个连续的点。我们称它们为 p1 和 p2:
p1.hasCurveFrom = false 和 p2.hasCurveTo = false:
代表一条直线,因此L命令。坐标取自p2.point.
p1.hasCurveFrom = true 和 p2.hasCurveTo = true:
表示三次样条,因此 C 命令。三个坐标取自:
- p1.curveFrom
- p2.curveTo
- p2.point
进一步提示
路径从第一个点的M命令开始到p.point。
属性"isClosed": true
显然表示一条封闭路径。因此,命令以 Z
结尾以关闭路径。
可能还有很多我不知道的细微之处。
如果您想实现一个完整的 Sketch 到 SVG 转换器,您还需要实现不同的形状 类 而不仅仅是 三角形、oval 和 shapePath 并且您需要处理所有其他属性,例如 isFlippedHorizontal、isFlippedVertical 、rotation、cornerRadius、resizingType 等