Home > Mobile >  Transform-origin CSS property not recognized by Illustrator
Transform-origin CSS property not recognized by Illustrator

Time:09-08

I'm doing an online customization tool on a website which directly changes an SVG element made on Adobe Illustrator by a graphist. I have a problem with the transform-origin: center CSS property which is not understood when opening the svg on Illusrator.

However, for exemple, the transform: rotate(180) is understood and read.

How can I do to make it works another way (or this way but different ?) please ? Can't find anything on the Internet so far..

CodePudding user response:

A possible workaround might be to convert all transform properties to matrix transformations.

This way we can reset all transform-orgin attributes to the default "0 0".

Example: convert all transformations to matrix

// getTransformToElement polyfill
SVGElement.prototype.getTransformToElement =
  SVGElement.prototype.getTransformToElement ||
  function(toElement) {
    return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
  };


//let svgOrigMarkup = svgOrig.value;
svgPreview.innerHTML = svgOrig.value;
let svg = document.querySelector("svg");
optimizeForAi(svg);


svgOrig.addEventListener('change', function(e) {
  svgPreview.innerHTML = e.currentTarget.value;
  svg = document.querySelector("svg");
  optimizeForAi(svg);
})



function optimizeForAi(svg) {
  //add namespace
  let xmlns = svg.getAttribute('xmlns');
  if (!xmlns) {
    svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  }
  //add viewBox and dimensions
  addViewBoxAndWidth(svg);
  let els = svg.querySelectorAll("*");
  //convert units and transformations
  els.forEach(function(el) {
    transFormToMatrix(el);
    percentageToAbs(svg, el)
  });
  //update markup
  svgMarkup.value = svg.outerHTML;
}



function addViewBoxAndWidth(svg) {
  let vB = svg.getAttribute("viewBox");
  let [width, height] = [svg.getAttribute("width"), svg.getAttribute("height")];
  let [svgW, svgH] = vB
    ?
    [vB.split(" ")[2], vB.split(" ")[3]] : [width, height];
  if (!svgW || !svgH) {
    let bb = svg.getBBox();
    [svgW, svgH] = [bb.width, bb.height];
  }
  //add viewBox
  if (!vB) {
    svg.setAttribute("viewBox", [0, 0, svgW, svgH].join(" "));
  }
  //add width and height
  if (!width || !height) {
    svg.setAttribute("width", svgW   "px");
    svg.setAttribute("height", svgH   "px");
  }
}

function percentageToAbs(svg, el) {
  let vB = svg.getAttribute("viewBox");
  let [svgW, svgH] = [vB.split(" ")[2], vB.split(" ")[3]];

  // find percentage values
  let atts = [...el.attributes];
  atts.forEach(function(att, i) {
    let attName = att.nodeName;
    let attVal = att.value;
    if (attVal.indexOf("%") !== -1) {
      let rel = attName.indexOf("y") !== -1 ? svgH : svgW;
      //convert to absolute value
      let attValAbs = (rel / 100) * parseFloat(attVal);
      el.setAttribute(attName, attValAbs);
    }
  });
}

function transFormToMatrix(el) {
  let type = el.nodeName.toLowerCase();
  let matrixString = "";
  let types = [
    "path",
    "polygon",
    "polyline",
    "rect",
    "ellipse",
    "circle",
    "line",
    "text",
    "g",
    "svg"
  ];
  if (types.indexOf(type) !== -1) {
    // get el matrix
    let matrix = el.getTransformToElement(el.parentNode);
    let [a, b, c, d, e, f] = [
      matrix.a,
      matrix.b,
      matrix.c,
      matrix.d,
      matrix.e,
      matrix.f
    ];
    matrixString = [a, b, c, d, e, f].join(" ");
    let matrixStringRound = [a, b, c, d, e, f]
      .map((val) => {
        return  val.toFixed(3);
      })
      .join(" ");
    //exclude non transformed elements
    if (matrixStringRound != "1 0 0 1 0 0") {
      el.setAttribute("transform", `matrix(${matrixString})`);
      el.removeAttribute("transform-origin");
      el.style.setProperty('transform-origin', '0px 0px', 'important');
    }
  }
  return matrixString;
}
svg{
max-width:75%;
height:auto;
}
<div id="svgPreview"></div>
<h3>Paste in your svg markup</h3>
<textarea id="svgOrig" style="width:100%; min-height:20em">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 400" >
    <style>
      .g2{
        transform-origin: center;
      }
    </style>
    <rect width="1000" height="400" fill="orange"></rect>
    <g transform="translate(-200 50) rotate(-45)" transform-origin="500 200">
      <g  transform="translate(200 -50)" style="color:green">
        <text  x="50%" y="50%" transform="rotate(45)" transform-origin="center" text-anchor="middle" font-size="50">Text</text>
      </g>
    </g>
  </svg>
</textarea>

<h3>Optimized</h3>
<textarea id="svgMarkup" style="width:100%; min-height:20em"></textarea>

The transFormToMatrix(el) method does the matrix calculation and depends on the deprecated getTransformToElement() method (polyfill included).

Unfortunately transform-orgin is not be the only property AI or other graphic applications might struggle with (it also depends on you version).

Recommendations:

  • Prefer svg style attributes like transform="rotate(45 100 100)"
    Especially svg's rotate() tends to be more robust, since it also allows to define pivot point coordinates
  • include xmlns, viewBox, xmlns:xlink, width, height attributes - otherwise AI might calculate wrong artboard dimensions.
  • relative (%) values tend to make troubles – better use userUnits (so unitless values like x="100")
  • if your svg contains use elements add legacy xlink:href references like <use id="sym1" href="#symbol1" xlink:href="#symbol1" />
  • Related