ckportfolio.com - Manual SVG visualization with PHP

Manual SVG visualization with PHP

Setup

As we move onto creating a simple visualization of daily weather forecast data with SVG, we can start by setting up the drawable region in svg.php, complete with a first heading that serves as a buffer between the page and the browser address bar. In addition, we can also insert a faint rectangle that paints the entire region for visibility:

svg.php

<h1 class="my-3">SVG</h1>
<svg id="example" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#EEEEEE"></rect>
</svg>

The result is a 100 by 100 square SVG region that stretches across the column.

PHP Loop and SVG Elements

Using PHP, we will be looking through the forecase information via loop and create horizontal bars that represent individual entries. Because we can expect a total of 6 or 7 entries in the previously created forecast variable, we can experiment with the offset as the following:

svg.php

<h1 class="my-3">SVG</h1>
<svg id="example" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#EEEEEE"></rect>

    <? foreach ($forecast as $i => $entry) { ?>

        <rect x="10" y="<?= $i * 11 + 10 ?>" width="80" height="3" fill="crimson"></rect>

    <? } ?>

</svg>

Note that we are creating various <rect> objects through this loop: while we are keeping the various attributes (x, ,width, height, and fill) static, we are relying on each array entry's numerical key ($i) to generate a suitable y value. We are multiplying the key by a specific number, and adding an offset to bring the resultant bars a little further down.

Above each bar, we can insert a text component that displays the date as well as the temperature:

svg.php

...
    <? foreach ($forecast as $i => $entry) { ?>

        <?

            $date = date("F j, Y (l)", $entry->time);
            $low = round(($entry->temperatureLow - 32)*5/9);
            $high = round(($entry->temperatureHigh - 32)*5/9);
        ?>

        <rect x="10" y="<?= $i * 11 + 10 ?>" width="80" height="3" fill="crimson"></rect>

        <text x="10" y="<?= $i * 11 + 8 ?>" style="font-size:3px;"><?= date("F j, Y (l)", $entry->time) ?></text>
        <text x="90" y="<?= $i * 11 + 8 ?>" style="font-size:2px" text-anchor="end">
            Low <?= $low ?>&deg;
            High <?= $high ?>&deg;
        </text>

    <? } ?>
...    

Dark Sky API does not give us values that we can directly work with: the date is only available as a UNIX timestamp, and the temperature values are in the Fahrenheit scale. We can resolve this issue by using date() to convert the timestamp into a more user-friendly format, and apply simple arithmetic to update the temperatures into the Celsius scale.

Finally, we can have the rectangle widths to map to the corresponding high (or low) temperate values. This requires slightly more complex calculation to identify the minimum and maximum range of the bar width, but for simplicity, we can hard code the values for this exercise:

svg.php

...
    <rect x="10" y="<?= $i * 11 + 10 ?>" width="<?= 60 + $low * 3 ?>" height="3" fill="crimson"></rect>
...

Note that we are setting the default width to 60, and setting the offset based on the low temperature value multiplied by 3. While this method is far from being fool-proof in situations where the temperature values are higher, it serves as a sufficient example for mapping SVG graphics to data points from an external source.

Fin