UNPKG

sketch-json-parse

Version:

sketch-json解析

346 lines (345 loc) 12.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const insert = (newLayer, layers) => { const { x: nx, y: ny, width: nwidth, height: nheight } = newLayer.structure; if (!layers || layers.length === 0) { layers[0] = newLayer; return; } let pos = -1; for (let index = 0; index < layers.length; index++) { const layer = layers[index]; const { x, y, width, height } = layer.structure; // TODO 误差量 if (x <= nx + 1 && x + width + 1 >= nx + nwidth && y <= ny + 1 && y + height + 1 >= ny + nheight) { // if (!layer.children) layer.children = []; // insert(newLayer, layer.children); // return; pos = index; } } if (pos !== -1) { const layer = layers[pos]; if (!layer.children) layer.children = []; insert(newLayer, layer.children); } else { layers.push(newLayer); } }; const pow2 = (n) => { return Math.pow(n, 2); }; function sortData(data) { const newData = []; const offset = 20000; // data.sort(({ x: x1, y: y1 }, { x: x2, y: y2 }) => { // return (Math.pow(x1, 2) + Math.pow(y1 + offset, 2)) - (Math.pow(x2, 2) + Math.pow(y2 + offset, 2)); // }).sort(({ x: x1, y: y1, height: height1 }, { x: x2, y: y2, height: height2 }) => { // if ((y1 >= y2 && y1 + height1 <= y2 + height2) || (y1 <= y2 && y1 + height1 >= y2 + height2)) { // return x1 - x2; // } // return (Math.pow(x1, 2) + Math.pow(y1 + offset, 2)) - (Math.pow(x2, 2) + Math.pow(y2 + offset, 2)); // }) // .forEach((layer, i) => { // layer.index = i; // insert(layer, newData); // }); // return newData; const len = data.length; for (let i = 0; i < len; i++) { for (let j = 0; j < len - 1; j++) { const { x: x1, y: y1, width: width1, height: height1 } = data[j].structure; const { x: x2, y: y2, width: width2, height: height2 } = data[j + 1].structure; if (x1 === x2 && y1 === y2) { if (width1 * height1 < width2 * height2) { [data[j], data[j + 1]] = [data[j + 1], data[j]]; } } else if ((y1 >= y2 && y1 + height1 <= y2 + height2) || (y1 <= y2 && y1 + height1 >= y2 + height2)) { if (x1 > x2) { [data[j], data[j + 1]] = [data[j + 1], data[j]]; } } else if ((pow2(x1) + pow2(y1 + offset)) > (pow2(x2) + pow2(y2 + offset))) { [data[j], data[j + 1]] = [data[j + 1], data[j]]; } } } data.forEach((layer, i) => { layer.structure.zIndex = i; insert(layer, newData); }); return newData; } const getXYWH = (arr) => { let ax = arr[0].x; let ay = arr[0].y; let awidth = arr[0].width; let aheight = arr[0].height; for (let { x, y, width, height } of arr) { if (x < ax) ax = x; if (y < ay) ay = y; if (x + width > ax + awidth) awidth = x + width - ax; if (y + height > ay + aheight) aheight = y + height - ay; } return { x: ax, y: ay, width: awidth, height: aheight, }; }; const getMax = (arr, edgeFlag = true) => { // 分组 const arrMap = new Map(); arr.forEach((d) => { const { width, height } = d.structure; const wh = `${width},${height}`; const { n, nArr } = arrMap.get(wh) || { n: 0, nArr: [] }; nArr.push(d); arrMap.set(wh, { n: n + 1, nArr, }); }); let maxKey = null; let maxN = 0; const arrWide = getXYWH(arr); let len = arr.length; while (len) { len--; for (const [key, { n }] of arrMap) { if (n > maxN) { maxN = n; maxKey = key; } } if (maxN === 1) break; const maxArr = arr.filter(({ structure }) => { const { width, height } = structure; // 大小容差 return `${width},${height}` === maxKey; }); const overlappingFlag = arr.reduce((prev, curr) => { if (!prev) return curr; if (prev === true) return true; const { x: px, y: py, width: pwidth, height: pheight } = prev; const { x, y, width, height } = curr.structure; return !(px > x + width || px + pwidth < x || py > y + height || py + pheight < y); }, false); // const maxArrWide = getXYWH(maxArr); const { structure: { x, y }, componentName } = maxArr[0]; if (componentName === 'Text') { arrMap.delete(maxKey); maxN = 1; } else if (edgeFlag && x !== arrWide.x && y !== arrWide.y) { arrMap.delete(maxKey); maxN = 1; } else if (overlappingFlag === true) { arrMap.delete(maxKey); maxN = 1; } else { break; } } return { maxKey, maxN }; }; const groupData = (arr, p) => { if (!arr || arr.length === 0) return; if (arr.length <= 1) { if (arr[0].children) { groupData(arr[0].children, arr[0]); } return; } let { maxKey, maxN } = getMax(arr); const groupLayers = []; for (let i = 0; i < arr.length; i++) { const d = arr[i]; // if (d.id === '9a2sea9u') debugger; if (d.textContainer !== true && d.children && d.children.length > 0) groupData(d.children, d); if (maxN === 1 || d.sign === '__li') { groupLayers[i] = d; continue; } const { width: dWidth, height: dHeight } = d.structure; if (!groupLayers[0]) groupLayers[0] = []; if (groupLayers.length <= 1 && `${dWidth},${dHeight}` !== maxKey) { groupLayers[0].push(d); continue; } // TODO if (!groupLayers[1]) groupLayers[1] = []; if (`${dWidth},${dHeight}` === maxKey) { groupLayers[1].push([d]); groupLayers[1].sign = '__list'; } else { const liLayers = groupLayers[1]; if (liLayers.length > 1 && liLayers[liLayers.length - 1].length === liLayers[0].length) { groupLayers[2] = arr.slice(i); break; } liLayers[liLayers.length - 1].push(d); } } if (maxN > groupLayers[1].length) { groupLayers.length = 0; groupLayers.push([...arr]); } // if (p && p.id === '5sj0hqpc') debugger; if (groupLayers[1] && Array.isArray(groupLayers[1]) && groupLayers[1][0].sign === '__list') { const overlappingFlag = groupLayers[1].reduce((prev, curr) => { if (!prev) return curr; if (prev === true) return true; const { x: px, y: py, width: pwidth, height: pheight } = getXYWH(prev); const { x, y, width, height } = getXYWH(curr); return !(px > x + width || px + pwidth < x || py > y + height || py + pheight < y); }, false); if (overlappingFlag === true) { groupLayers.length = 0; groupLayers.push([...arr]); } } if (maxN === 1) { const { width: mwidth, height: mheight } = getXYWH(arr); const segArr = []; arr.forEach((d, i) => { if ((d.structure.width === mwidth && d.structure.height < 5) || (d.structure.height === mheight && d.structure.width < 5)) segArr.push(i); }); // TODO 如果第一个或者最后一个不分组 // TODO 此处判断有待优化 if (segArr.length > 0 && segArr.length < arr.length) { // debugger; groupLayers.length = 0; const newArr = [...arr]; segArr.reduce((pv, cv, idx) => { groupLayers.push([...newArr.slice(pv, cv)]); if (p && p.sign === '__li') groupLayers[groupLayers.length - 1].sign = '__li'; groupLayers.push([...newArr.slice(cv, cv + 1)]); if (cv === newArr.length - 1) return; if (idx === segArr.length - 1) { groupLayers.push([...newArr.slice(cv + 1)]); if (p && p.sign === '__li') groupLayers[groupLayers.length - 1].sign = '__li'; } return cv + 1; }, 0); } else if (p && p.sign === '__li') { const __groupLayers = []; const YA = []; const fullWidthArr = []; for (let i = 0; i < arr.length; i++) { const d = arr[i]; // if (d.id === 'lomlu25m') debugger; let flag = true; let { width: dWidth, x: dX } = d.structure; if (i === 0) { YA[0] = { width: dWidth, x: dX }; } if (p && dWidth === p.structure.width) { fullWidthArr.push(d); continue; } // TODO 先小后大 处理 for (let j = 0; j < YA.length; j++) { const { x: yX, width: yWidth } = YA[j]; // if (!(yX > dX || yX + yWidth < dX + dWidth)) { if (!(yX > dX + dWidth || yX + yWidth < dX)) { if (!__groupLayers[j]) __groupLayers[j] = []; __groupLayers[j].push(d); flag = false; break; } } if (flag) { YA.push({ width: dWidth, x: dX }); const pos = YA.length - 1; if (!__groupLayers[pos]) __groupLayers[pos] = []; __groupLayers[pos].push(d); } } if (YA.length > 1) { groupLayers.length = 0; groupLayers.push(...__groupLayers.filter(l => !!l)); groupLayers.push(fullWidthArr); } } } if (p) { if (!Array.isArray(groupLayers[0])) { return p.children = groupLayers; } // if (p && p.id === '5sj0hqpc') debugger; p.children = groupLayers.filter((gls) => gls.length > 0).map((gls) => { if (gls.length === 1) { return gls[0]; } // TODO const c = gls.map(gl => { if (!Array.isArray(gl)) return gl; if (gl.length === 1) { if (gls.sign === '__list') gl[0].sign = '__li'; return gl[0]; } return Object.assign(Object.assign({ sign: gls.sign === '__list' ? '__li' : '__oth' }, getXYWH(gl)), { children: gl }); }); const cp = Object.assign(Object.assign({ sign: gls.sign ? gls.sign : '__oth' }, getXYWH(c)), { children: c }); return cp; }); // if (p && p.id === '5sj0hqpc') debugger; if (p.children.length === 1 && p.children[0].sign) { p.children = p.children[0].children; } p.children.forEach((pc) => { if (pc.sign === '__list') { pc.children.forEach((pcc) => { // debugger; pcc.children && groupData(pcc.children, pcc); }); return; } if (pc.children && pc.children.length > 0 && pc.children[0].sign !== '__li') { pc.children && groupData(pc.children, pc); } }); } }; const domFormat = (data) => { const [artboard, ...childData] = data; const newData = sortData(childData); groupData(newData); artboard.children = newData; return [artboard]; }; exports.default = domFormat;