Authoring Zegs

Zegami’s intuitive interface empowers users to explore their data without the need to learn other complex data tools. While Zegami is extremely useful for displaying large collections of images, not all data sets have images. In keeping with our vision to make sense of data we need a way to represent a data point as a tile.

These tiles or Zegs are dynamic (rendered by the browser) and data-bound (the visual elements of the tile will be tied to the items metadata).

An example Zeg. Where the up and down arrow indicators are based on the % change value from the items metadata.

Zegs can be designed to render different levels of detail based on the size of the Zeg within the view. For example this is useful when the Zegs are very small as only simple colours are recognisable at this level. In the following example the colour of each Zeg is different based on the “Market Segment” value of the dataset.

Zegami has three levels of detail: smallmedium and large.

Authoring a Zeg #

A combination of SVG and XSLT was chosen as the languages to define a Zeg. The decision to use SVG was grounded in the fact that it’s used by many design tools such as Adobe Illustrator and Inkscape. As SVGs are described using XML, we can use XSLT transformations to add complex logic and data binding.

As a simple example to get started, we can create an svg element that contains a single rect element to draw a coloured box.

<svg width="68" height="68"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xsl:version="1.1"
>
    <rect y="0" width="68" height="68" fill="#a6bddb"/>
</svg>

The result is a simple square.

Data binding basics #

The above example simply renders a static coloured box regardless of the data provided  during the transformation process. It’s possible to use the XSLT process to bind data values.

For example, let’s imagine we have a data source with the following values of the table shown below.

We could use an SVG text element to draw the name value on to each Zeg

To achieve this, Zegami internally converts a data row into an XML document.

<row>
<value colname="name">Jane</value>
<value colname="performance">7</value>
<value colname="salary">100000</value>
</row>

It’s therefore possible to use XPath to select the values we want to bind.

We can use the combination of the xsl:value-of element with an XPath selector to write the name value in the transformation. An example of this is shown below.

<svg
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 width="64" height="64" xsl:version="1.1"
>
 <rect y="0" width="64" height="64" fill="#a6bddb" />
 <g>
   <text x="0" y="30" font-size="8px">
     <xsl:value-of select="row/value[@colname='name']" />
   </text>
 </g>
</svg>

 Which results in:


Conditional elements

XSLT supports conditional statements which means it is possible to render different elements based on the data values provided. An example of this would be to change the fill colour of the rect element.


This transformation essentially combines the information available both in the name’ column and the ‘fav colour’ column.


You can also use conditional statements to render based on different sizes, as the size’ attribute is passed in along with your item’s metadata as a property of the row object itself. For example:

<svg 
xmlns="http://www.w3.org/2000/svg" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
width="64" height="64" xsl:version="1.1"
>
 <xsl:choose>
   <xsl:when test="value[@colname='fav colour'] = ‘green'">
     <rect y="0" width="64" height="64" fill="#00FF00" />
   </xsl:when>
   <xsl:when test="value[@colname='fav colour'] = ‘red'">
     <rect y="0" width="64" height="64" fill="#FF0000" />
   </xsl:when>
   <xsl:otherwise>
     <rect y="0" width="64" height="64" fill="#0000FF" />
   </xsl:otherwise>
 </xsl:choose>
 <g>
   <text x="0" y="30" font-size="8px">
     <xsl:value-of select="row/value[@colname='name']" />
   </text>
 </g>
</svg>


Adding Images

The SVG image element is supported so that images can be mixed in with dynamic content. However, to support externally referenced images an additional xmlns:xlink namespace to be
present on the SVG element.

xmlns:xlink="http://www.w3.org/1999/xlink"

With this namespace available, we can use the xlink:href attribute to point an external image resource. This could also be combined with an XPath selector for dynamic images if your metadata has a URL to an image, multiple images can be combined. 

<svg
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 width="64" height="64" xsl:version="1.1"
>
 <rect y="0" width="64" height="64" fill="#a6bddb" />
 <g>
   <text x="0" y="30" font-size="8px">
    <xsl:value-of select="row/value[@colname='name']" />
</text>
<image
 x="8" y="3" width="48" height="48"
 preserveAspectRatio="none"
 xlink:href="http://localhost/avatar.jpg?id={/row/value[@colname=’id’]}"
/>
 </g>
</svg>

For security reasons, browsers may block image content that is loaded from a domain that is different from the host. In this scenario will not be loaded. You can work around this by creating a server side proxy page which can fetch the images for you.

Zeg Details levels #

When rendering very small tiles, it doesn’t make sense to have highly detailed Zegs as often the detail cannot be seen. It also hurts overall application performance, so a ‘size’ attribute is provided to help you render different levels of complexity based on the visual size.

