public interface SvgSymbols
SVG can be loaded directly in a page and, when loaded in this way, can be accessed/modified in JavaScript and affected by CSS at runtime. However, such modifications can be costly and are known to cause flickering in some browsers, due to files being reloaded and necessary DOM changes when images are reloaded/updated.
sprite:svg:
.
This approach is great for working with SVG graphics in your app because it works for any SVG and doesn't cause server trips or make sizable DOM modifications. However, it does require some preparation and has limits in terms of runtime styling.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" > <symbol id="icon-play" viewBox="0 0 32 32"> <path d="M6 4l20 12-20 12z"></path> </symbol> <symbol id="icon-pause" viewBox="0 0 32 32"> <path d="M4 4h10v24h-10zM18 4h10v24h-10z"></path> </symbol> </svg>
An <svg> container structured in this way will not be rendered in the browser, but the
<symbol>s it defines are made available as a set of templates which
can be re-used later in src
strings, via the special prefix
"sprite:svg:". The format of src
strings differs slightly according
to where your <svg> container is defined. If it's defined inline in the HTML, only
the fragment-id is required - for example
src: "sprite:svg:#icon-play"If it's defined in a separate file, you must also specify which file:
src: "sprite:svg:path/to/fileName.svg#icon-play"When the external file-name is specified in this way, there is no need for the developer to explicitly load the file.
Note that this mechanism is not explicitly supported in any version of Internet Explorer, since that browser has never had full SVG support.
Since SVG is XML-based, individual SVG editors and other tools often write additional metadata into .svg files. This extra context is not relevant to using these graphics as symbols in the framework and can usually be entirely removed without ill effects. For example, here is a .svg file exported from a popular image-editing software and its equivalent symbol element-content.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="someID" x="0px" y="0px" viewBox="0 0 2500 2500" enable-background="new 0 0 2500 2500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><defs id="defs1" /> <path fill-rule="evenodd" clip-rule="evenodd" d="M1237.77,0.57c-33.09,4.54-61.94,30.54-70.21,63.29 ..." id="path1" style="fill:#3d618a;fill-opacity:1" /> </svg>
Following the instructions above, this .svg will end up as a runtime-stylable symbol like this:
<symbol id="add" viewBox="0 0 2500 2500" > <path fill-rule="evenodd" clip-rule="evenodd" d="M1237.77,0.57c-33.09,4.54-61.94,30.54-70.21,63.29 ..." id="path1" style="fill:currentColor;fill-opacity:1" /> </symbol>
"sprite:svg:[path-to-file.svg]#[symbolId];"Additional supported properties include:
Img.imageWidth
or
FormItem.pickerIconWidth
- if no such sizes exist, SVGs will be rendered at the
browser's default size for symbols, which is typically 300x150.
See below for example usages.
At its most basic, individual graphics elements in a <symbol> which do not specify colors inline can be easily modified. If all child elements are unstyled (ie, the symbol is single-color, even if it has multiple child graphics), the image-color can be changed as a whole by applying external CSS that sets the SVG fill and stroke settings to different colors. If some child elements have inlined styles, they will not be modified by such external CSS - this means that certain parts of a <symbol> can be of a fixed-color, via inlined styles, while other parts can be left unstyled and can be customized via external CSS later, to highlight only those unstyled parts.
Note, however, that this is not the recommended approach: Applying custom styles via fill and stroke can be difficult to achieve consistently across different images, which may use fills or strokes in any combination, or use "compound paths" to render what looks like a stroked line-drawing but is actually various filled shapes. We provide a sample of this mechanism in our online showcase - the graphics in this sample are all stroked lines which also form closed-shapes, meaning that both stroke and fill have an effect; but this is unlikely to be true in many cases.
fill="currentColor"
or
style="fill:currentColor;"
. This value is always equal to the
current/inherited CSS color
and can be
referenced by graphics elements. If your CSS class sets fill
and
color
to different values, graphics elements that use currentColor
will assume the color
value.
To achieve this, your SVGs will need to be saved with fill/stroke colors inline where they apply, and the parts that should change color later should all use the same known color. As part of preparing your symbol, find and replace that known color with "currentColor". Now, when this graphic is used later, any parts with fill or stroke set to "currentColor" will inherit the CSS "color" value from its container, or from a "cssClass" or "color" setting in the src string.
As noted above, it's also possible to fully re-style more complex, multi-color SVG - but this involves ensuring that all styling is externalized and backed by CSS; these details are highly dependent on the graphics and as such are the responsibility of the graphics designer or generator tool.
For demonstration code, see the SVG Symbols sample in our online showcase
svgIcon
style that you can use or modify for this purpose, or you can create
your own custom styles. However, note that this technique can be inconsitent depending on
design-choices across images, as described above
// grey color changing to red on rollover .icon { color: grey; } .iconOver { color: red; }This class can then be applied to a stateful widget housing a symbol, via its
baseStyle
or similar, or by
including it directly in src
strings via "cssClass", or as separate per-state
URLs in an SCStatefulImgConfig
object.
isc.Img.create({ // show stateful styles showRollOver: true, // use baseStyle for statefulness src: "sprite:svg:fileName.svg#icon-id;", baseStyle: "icon" // or, use cssClass in config-strings for statefulness src: "sprite:svg:fileName.svg#icon-id;cssClass:icon;" // or, use a specific cssClass for each state, in an SCStatefulImgConfig block // - note, all states are supported, but this sample code only shows 2 src: { _base: "sprite:svg:fileName.svg#icon-id;cssClass:icon;", Over: "sprite:svg:fileName.svg#icon-id;cssClass:iconOver;", } })
Developers can also override color
on a per usage basis, by specifying it
directly in sprite-config src
strings
isc.Img.create({ src: { _base: "sprite:svg:fileName.svg#icon-id;color:grey;", Over: "sprite:svg:fileName.svg#icon-id;color:red;", } })
Most UI elements provide colors that will be picked up by child symbols that don't specify a
cssClass or color - for example, a symbol used as the icon in a MenuItem will show
skin-appropriate stateful colors automatically.
MenuItem.icon
is not itself a
stateful attribute, but its colors will be inherited
from the menu's stateful icon-field
if not specified.
isc.Menu.create({ items: [ { title: "Option 1", icon: "sprite:svg:fileName.svg#icon-id" } ] })