Exibição avançada de imagens SVG com Sitecore

Imagens SVG são basicamente vetores (coordenadas, objetos e propriedades) cuja aparência pode ser manipulada com CSS – confira este artigo para mais detalhes sobre como isso funciona.

Resumidamente: para poder estilizar imagens de arquivos SVG com CSS, você precisa jogar o conteúdo do SVG (basicamente XML) diretamente dentro do HTML. Então, ao invés da tradicional tag <img tag:

<img src="image.svg"

Precisamos jogar o conteúdo do arquivo SVG inline no html, que vai ficar algo assim:

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

Para o Sitecore, isso significa que não podemos mais usar a tag padrão sc:Image para renderizar o conteúdo de um campo do tipo Image – isto renderizaria sua imagem SVG dentro de uma tag <img, que não permite manipulação pelo CSS…

Usercontrol

Para termos algo compatível tanto com a manipulação via CSS e o Experience Editor do Sitecore, minha proposta é usarmos um asp usercontrol como este abaixo:

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>
   /// Campo do Componente
   /// </summary>
   public string Field { get; set; }
   /// <summary>
   /// Item do componente (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)
   {
     // Quando editar em Page Editor mode, sempre usar um <sc:image
     // Se não houver um campo, abortar
     if (Sitecore.Context.PageMode.IsPageEditorEditing || string.IsNullOrEmpty(Field))
     {
        ShowScImage();
        return;
     }
     // Abortar caso o campo não for encontrado
     var referencedImageField = (Sitecore.Data.Fields.ImageField)Item.Fields[Field];
     if (referencedImageField == null)
     {
       ShowScImage();
       return;
     }
     // Pegar a imagem referenciada – Abortar caso a imagem não seja encontrada
     var imageItem = referencedImageField.MediaItem;
     if (imageItem == null)
     {
        ShowScImage();
        return;
     }
     // Se não for uma imagem SVG, usar um <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;
    // Pegar a string da Image Stream
    var stream = mediaItem.GetMediaStream();
    var reader = new StreamReader(stream);
    var svgString = reader.ReadToEnd();
    reader.Close();
    stream.Close();
    // Pegar a tag SVG da string
    // Não encontrou tag SVG tag – exibir como <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

A solução proposta faz uso de Streaming para uma melhor performance, de modo que os tempos de renderização não sejam afetados.

Como usar

Temos agora nosso controle customizado para renderização de imagens SVG inline em modo Preview ou Normal, compatível com o modo Experience Editor do Sitecore.

Para usá-lo, primeiro registre o Usercontrol:

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

E então use-o da mesma forma que faria com um sc:Image normal:

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

No code behind você pode também acessar as propriedades “Field” e “Item” como um componente Image normal:

imgClear.Item = Sitecore.Context.Item;

E isso é tudo que precisamos!

Publicado em 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>