Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 inline SVG autocrop whitespace

I've got an SVG diagram (complicated a little) that is generated using php and some data from the database. In that case, I can't predict the length of labels on the svg and anything. Diagram is generated on the fly, and data is always unknown. That is why, I'm starting with this:

<svg class="chart" id="chart1" viewBox="0 0 1000 1000">

I'm setting huge viewbox (1000, 1000) and I start generating SVG somewhere in the middle of this viewbox. After that, some elements are near the left sometimes, another one near top, and for example at the bottom I've got 200 blank space rectangle.

Is there any option for autocropping whitespace in SVG to match content? I've got an intuition that my idea isn't good, I'm missing something or doing something terribly wrong.

Let's say that this can be an example of the final product (copyright wikipedia): http://upload.wikimedia.org/wikipedia/commons/f/f4/Wiggers_Diagram.svg

I'm not putting any further code here, as it doesn't make sense the SVG generation function is really huge and complicated and the problem corresponds to the final result rather.

Any solution or idea will be appreciated, The problem corresponds to html5 and svg (tags) but the solution can be also javascript or css (if exists).


Update: I was asked for real demo (minimal):

.chart {
  overflow: auto;
  position: relative;
  border: 1px solid #ccc;
  width: 500px;
  background: #fff;
}
.chart .point {
  stroke: #555;
  stroke-width: 10;
  fill: #000;
}
.chart .plot {
  stroke: #aaa;
  stroke-width: 2;
}
.chart .popup {
  fill: #000;
  font-family: sans-serif;
}
.chart .axis {
  stroke: #aaa;
  stroke-width: 1;
}
.chart .grid {
  stroke: #ccc;
  stroke-width: 1;
}
.chart .legend {
  fill: black;
  font-family: sans-serif;
}
.region:hover .popup {
  visibility: visible;
}
<svg class="chart" id="chart" viewBox="0 0 1000 500">
  <line x1="110" y1="300" x2="1000" y2="300" class="grid" />
  <text x="110" y="300" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end">0</text>
  <line x1="110" y1="240" x2="1000" y2="240" class="grid" />
  <text x="110" y="240" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end">1</text>
  <line x1="110" y1="180" x2="1000" y2="180" class="grid" />
  <text x="110" y="180" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end">2</text>
  <line x1="110" y1="120" x2="1000" y2="120" class="grid" />
  <text x="110" y="120" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end">3</text>
  <line x1="130" y1="0" x2="130" y2="300" class="axis" />
  <line x1="130" y1="300" x2="1000" y2="300" class="axis" />
  <line x1="227" y1="300" x2="323" y2="300" class="plot" />
  <line x1="323" y1="300" x2="420" y2="300" class="plot" />
  <line x1="420" y1="300" x2="517" y2="300" class="plot" />
  <line x1="517" y1="300" x2="613" y2="300" class="plot" />
  <line x1="613" y1="300" x2="710" y2="60" class="plot" />
  <line x1="710" y1="60" x2="807" y2="300" class="plot" />
  <line x1="807" y1="300" x2="903" y2="300" class="plot" />
  <g class="region" id="chart_point_0">
    <rect x="178.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="227" cy="300" class="point" r="5" />
    <text x="227" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 227,320)">2014-05-04</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="227" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_1">
    <rect x="274.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="323" cy="300" class="point" r="5" />
    <text x="323" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 323,320)">2014-05-05</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="323" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_2">
    <rect x="371.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="420" cy="300" class="point" r="5" />
    <text x="420" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 420,320)">2014-05-06</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="420" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_3">
    <rect x="468.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="517" cy="300" class="point" r="5" />
    <text x="517" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 517,320)">2014-05-07</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="517" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_4">
    <rect x="564.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="613" cy="300" class="point" r="5" />
    <text x="613" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 613,320)">2014-05-08</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="613" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_5">
    <rect x="661.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="710" cy="60" class="point" r="5" />
    <text x="710" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 710,320)">2014-05-09</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="710" y="40" font-size="30" visibility="hidden">4</text>
  </g>
  <g class="region" id="chart_point_6">
    <rect x="758.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="807" cy="300" class="point" r="5" />
    <text x="807" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 807,320)">2014-05-10</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="807" y="280" font-size="30" visibility="hidden">0</text>
  </g>
  <g class="region" id="chart_point_7">
    <rect x="854.66666666667" fill="transparent" y="0" width="96.666666666667" height="500" />
    <circle cx="903" cy="300" class="point" r="5" />
    <text x="903" y="320" font-size="30" dominant-baseline="middle" class="legend" text-anchor="end" transform="rotate(270 903,320)">2014-05-11</text>
    <text class="popup" text-anchor="middle" dominant-baseline="bottom" x="903" y="280" font-size="30" visibility="hidden">0</text>
  </g>
</svg>

In this case the diagram is ths smallest one. I've got 8 - 12 times bigger and much more complicated once. Thx for the comment.

like image 225
Jacek Kowalewski Avatar asked May 09 '14 08:05

Jacek Kowalewski


1 Answers

Building off this answer and the above comments:

var svg = document.getElementsByTagName("svg")[0];
var bbox = svg.getBBox();
var viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ");
svg.setAttribute("viewBox", viewBox);

If you really need a non-JS solution: convert to PNG (or any other lossless format), then use trim to lop off the whitespace. You can do this from within PHP.

like image 171
candu Avatar answered Oct 31 '22 17:10

candu