摘要
命令M、L、C、S、Q、T平移均是x,y坐标加上偏移量offsetx,offsety
命令M(x, y)
M偏移公式Mx, y = Mx + offsetx, y + offsety
M25,15,偏移量10,15,偏移结果M35,30
命令L(x, y)
L偏移公式Lx, y = Lx + offsetx, y + offsety
L25,15,偏移量10,15,偏移结果L35,30
命令T(x, y)
T偏移公式Tx, y = Tx + offsetx, y + offsety
T25,15,偏移量10,15,偏移结果T35,30
命令C(x1, y1, x2, y2, x3, y3)
C偏移公式:
Cx1, y1,x2,y2,x3,y3 = Cx1+ offsetx, y1 + offsety,x2+ offsetx, y2 + offsety,x3+ offsetx, y3 + offsety
C25,15,40,150,30,80偏移量10,15,偏移结果C35,30,50,165,40,95
命令S(x1, y1, x2, y2)
S偏移公式:
Sx1, y1,x2,y2 = Sx1+ offsetx, y1 + offsety,x2+ offsetx, y2 + offsety
S25,15,40,150偏移量10,15,偏移结果S35,30,50,165
命令Q(x1, y1, x2, y2)
偏移公式:
Qx1, y1,x2,y2 = Qx1+ offsetx, y1 + offsety,x2+ offsetx, y2 + offsety
Q25,15,40,150偏移量10,15,偏移结果Q35,30,50,165
命令H(x)
H偏移公式Hx = Hx + offsetx
H25,偏移量10,15,偏移结果H35
命令V(y)
V偏移公式Vy = Vy + offsety
V15,偏移量10,15,偏移结果H30
重点,难点
命令A(rx, ry, xr, laf, sf, x,y)
A偏移公式:
Arx, ry, xr, laf, sf, x,y = Arx, ry, xr, laf, sf, x + offsetx, y + offsety
A25,15,40,1,0,80,100偏移量10,15,偏移结果A25,15,40,1,0,90,115
注:相对命令m l c s q a t h v不使用偏移量
代码举例:
var path1 ='M50,100A30,40,10,0,0,200,20'
var path2 = 'M10,10C20,20,30,10,40,20S50,30,60,20Q70,10,80,20T90,30'
// 平移到原点10,15
function movePath (pathData, move) {
let moveX = move.x
let moveY = move.y
let pathCommands = pathData.match(/[A-Za-z][^A-Za-z]*/g);
// 平移路径到原点
let translatedPathD = pathCommands.map(command => {
let commandLetter = command.match(/[A-Za-z]/)[0];
let commandParams = command.match(/[^A-Za-z]+/g);
if (commandLetter === 'A' || commandLetter === 'a') {
let flag = /[ ,]+/
commandParams = commandParams[0].split(flag)
commandParams = commandParams.filter(num => num)
// 处理A命令的参数
let rx = parseFloat(commandParams[0]);
let ry = parseFloat(commandParams[1]);
let xAxisRotation = parseFloat(commandParams[2]);
let largeArcFlag = parseFloat(commandParams[3]);
let sweepFlag = parseFloat(commandParams[4]);
let x = parseFloat(commandParams[5]) + (commandLetter === 'a' ? 0 : moveX);
let y = parseFloat(commandParams[6]) + (commandLetter === 'a' ? 0 : moveY);
// 重新构建A命令的参数
return `${commandLetter}${rx},${ry},${xAxisRotation},${largeArcFlag},${sweepFlag},${x},${y}`;
} else {
if (!commandParams) return commandLetter
let flag = /[ ,]+/
commandParams = commandParams[0].split(flag)
commandParams = commandParams.filter(num => num)
let lowercase = /[a-z]+/g
if (lowercase.test(commandLetter)) { // 小写命令
return commandLetter + commandParams.join(',')
}
if (commandLetter === 'M' || commandLetter === 'L' || commandLetter === 'T') {
let x = parseFloat(commandParams[0]) + moveX
let y = parseFloat(commandParams[1]) + moveY
return `${commandLetter}${x},${y}`
} else if (commandLetter === 'S' || commandLetter === 'Q') {
let x1 = parseFloat(commandParams[0]) + moveX
let y1 = parseFloat(commandParams[1]) + moveY
let x2 = parseFloat(commandParams[2]) + moveX
let y2 = parseFloat(commandParams[3]) + moveY
return `${commandLetter}${x1},${y1},${x2},${y2}`
} else if (commandLetter === 'C') {
let x1 = parseFloat(commandParams[0]) + moveX
let y1 = parseFloat(commandParams[1]) + moveY
let x2 = parseFloat(commandParams[2]) + moveX
let y2 = parseFloat(commandParams[3]) + moveY
let x3 = parseFloat(commandParams[4]) + moveX
let y3 = parseFloat(commandParams[5]) + moveY
return `${commandLetter}${x1},${y1},${x2},${y2},${x3},${y3}`
} else if (commandLetter === 'H') {
let h = parseFloat(commandParams[0]) + moveX
return `${commandLetter}${h}`
} else if (commandLetter === 'V') {
let v = parseFloat(commandParams[0]) + moveY
return `${commandLetter}${v}`
}
// 处理其他命令的参数
let translatedParams = commandParams.map(param => {
let num = parseFloat(param);
return (num + moveX)
});
return commandLetter + translatedParams.join(',');
}
}).join('');
return translatedPathD
}
var movePath1 = movePath(path1, {x:10,y:15})
var movePath2 = movePath(path2, {x:10,y:15})
console.log(movePath1)
// path1: M60,115A30,40,10,0,0,210,35
console.log(movePath2)
// path2:M20,25C30,35,40,25,50,35S60,45,70,35Q80,25,90,35T100,45