Building the Mall
SVG is an XML document, and as such, prior to establishing the document element of the SVG, you can specify a stylesheet. The Mall.svg (Listing 2
) file does so declaring a (more or less) standard CSS stylesheet. Though these are principally used for defining CSS classes rather than setting individual element appearances directly:
<?xml-stylesheet type="text/css" href="mall.css"?>
This mall.css (Listing 3
) file contains a series of class definitions, which in general look like the following:
Note that you can reference certain paint servers, such as gradients, within a CSS style using the fill:url() notation and placing a reference to an external item.
viewBox="0 0 11000 8500"
The <svg> element then specifies the width and height of the container and creates a ViewBox (a graphics context) with the origin at the upper left corner, and 1000 user units per inch of height. It's worth remembering here that the user coordinate system only provides an abstract coordinate layerthe SVG processor will map this abstract coordinate system into the physical pixel coordinates used by the operating system.
The SVG <defs> block is used to define static graphics primitives. Some of the more useful of these are custom gradients that can be used here to signify certain states for the stores and for the category buttons. The semantics of the gradients id make it possible to define "colors" that have specific relevancesuch as the "store" and "storeHighlight" colors, defining the neutral and highlighted (rolled over) state of any store (or store-like region, such as a bathroom or information kiosk).
<linearGradient id="store" gradientTransform="rotate(45)">
<stop offset="0%" stop-color="blue"/>
<stop offset="100%" stop-color="navy"/>
<stop offset="0%" stop-color="white"/>
<stop offset="100%" stop-color="lightBlue"/>
<!-- more gradients -->
In addition to the gradients, the defs section also defines the standard "button" used for selecting a given category:
<g id="categoryTemplate" onclick="showStoresByCategory('template')">
<rect id="template_box" width="200" height="200" x="-220" class="categoryBox"/>
<text id="template_text" class="legendText">template_label</text>
The <g> element bundles both the rectangle and the associated text box together into a single unit, setting up a format in which the word "template" will get replaced with the appropriate category ID. For instance, the code for "restaurants" would use the template to generate a button which looks like this:
<g id="restaurants" onclick="showStoresByCategory('restaurants')">
<rect id="restaurants_box" width="200" height="200" x="-220" class="categoryBox"/>
<text id="restaurants_text" class="legendText">Restaurants</text>
The mall itself is outlined with a thicker border, and can be selected as a separate entity on a mouseover, which handles displaying "default" information using the displayInfo() function. This is defined later in the scripts.
<g id="MallOutline" onmouseover="displayInfo(evt)">
<rect id="background" class="background" x="0" y="500" width="13000" height="8000"/>
<path id="outline" class="mall" _
d="M10972 6979l0 -2492 -4246 -13 0 -3547 -2386 0 0 3574 -4285 0 -14 2478 10931 0z"/>
Each store's shape is defined using one or more graphical primitives (usually, but not always, paths), contained in a single <g> element that acts as the aggregator for events:
<g id="storeLayer" onmouseover="displayInfo(evt)" onmouseout="restore(evt)"_
<path id="store01" class="store" d="M3285 4517 l0 883 653 0 0 -883 -653 0z"/>
<path id="store02" class="store" d="M2685 4880 l0 520 600 0 0 -883 -376 0 0 363 -224 0z"/>
<path id="store03" class="store" d="M3938 4517 l0 883 652 0 0 -883 -652 0z"/>
<path id="store04" class="store" d="M2210 5404 l475 -4 0 -520 224 0 0 -363 -699 0 0 887z"/>
Each store's id
ties it to the XML document defined previously, while the class attribute applies the appropriate CSS class to each shape. Note that again the displayInfo()
function is invoked on a mouseover, overriding the invocation on the previous shapes. The showVideo()
function is called upon a mouseclick to begin a video.
The use of the evt object here can seem to be a little confusing. Within SVG, every time an event handler invokes a function, the SVG processor passes an event object in after all declared parameters. This object can be queried for information about which object the event occurred to, what event was invoked, and in mouse-centric activities, where the mouse was relative to the client window. The evt parameter used here is undefined and is for placeholder value only; the more salient evt parameter on the function declaration wil contain an instance of the event.
The next layer is strictly an SVG 1.2 featurethe use of the <foreignObject> tag to embed HTML content that can later be referenced. In this case, the tag displays the description and title of each shop in the upper-left hand area:
<g id="storeNameLayer" transform="translate(200,1000)">
<svg width="2400" height="3200" viewBox="0 0 250 250">
<foreignObject width="250" height="250">
<h1 id="storeName">Sophisticated Mall</h1>
<p id="storeDesc">Sophisticated Stores for the Discriminating Shopper.</p>
Significantly, even though this information is in a "foreign" namespace, the SVG DOM can in fact manipulate it. Thus both storeName and storeDesc can be populated with new content through DOM calls. This gives you at least a subset of Dynamic HTML within the SVG environment. The HTML is displayed relative to its internal viewBox coordinate system.
When a store is moused over, a picture is displayed in the upper-right hand side. When the store is clicked, this initiates a video (SVG 1.2 only). These need to be placed within the environment, even if they inititally do not point to anything useful.
<g id="storeImageLayer" transform="translate(6900,1000)">
<image id="storeImage" xlink:href="" width="4000" height="3000">
<g id="storeVideoLayer" transform="translate(6900,1000)">
<video id="storeVideo" xlink:href="" width="4000" height="3000" restart="always" begin="storeLayer.click"/>
The video element in particular illustrates some of the power of the declarative paradigm. The link (xlink:href) points to the video resource, with the specific formats dictated by the given SVG viewer. For instance, the Adobe SVG viewer beta currently works with Microsoft AVI, MPEG, Quicktime, Shockwave, and other formats. The begin attribute indicates that whenever the storeLayer (or any item within the story layer) is clicked, the movie should start, while the restart attribute indicates that whenever the event is invoked, the video should start over. The specific resource is set using the xlink:href attribute.
The final two lines in the SVG (before it's closed out with the </svg> tag) define the location where the legend is drawn, and point to the location of the scripts respectively. Note that the syntax for the <script> element in SVG differs significantly from that of HTML:
<g id="legend" transform="translate(1000,7200)">
It is worth noting in general that the principal purpose of the SVG is to either define the resources or establish the location in the local coordinate system where particular pieces end up appearing. In this role, SVG acts more like an application such as Visual Basic, placing the components in place then letting the code layer handle the otherwise undefined state management of these components.