居中 SVG 路径

Centering a SVG path

有没有办法将我的 <path> 置于 SVG 文件的中心?

这是我的 SVG: xml

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72">
    <rect width="100%" height="100%" fill="#444444" />
    <path d="M5.7 0L1.4 10.985V55.88h15.284V64h8.597l8.12-8.12h12.418l16.716-16.716V0H5.7zm51.104 36.3L47.25 45.85H31.967l-8.12 8.12v-8.12H10.952V5.73h45.85V36.3zM47.25 16.716v16.716h-5.73V16.716h5.73zm-15.284 0v16.716h-5.73V16.716h5.73z" fill="#6441A4" />
</svg>

添加合适的变换。这似乎相当接近:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72">
    <rect width="100%" height="100%" fill="#444444" />
    <path fill="#6441A4" 
          transform="translate(3.95 3.95)" 
          d="M5.7 0L1.4 10.985V55.88h15.284V64h8.597l8.12-8.12h12.418l16.716-16.716V0H5.7zm51.104 36.3L47.25 45.85H31.967l-8.12 8.12v-8.12H10.952V5.73h45.85V36.3zM47.25 16.716v16.716h-5.73V16.716h5.73zm-15.284 0v16.716h-5.73V16.716h5.73z"/>
</svg>

另一个快速修复可以设置 negative viewBox x/y values 像这样:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3.95  -3.95  72 72" >
 <rect x="-3.95" y="-3.95" width="100%" height="100%" fill="#444444" />        
 <path fill="#6441A4" 
          d="M5.7 0L1.4 10.985V55.88h15.284V64h8.597l8.12-8.12h12.418l16.716-16.716V0H5.7zm51.104 36.3L47.25 45.85H31.967l-8.12 8.12v-8.12H10.952V5.73h45.85V36.3zM47.25 16.716v16.716h-5.73V16.716h5.73zm-15.284 0v16.716h-5.73V16.716h5.73z"/>
</svg>

有点hacky,特别是如果你需要像<rect>这样的背景元素。

通过重新计算路径坐标来居中和缩放

很可能,转换工作得很好,应该是您的第一选择。
如果您需要对转换进行“硬编码”——这并不太复杂:

let svg = document.querySelector(".svg");
let path = svg.querySelector("path");
let bBox = svg.getBBox();
let vBox = svg.getAttribute("viewBox");
let vBoxArr = vBox ? vBox.split(" ") : [0, 0, bBox.width, bBox.height];


scalePathProportional(path, 0.75);
centerPath(path, true, true);

function centerPath(path, centerX= true, centerY=true, precision=3, render=true){
  let svg = path.closest('svg');
  let viewBox = svg.getAttribute('viewBox');
  let bBox = svg.getBBox();
  viewBox = viewBox ? viewBox.split(' ') : ([bBox.x, bBox.y, bBox.width, bBox.height]);  
  let offXnorm = viewBox[0] * (-1);
  let offYnorm = viewBox[1] * (-1);
  
  // convert to relative to move only M
  let dRel = snapPathToRelative(path, 1);
  let pathBB = path.getBBox();
  let pX = pathBB["x"];
  let pY = pathBB["y"];
  // get x/y offsets to center path
  let shiftX = (viewBox[2] - pathBB.width) / 2  - pX ;
  let shiftY = (viewBox[3] - pathBB.height) / 2 - pY;
  // save them to pathData
  dRel[0][1] = (dRel[0][1] + shiftX).toFixed(precision) * 1;
  dRel[0][2] = (dRel[0][2] + shiftY).toFixed(precision) * 1;
  // apply change
  if(render){
      path.setAttribute('d',dRel.toString());
  }
  return dRel;
}

//scale to path to width and height by units or percentages
function scalePathProportional(path, scale=1) {
  let svg = path.closest("svg");
  let pathData = path.getPathData();
  pathData.forEach(function (command, p) {
    let coords = command.values;
    //scale coordinates if viewBox < 1000 units
    if (scale!==1) {
      coords.forEach(function (el, i) {
        coords[i] = coords[i] * scale;
      });
    }
  });
  path.setPathData(pathData);
  return pathData;
}


function snapPathToRelative(path, precicion=null, render=false){
  let d = path.getAttribute('d');
  let pathRel = Snap.path.toRelative(d);
  if(precicion){
    roundCoords(pathRel)
  }
  if(render){
      path.setAttribute('d', pathRel.toString());
  }
  return pathRel;
}

function roundCoords(commands, decimals=1){
commands.forEach(function (coordinates, i) {
        let coordRelative = [];
        coordinates.forEach(function (coordinate, v) {
            if (typeof coordinate === 'number') {
                coordinate = (coordinate).toFixed(decimals) * 1
            }
            coordRelative.push(coordinate);
        });
        commands[i] = coordRelative;
    });
    //console.log(commands)
    return commands;
}
svg {
  display: inline-block;
  height: 5em;
  font-size: 1em;
  border: 1px solid #ccc;
  background-color:#444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/path-data-polyfill@1.0.3/path-data-polyfill.min.js"></script>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72">
    <rect width="100%" height="100%" fill="#444444" />
    <path d="M5.7 0L1.4 10.985V55.88h15.284V64h8.597l8.12-8.12h12.418l16.716-16.716V0H5.7zm51.104 36.3L47.25 45.85H31.967l-8.12 8.12v-8.12H10.952V5.73h45.85V36.3zM47.25 16.716v16.716h-5.73V16.716h5.73zm-15.284 0v16.716h-5.73V16.716h5.73z" fill="#6441A4" />
</svg>

按比例缩放 d 坐标
需要遍历所有路径命令并将所有坐标乘以比例因子(如 0.75)。 要获取路径数据,我使用 Jarek Foksa's pathData polyfill

居中路径
涉及父 svg 的 viewBox 和实际路径边界之间的一些比较(通过 path.getBBox() 检索)。
要实际水平和垂直移动路径 x/y 偏移量,我们可以通过将路径命令转换为相对坐标(使用 snap.svg's toRelative(d).
来简化任务 现在我们只需要更改 M 命令的 x/y 坐标(另见 Lea Verou 的 post Convert SVG path to all-relative or all-absolute commands

**免责声明:不适用于现场使用**
这种方法应该用于自定义 svg pre-optimizing。所以 运行 脚本 - re-save 你的 svg 资源。