phiz

Guides

Rendering

Specifications

toArray() returns the Vega-Lite specification and toJson() encodes it. Plots also implement JsonSerializable. The specification declares the Vega-Lite 6 schema.

Four escape hatches reach the parts of Vega-Lite that phiz does not wrap:

  • raw([...]) deep-merges arbitrary Vega-Lite into the top level. Nested objects merge, and lists and scalars replace.
  • transform(...) adds Vega-Lite transforms that run before every layer.
  • layer([...]) adds a raw Vega-Lite layer.
  • param() and select() add raw parameters.

HTML

embed() returns a container element followed by the script tags, and html() returns a standalone page. Both pass vega-embed options, such as ['actions' => false] or ['renderer' => 'svg'].

The container carries the specification in a data-phiz attribute. A small loader script, about 100 lines, renders every such element with vega-embed. It renders them again when the attribute changes. The same markup therefore works in static pages, Blade views, and Livewire components.

The browser libraries are pinned:

Library Version
vega 6.4.0
vega-lite 6.4.3
vega-embed 7.3.0

Assets chooses where they come from:

use Phiz\Assets;

$plot->embed(assets: Assets::cdn());                 // jsDelivr, with subresource integrity (the default)
$plot->embed(assets: Assets::local('/js/vega'));     // copies you serve: vega.min.js, vega-lite.min.js, vega-embed.min.js
$plot->html(assets: Assets::inline('/path/to/js'));  // embedded in the page, for offline files
$plot->embed(assets: Assets::none());                // your bundle already sets window.vegaEmbed
$plot->embed(assets: false);                         // just the container

Static export

svg(), png(), pdf(), and save() run the vl-convert command-line tool. It renders without a browser, which suits reports, email, and print. vl-convert bundles its own Vega-Lite, and phiz runs it with Vega-Lite 6.1. The test suite validates every specification against the Vega-Lite 6.1 schema, so the same specification renders in both places.

$plot->save('figure.svg');
$plot->save('figure.png', scale: 3);
file_put_contents('figure.pdf', $plot->pdf());

phiz finds the binary through the PHIZ_VL_CONVERT or VL_CONVERT environment variable, then PATH. Download it from the vl-convert releases. Version 1.9.0 is tested. If the binary is missing, phiz throws Phiz\Exceptions\VlConvertNotFound with these instructions. new Export(binary: ..., timeout: ..., fontDir: ...) sets the binary path, the timeout, and an extra font directory explicitly.

Installing vl-convert

vl-convert has no Homebrew formula or apt package. Each release ships a self-contained binary for macOS (osx-arm64, osx-64) and Linux (linux-64, linux-aarch64). The Linux binaries link only against glibc and zlib, so they run on a bare Ubuntu image with no fonts or other packages installed. On Ubuntu the install is:

curl -sSLo /tmp/vl-convert.zip https://github.com/vega/vl-convert/releases/download/v1.9.0/vl-convert_linux-64.zip
sudo unzip -j -o /tmp/vl-convert.zip bin/vl-convert -d /usr/local/bin
vl-convert --version

On macOS, download vl-convert_osx-arm64.zip from the same release and unzip it the same way. The macOS binary has only an ad hoc signature. A copy fetched with curl or gh release download is not quarantined and runs directly. If a browser download is quarantined, xattr -d com.apple.quarantine vl-convert clears the flag. Put the binary in a directory on PATH, or point PHIZ_VL_CONVERT at it.

Reproducible SVG

SVG output from a given specification is byte-for-byte identical between runs, except for charts with unseeded jitter. Without seed:, jitter() uses Vega’s unseeded random(), so a jittered chart changes on every render. With seed:, the offsets are part of the specification and the output is stable. It is also identical between macOS and Linux, between ARM and x86, and with or without system fonts installed. vl-convert measures sans-serif text with its bundled Liberation Sans, so the layout does not depend on the machine’s fonts. The SVG keeps its text as <text font-family="sans-serif"> elements, so the viewer’s browser chooses the font that is displayed.

Committed SVG files therefore change only when the specification, the vl-convert version, or the pinned Vega-Lite version changes. A theme that names a font other than sans-serif, or an export with fontDir:, makes text measurement depend on the fonts available to vl-convert. Pin the vl-convert version wherever committed figures are generated.

From phpstats/phiz@bc7ed3e.