javascript - 将 svg 路径 d 拆分为对象数组
问题描述
有没有办法将d
路径字符串拆分为对象数组?
例如:
const d = `M 0 0 L 0 10 C 0 10 20 30 20 20 Z`
const result = fromPathToArray(d)
// const result = [
// { type: 'M', x: 0, y: 0 },
// { type: 'L', x: 0, y: 10 },
// { type: 'C', x1: 0, y1: 10, x2: 20, y2: 30, x3: 20, y3: 20 },
// { type: 'Z' },
// ]
这是我的起始代码:
const PATH_COMMANDS = {
M: ["x", "y"],
m: ["dx", "dy"],
H: ["x"],
h: ["dx"],
V: ["y"],
v: ["dy"],
L: ["x", "y"],
l: ["dx", "dy"],
Z: [],
C: ["x1", "y1", "x2", "y2", "x", "y"],
c: ["dx1", "dy1", "dx2", "dy2", "dx", "dy"],
S: ["x2", "y2", "x", "y"],
s: ["dx2", "dy2", "dx", "dy"],
Q: ["x1", "y1", "x", "y"],
q: ["dx1", "dy1", "dx", "dy"],
T: ["x", "y"],
t: ["dx", "dy"],
A: ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"],
a: ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"]
};
export function splitPath(path) {
const items = path.trim().split(/\s*,|\s+/);
const segments = [];
items.forEach((item, i) => {
const type = isString(item) ? item : null
// ...
})
return segments
}
老实说我不知道该怎么办..
解决方案
对于您所描述的情况,这是一个简单的例程。请注意,这种简单的解决方案只有在您知道输入遵循某种模式时才有用。如评论所示,一般情况更复杂。此外,您应该添加完整性检查以处理错误输入。
const PATH_COMMANDS = {
M: ["x", "y"],
m: ["dx", "dy"],
H: ["x"],
h: ["dx"],
V: ["y"],
v: ["dy"],
L: ["x", "y"],
l: ["dx", "dy"],
Z: [],
C: ["x1", "y1", "x2", "y2", "x", "y"],
c: ["dx1", "dy1", "dx2", "dy2", "dx", "dy"],
S: ["x2", "y2", "x", "y"],
s: ["dx2", "dy2", "dx", "dy"],
Q: ["x1", "y1", "x", "y"],
q: ["dx1", "dy1", "dx", "dy"],
T: ["x", "y"],
t: ["dx", "dy"],
A: ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"],
a: ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"]
};
function fromPathToArray(path) {
const items = path.replace(/[\n\r]/g, '').
replace(/-/g, ' -').
replace(/(\d*\.)(\d+)(?=\.)/g, '$1$2 ').
trim().
split(/\s*,|\s+/);
const segments = [];
let currentCommand = '';
let currentElement = {};
while (items.length > 0){
let it = items.shift();
if (PATH_COMMANDS.hasOwnProperty(it)){
currentCommand = it;
}
else{
items.unshift(it);
}
currentElement = {type: currentCommand};
PATH_COMMANDS[currentCommand].forEach((prop) => {
it = items.shift(); // TODO sanity check
currentElement[prop] = it;
});
if (currentCommand === 'M'){
currentCommand = 'L';
}
else if (currentCommand === 'm'){
currentCommand = 'l';
}
segments.push(currentElement);
}
return segments
}
const d = `M 0 0 10 10 L 0 10 C 0 10
20 30 20 20 a 4.12.12 1 0 1 4.13-1 Z`;
const result = fromPathToArray(d);
console.log(result);
推荐阅读
- javascript - document.activeElement 条件不起作用(id 或 ref 在 div 元素内)
- google-cloud-platform - 如何连接到 mqtt.googleapis.com
- excel - VBA 列表框显示带有货币格式的错误符号
- perl - perl-5.14.2 使测试失败
- java - 我可以让轮询器在 start() 命令之后使用 WAIT 开始他的周期吗?
- reactjs - 未处理的拒绝(TypeError):无法在已撤销的代理上执行“获取”
- python - 如何从列表变量中的每组向量中删除单引号?
- mysql - 无法通过套接字'/run/mysqld/mysqld.sock 连接到本地 MySQL 服务器
- ssconvert - SSconvert 将日期转换为 YYYY-MM-DD,而不考虑 xlsx 日期格式
- three.js - 三个Js:不同的颜色到不同的几何面