使用javascript解析SVG转换属性
Parse SVG transform attribute with javascript
假设我们有一个SVG转换字符串:
transform = "translate(6,5),scale(3,3)";
有没有一个巧妙的正则表达式函数可以用来将其解析为可用的东西?
这里有一个漂亮的小代码片段,可以满足您的需求,它应该涵盖大多数场景,以防您想要解析的字符串有不同数量的参数:
function parse (a)
{
var b={};
for (var i in a = a.match(/('w+'(('-?'d+'.?'d*e?'-?'d*,?)+'))+/g))
{
var c = a[i].match(/['w'.'-]+/g);
b[c.shift()] = c;
}
return b;
}
运行此
parse('translate(6,5),scale(3,3.5),a(1,1),b(2,23,-34),c(300)');
将导致以下情况:
{
translate: [ '6', '5' ],
scale: [ '3', '3.5' ],
a: [ '1', '1' ],
b: [ '2', '23', '-34' ],
c: [ '300' ]
}
假设您在浏览器中运行,您也可以使用SVG DOM来解析和解码转换字符串。
var svgns = "http://www.w3.org/2000/svg";
function getTransformList(transformStr)
{
// Create a fake <rect> element to set the transform to
var rect = document.createElementNS(svgns, "rect");
rect.setAttribute("transform", transformStr);
// Use the DOM to get the list of decoded transforms
dumpTransform(rect.transform.baseVal);
}
function dumpTransform(transformList)
{
for (var i = 0; i < transformList.numberOfItems; i++)
{
var transform = transformList.getItem(i);
var m = transform.matrix;
switch (transform.type)
{
case 2:
console.log("translate("+m.e+","+m.f+")");
break;
case 3:
console.log("scale("+m.a+","+m.d+")");
break;
case 4:
console.log("rotate("+transform.angle+")");
// TODO need to also handle rotate(angle, x, y) form
break;
case 5:
// TODO skewX()
break;
case 6:
// TODO skewY(()
break;
case 1:
default:
console.log("matrix("+m.a+","+m.b+","+m.c+","+m.d+","+m.e+","+m.f+")");
break;
}
}
}
getTransformList("translate(6,5),scale(3,3)");
改编自@chernjie的解决方案:
function parse_transform(a) {
var b = {};
for (var i in a = a.match(/('w+)'(([^,)]+),?([^)]+)?')/gi)) {
var c = a[i].match(/['w'.'-]+/g);
b[c.shift()] = c;
}
return b;
}
var transform = "translate(6,5),scale(3,3)";
var translate = /translate'('s*([^'s,)]+)[ ,]([^'s,)]+)/.exec(transform);
var translateX = translate[1]
var translateY = translate[2]
var scale = /scale'('s*([^'s,)]+)[ ,]([^'s,)]+)/.exec(transform);
var scaleX = translate[1]
var scaleY = translate[2]
transformValues = {translate:{x:translateX,y:translateY},
scale:{x:scaleX,y:scaleY}}
相当恶心,但@icedwater让我自己做所有的工作,所以…
我会尝试一下,并说您希望将其解析为一个JSON对象,该对象包含列表中的每个属性作为条目。这是我迄今为止最接近的一次:
function listIntoJSON(theTransformInQuestion) {
// let's work with transform = "translate(6,5),scale(3,3)" as specified.
var result = []; // empty list to be returned
var splitList = theTransformInQuestion.split(/'W/);
// now splitList is ["translate", "6", "5", "", "scale", "3", "3", ""]
for (var t = 0; t < splitList.length; t += 4) {
var op = {};
op.name = splitList[t];
op.x = splitList[t + 1];
op.y = splitList[t + 2];
result.push(op); // add op to the result list
}
return result;
}
哪个需要
transform = "translate(6,5),scale(3,3)";
并返回
[
{name: "translate", x: "6", y: "5"},
{name: "scale", x: "3", y: "3"}
]
并且应该适用于任何数量的变换。有点像黑客,但现在可以了。
即使这是一个老问题,今天我也有同样的需求,最终得到了这个regex:
const regex = /(('w+)'((,?'s*-?'d*'.?'d+(px|in|px|cm|mm|pt|pc|em|ex|ch|rem|deg|rad|grad|turn)?)+')'s*)/gi;
很长,但它也考虑了度量单位。
您可以在此处进行测试:https://regex101.com/r/M8rRjo/1/
这不是regex,但有一个类似的问题(用一个非常好的、全面的解决方案取代D3v4中的d3.transform):
function getTransformation(transform) {
// Create a dummy g for calculation purposes only. This will never
// be appended to the DOM and will be discarded once this function
// returns.
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
// Set the transform attribute to the provided string value.
g.setAttributeNS(null, "transform", transform);
// consolidate the SVGTransformList containing all transformations
// to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get
// its SVGMatrix.
var matrix = g.transform.baseVal.consolidate().matrix;
// Below calculations are taken and adapted from the private function
// transform/decompose.js of D3's module d3-interpolate.
var {a, b, c, d, e, f} = matrix; // ES6, if this doesn't work, use below assignment
// var a=matrix.a, b=matrix.b, c=matrix.c, d=matrix.d, e=matrix.e, f=matrix.f; // ES5
var scaleX, scaleY, skewX;
if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
return {
translateX: e,
translateY: f,
rotate: Math.atan2(b, a) * 180 / Math.PI,
skewX: Math.atan(skewX) * 180 / Math.PI,
scaleX: scaleX,
scaleY: scaleY
};
}
console.log(getTransformation("translate(20,30)"));
console.log(getTransformation("rotate(45) skewX(20) translate(20,30) translate(-5,40)"));
相关文章:
- 可以转换显示属性吗?如果没有,什么'这是最好的解决方案
- 手柄'img'单击事件并插入'alt'使用jQuery将属性转换为文本框
- Javascript将数组中对象的属性转换为字符串
- 如何在不使用css转换的情况下将jQuery animate与css3属性相结合
- 如何将CSS背景位置属性从百分比转换为像素
- 如何将返回一串数字的 JSON 属性转换为日期
- 使用多个 css 类将 css 转换属性应用于 DOM 对象时遇到问题
- 使用 JavaScript 更新转换属性中的 rotate() 属性
- 如何使用更多次 css 转换属性
- Babel React 转换:属性值预期的字符串类型,但得到空
- jQuery 如何将 CSS 转换属性设置为任何对象
- 使用 jQuery 2.1+ 更改 css 会忽略转换属性
- 使用javascript解析SVG转换属性
- mozilla css转换属性dosn'不起作用
- CSS中转换属性的动态值
- 意外值翻译解析转换属性
- Css3过渡+转换属性在早期版本的IE中不工作
- -translate的webkit转换属性
- 用于CSS3动画和转换属性的Javascript代码
- XML3D css转换vs自定义转换属性