Advanced display of SVG Images in Sitecore

SVG Images are basically vector images (coordinates, objects and properties) with data that can be manipulated with CSS styling – check out this article for details on how that works.

In short, to take advantage of CSS styling over SVG files, you must throw the XML content of the SVG file, directly into the HTML markup. So instead of the traditional <img tag:

<img src="image.svg"

You must throw inline the content of the SVG file, which will be something like:

<svg ...> <ellipse class="chair" .../> </svg>

In Sitecore that means you can’t use the standard sc:Image control to render the content of an Image Field – that will render your SVG as an <img HTML tag, which can’t be touched by CSS styling…

Usercontrol

In order to have something that is compatible both with CSS Styling and Sitecore’s Page Editor mode, my proposal is to have a custom asp usercontrol like this:

Image.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Image.ascx.cs" Inherits="Layouts.UserControls.Image" %>
<sc:Image runat="server" ID="scImage" />
<asp:Literal runat="server" ID="litImage"></asp:Literal>

 Image.ascx.cs (Codebehind)

namespace Layouts.UserControls
{
 public partial class Image : UserControl
 {
   /// <summary>
   /// Component's Field
   /// </summary>
   public string Field { get; set; }
   /// <summary>
   /// Component's Item (Default=Context)
   /// </summary>
   public Item Item
   {
      get { return _item ?? Sitecore.Context.Item; }
      set { _item = value; }
   }
   private Item _item;
   protected void Page_Load(object sender, EventArgs e)
   {
     // When editing in Page Editor mode, always use an <sc:image
     // If no field is set, escape and let it break
     if (Sitecore.Context.PageMode.IsPageEditorEditing || string.IsNullOrEmpty(Field))
     {
        ShowScImage();
        return;
     }
     // Escape if field is not found
     var referencedImageField = (Sitecore.Data.Fields.ImageField)Item.Fields[Field];
     if (referencedImageField == null)
     {
       ShowScImage();
       return;
     }
     // Get referenced image - Scape if image is not found
     var imageItem = referencedImageField.MediaItem;
     if (imageItem == null)
     {
        ShowScImage();
        return;
     }
     // If this is not an svg use a normal <sc:Image
     var imageMediaItem = (MediaItem) imageItem;
     if (!imageMediaItem.Extension.ToLower().Contains("svg"))
     {
        ShowScImage();
        return;
     }
     ShowSvgImage(imageMediaItem);
 }
 public static string GetMediaUrlWithServer(MediaItem mediaItem, Item item = null)
 {
    item = item ?? Sitecore.Context.Item;
    var options = new UrlOptions { AlwaysIncludeServerUrl = true, AddAspxExtension = false };
    var itemUrl = LinkManager.GetItemUrl(item, options);
    var mediaOptions = new MediaUrlOptions { AbsolutePath = true };
    var mediaUrl = MediaManager.GetMediaUrl(mediaItem, mediaOptions);
    return itemUrl + mediaUrl;
 }
 private void ShowSvgImage(MediaItem mediaItem)
 {
    litImage.Visible = true;
    scImage.Visible = false;
    // Get string from Image Stream
    var stream = mediaItem.GetMediaStream();
    var reader = new StreamReader(stream);
    var svgString = reader.ReadToEnd();
    reader.Close();
    stream.Close();
    // Get SVG tag from string
    // No SVG tag found - fallback to <sc:Image
    if (!svgString.Contains("<svg"))
    {
       ShowScImage();
       return;
    }
    svgString = svgString.Substring(svgString.IndexOf("<svg",StringComparison.Ordinal));
    litImage.Text = svgString;
 }
 private void ShowScImage()
 {
    litImage.Visible = false;
    scImage.Visible = true;
    scImage.Item = Item;
    scImage.Field = Field;
    ReflectAttributesToControl(scImage); 
 }
 private void ReflectAttributesToControl(WebControl control)
 {
    foreach (string key in Attributes.Keys)
     control.Attributes[key] = Attributes[key];
 }
}

Streaming

The proposed solution makes use of Streaming for better performance, so rendering times are not affected.

How to Use

Now we have our custom image rendering control that renders inline SVG images when you are in Preview or Normal mode, and is compatible with Sitecore’s Page Editor mode.

To use, first you have to register the Usercontrol:

<%@ Register TagPrefix="custom" TagName="Image" Src="~/layouts/UserControls/Image.ascx" %>

Then use it just like you’d do with a standard sc:Image control:

<custom:Image runat="server" ID="imgSvgImage" Field="My Field Name" />

At the code behind you can also access the properties “Field” and “Item” just like the normal Image control:

imgClear.Item = Sitecore.Context.Item;

And that’s all!

Posted in Architecture, Experience Editor, Front-end, Uncategorized

Leave a Reply

Your email address will not be published. Required fields are marked *

*

  Am Not Spammer

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>