Home > Blockchain >  html css svg path align center on screen
html css svg path align center on screen

Time:02-16

I want to show dynamically svg but every time svg position is changing and sometimes overflowing from screen. I want to alignt this svg path center of screen.

function App() {
  const [city, setCity] = useState("");

  useEffect(() => {
    setCity(cities[Math.floor(Math.random() * cities.length)]);
  }, []);

  return (
    <div>
      <div className="svg-div">
        <svg height="100%" width="100%" className="svg" viewBox="0 0 600 600">
          <g>
            <path id="city" d={city?.d} />
          </g>
        </svg>
      </div>

      <Input cities={cities} />
    </div>
  );
}

export default App;

enter image description here

enter image description here

CodePudding user response:

Add this css . svg-div{ display: flex: justify-content: center; align-items: center; }

CodePudding user response:

Most likely your dynamically retrieved paths are parts of a complete map svg.

So the surrounding space or overflow ist caused by the paths' coordinates which are relative to the original map viewBox.

Example 1: extracted map region

.svgAssetHidden {
  visibility: hidden;
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.map,
.svg-use
{
  display: block;
  width: 20em;
  border: 1px solid #ccc;
  fill:#ccc;
}

.map path{
  stroke-width:2;
  stroke:#fff;
}
<p>Complete map</p>
<svg id="svgMapComplete"  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <path id="region1" d="M36.4 21.3l-5.9-11.8l7.3-1l2.9 2.8l7.3-1.9l-2.6-3.9l-1.5-3.1l7.1-2.3l13.6 3.3l25.7-1.2l3.6 3.9l-12 6.4l-3.6 7.1l-29 7.4l-12.9-5.7z" />
  <path id="region2" d="M100.1 30.2l-3.7 11.2l-9.5 15.1c0 0-26.1 1.3-27.4 1.3c-1.2 0-2.9 8.4-3.4 10.7l-19.1-2.2l-6.5-15.1l-3.3-12.9l-21.4-12.3l6.8-9.4l10.9-6.2l7-1l5.9 11.7l13 5.9l29-7.4l-1.4 2.7l9.6 3.7l10.8-5.4l2.7 9.6z" />
  <path id="region3" d="M37 66.3l19.2 2.2c0 0.1 0 0.2-0.1 0.3c-0.4 1.8-10 6.8-10 6.8l-32.3 24.2l-13.8-6.7l4.1-26.8l6.3-11.4l-2.8-10.7l-6.3-11.9l4.5-6.3l21.4 12.2l3.3 12.9l6.5 15.2z" />
</svg>

<p>Map fragment – display region</p>
<svg id="svgMapCompletePart"  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
  <path id="region3" d="M37 66.3l19.2 2.2c0 0.1 0 0.2-0.1 0.3c-0.4 1.8-10 6.8-10 6.8l-32.3 24.2l-13.8-6.7l4.1-26.8l6.3-11.4l-2.8-10.7l-6.3-11.9l4.5-6.3l21.4 12.2l3.3 12.9l6.5 15.2z" />
</svg>

The southwestern region still has surrounding space since it's relative to the parent map's initial viewBox.

To circumvent this problem you could wrap all path elements in a <symbol>element containing its own viewbox – you will need to get each region's boundary box via getBBox().

Example 2: show regions wrapped in symbol elements

/**
 * select
 */
let svg = document.querySelector("#svgMap");
let regions = svg.querySelectorAll("path");

/**
 * query elements to be wrapped in symbols
 **/
function wrapSymbols(parent, els) {
  els.forEach(function(el, i) {
    let symbol = wrapSymbol(el, i);
    parent.appendChild(symbol);
  });
}

/**
 * wrap path in symbol element
 **/
function wrapSymbol(el, i = 0) {
  let symbol = document.createElementNS("http://www.w3.org/2000/svg", "symbol");
  symbol.id = el.id ? "symbol-"   el.id : "symbol-"   i;
  let symbolBB = el.getBBox();
  let symbolVBox = [symbolBB.x, symbolBB.y, symbolBB.width, symbolBB.height];
  symbolVBox.forEach(function(el, i) {
    symbolVBox[i] =  symbolVBox[i].toFixed(2);
  });
  symbol.setAttribute("viewBox", symbolVBox.join(" "));
  symbol.insertAdjacentElement("beforeend", el);
  return symbol;
}

/**
 * create example use html
 **/
function getExampleUseHTML(el) {
  let useHtml = "";
  let symbols = document.querySelectorAll("symbol");
  symbols.forEach(function(el, i) {
    let vB = el.getAttribute("viewBox").split(" ");
    useHtml  =
      '<svg  viewBox="0 0 '  
      vB[2]  
      " "  
      vB[3]  
      '">\n'  
      '<use  href="#'  
      el.id  
      '" />\n'  
      "</svg>\n";
  });
  return useHtml;
}

/**
 * render example use html
 */
wrapSymbols(svg, regions);
let useHTML = getExampleUseHTML(svg);
document.body.insertAdjacentHTML(
  "beforeend",
  '<div >'   useHTML   "</div>"
);
.svgAssetHidden {
  visibility: hidden;
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.map-cell-flex {
  display: flex;
  flex: 1;
}

.map,
.svg-use {
  border: 1px solid #ccc;
  fill: #ccc;
}
<p>Map fragment – display region by use element</p>
<svg id="svgMap"  xmlns="http://www.w3.org/2000/svg">
  <path d="M36.4 21.3l-5.9-11.8l7.3-1l2.9 2.8l7.3-1.9l-2.6-3.9l-1.5-3.1l7.1-2.3l13.6 3.3l25.7-1.2l3.6 3.9l-12 6.4l-3.6 7.1l-29 7.4l-12.9-5.7z" />
  <path d="M100.1 30.2l-3.7 11.2l-9.5 15.1c0 0-26.1 1.3-27.4 1.3c-1.2 0-2.9 8.4-3.4 10.7l-19.1-2.2l-6.5-15.1l-3.3-12.9l-21.4-12.3l6.8-9.4l10.9-6.2l7-1l5.9 11.7l13 5.9l29-7.4l-1.4 2.7l9.6 3.7l10.8-5.4l2.7 9.6z" />
  <path d="M37 66.3l19.2 2.2c0 0.1 0 0.2-0.1 0.3c-0.4 1.8-10 6.8-10 6.8l-32.3 24.2l-13.8-6.7l4.1-26.8l6.3-11.4l-2.8-10.7l-6.3-11.9l4.5-6.3l21.4 12.2l3.3 12.9l6.5 15.2z" />
</svg>

Once you've wrapped your path elements in a symbol you can place your regions via <use>

Symbol definition:

<symbol id="symbol-0" viewBox="30.5 0.1 63.4 26.9">
    <path d="M36.4 21.3l-5.9-11.8l7.3-1l2.9 2.8l7.3-1.9l-2.6-3.9l-1.5-3.1l7.1-2.3l13.6 3.3l25.7-1.2l3.6 3.9l-12 6.4l-3.6 7.1l-29 7.4l-12.9-5.7z" />
</symbol>

Use instance:

<svg  viewBox="0 0 63.4 26.9">
   <use  href="#symbol-0" />
</svg>  
  • Related