We recommend using a simple element such as a single colour or letter at the ‘small’ size.

Using definitions in Zegs #

For zegs that use internal references using ids such as gradients and patterns, the id must be unique for each tile generated. An ‘index’ property is provided on the row input data can be used as a suffix for any id values to ensure this.

Zeg Optimisation  #

Using a combination of SVG and XSLT offers a good balance of speed and customisability. However when performing hundreds of transforms a second, they can perform poorly
unless some measures are taken to reduce the amount we render when viewing thousands of Zegs simultaneously.

Handling Variance #

When rendering Zegs at a small or medium level, the number of columns which actually affect the rendered output will likely be fewer than the total. The dynamic tile engine will attempt to reduce the number of transforms it has to perform if possible, but it requires a hint.

This technique works best if your column has a small amount of variety in the total possible values. Take the dataset for example below.

Each value in the first two columns is unique. Therefore, if we render our small sized Zeg using this data, we will have to render each one individually.

However, when rendering only using the fav colour’ column there are only three possible outcomes. Therefore, building our small sized zeg based on favourite colour would be much
faster as we would only need to perform a transformation three times.

This yields a substantial performance improvement. We do however need to explicitly declare that we are only concerned about that column at the small size. We can do this
using xsl:variables at the top of the XSLT.

<xsl:variable name="key_small" select="row/value[@colname='fav colour']"/>

You can use the concat function to combine multiple columns into the key, if you had two columns that your XSLT uses at a medium size as an example.

<xsl:variable name="key_medium" select="concat(row/value[@colname='fav colour'], row/value[@colname='performance'])"/>

The total possible variations increases, which reduces performance, but less than rendering each medium Zeg individually if multiple hundred are in view simultaneously.

Optimising your Dataset #

When the column you want to see when Zegs are ‘small’ has an overwhelming amount
of total variation, collection performance can be improved by a substantial amount by
passing additional columns for zeg optimisation.


For example, a column may have hundreds of numerical values, but your XSLT only
renders three possible background colours based on simple ‘less than-greater than’ logic.


Providing an additional pre-computed column which reduces these values to ‘Low’,
Medium’ and ‘High’ and using that column in the XSLT instead would greatly aid variance
optimisations using the ‘key_small’ variable.

Clipping Information #

Occasionally you might find it desirable to clip information such that text does not overflow given boundaries. This can be achieved using SVG clip paths, or by using transforms to tweak the text data to include and ellipsis after a set number of characters.

To create a clip path, you can wrap drawing functions inside a clipPath object. Objects can reference a clip path so that parts of the drawn object outside of the clip region are not shown.

<clipPath id="textClip">
 <rect x="10" y="10" width="80" height="80"/>
</clipPath>
<text clip-path="url(#textClip)" x="10" y="10">
 Lorem ipsum dolor sit amet
</text>

The effect is similar to using cookie cutters when baking, you define the shape with your clip path. 

This approach is a more simple alternative to trimming the text itself

There is not an elegant way of doing text wrapping inside XSLTs, a rational approach is to a limit of characters and then append an ellipsis in the event that the length of the text data exceeds this.

You can use the substring XSL function along with an XSL if statement to achieve this.

The following code declares the limit variable. The underscore in ‘_limit’ tells the dynamic tile manager to ignore it, otherwise it may be interpret it as keys or flags.

<xsl:variable name="_limit" select="8"/>
<text x="10" y="10">
 <xsl:value-of select="substring(row/value[@colname='NAME'],1,$_limit)"></xsl:value-of>
 <xsl:if test="string-length(row/value[@colname='NAME']) >= $_limit">...</xsl:if>
</text>

Tips for authoring with Inkscape #

Inkscape is a free, vector based, drawing tool that naively supports SVG files. Using Inkscape is a great way to produce high quality Zegs without having to spend too much time creating an SVG problematically. However there are a few things to keep in mind.

First in Document Properties set the Display units and Units to ‘px’. Then set the size of the svg, making sure the scale is 1 and the Viewbox is the same. This makes the units all sensible so that it’s easier to make code level tweaks when converting to XSLT.

Quite often it adds annoying top level group transforms which can make it tricky to make adjustments when creating the xslt. To get around this, open the XML Editor (Edit > XML Editor), find the node and then delete the transform attribute from the g node. 

When saving make sure that the type is Optimized SVG as this removes 90% of the junk that Inkscape adds to the file.

We’ve also found that radial gradients and masks don’t work. Also linear gradients fail in IE. Once the SVG markup is sensible then it’s usually fairly straight forward to add the XSLT.

Powered by BetterDocs