用javascript解析SVG变换属性

时间:2021-12-30 15:30:17

Supposing we have an SVG transform string:

假设我们有一个SVG转换字符串:

transform = "translate(6,5),scale(3,3)";

Is there a slick regex function we could use to parse that into something usable?

是否有一个灵活的正则表达式函数,我们可以用它来解析可用的东西?

5 个解决方案

#1


13  

Here's a nifty little snippet of code that might get you what you need, it should cover most scenario in case the string you intend to parse has different number of arguments:

这里有一段漂亮的小代码片段,可以为您提供所需的代码,如果您打算解析的字符串具有不同数量的参数,它应涵盖大多数情况:

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;
}

Running this

跑这个

parse('translate(6,5),scale(3,3.5),a(1,1),b(2,23,-34),c(300)');

Will result in this:

会导致这个:

{
    translate: [ '6', '5' ],
    scale: [ '3', '3.5' ],
    a: [ '1', '1' ],
    b: [ '2', '23', '-34' ],
    c: [ '300' ]
}

#2


4  

Assuming you are running in a browser, you could also use the SVG DOM to parse and decode the transform string.

假设您在浏览器中运行,您还可以使用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.length; i++)
  {
    var transform = transformList[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)");

#3


3  

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}}

Pretty gross, but @icedwater was making me do all the work myself so...

相当严重,但@icedwater让我自己完成所有的工作......

#4


2  

Adapted from @chernjie's solution:

改编自@ 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;
}

#5


1  

I'll take a stab at this and say you want it to be parsed into a JSON object containing each of the properties as an entry in a list. This is the closest I have come so far:

我将对此进行一次尝试,并表示您希望将其解析为包含每个属性作为列表中条目的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;
}

which will take

这需要

transform = "translate(6,5),scale(3,3)";

and return

并返回

[
    {name: "translate", x: "6", y: "5"}, 
    {name: "scale", x: "3", y: "3"}
]

and should work for any number of transforms. Bit of a hack, but it will do for now.

并且应该适用于任意数量的变换。有点黑客,但它现在会做。

#1


13  

Here's a nifty little snippet of code that might get you what you need, it should cover most scenario in case the string you intend to parse has different number of arguments:

这里有一段漂亮的小代码片段,可以为您提供所需的代码,如果您打算解析的字符串具有不同数量的参数,它应涵盖大多数情况:

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;
}

Running this

跑这个

parse('translate(6,5),scale(3,3.5),a(1,1),b(2,23,-34),c(300)');

Will result in this:

会导致这个:

{
    translate: [ '6', '5' ],
    scale: [ '3', '3.5' ],
    a: [ '1', '1' ],
    b: [ '2', '23', '-34' ],
    c: [ '300' ]
}

#2


4  

Assuming you are running in a browser, you could also use the SVG DOM to parse and decode the transform string.

假设您在浏览器中运行,您还可以使用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.length; i++)
  {
    var transform = transformList[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)");

#3


3  

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}}

Pretty gross, but @icedwater was making me do all the work myself so...

相当严重,但@icedwater让我自己完成所有的工作......

#4


2  

Adapted from @chernjie's solution:

改编自@ 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;
}

#5


1  

I'll take a stab at this and say you want it to be parsed into a JSON object containing each of the properties as an entry in a list. This is the closest I have come so far:

我将对此进行一次尝试,并表示您希望将其解析为包含每个属性作为列表中条目的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;
}

which will take

这需要

transform = "translate(6,5),scale(3,3)";

and return

并返回

[
    {name: "translate", x: "6", y: "5"}, 
    {name: "scale", x: "3", y: "3"}
]

and should work for any number of transforms. Bit of a hack, but it will do for now.

并且应该适用于任意数量的变换。有点黑客,但它现在会做。