Sunday, September 14, 2014
Star Wars: Commander
Monday, September 8, 2014
Dynamically Changing the Color of SVG Using an ASP.NET HttpHandler
I have an SVG file that I'm using as the background image of elements on the page (using sprites). I wanted to dynamically update the color of the shapes and paths when theming the application, but I could not find a way to do this using CSS when the SVG is loaded as a background image (I have heard that inline <svg> elements will inherit style rules).
The way I solved the issue was to use a custom HttpHandler in my ASP.NET application that allows me to replace parts of the SVG with other content. Here's the code I used:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;
namespace MyNamespace
{
public class DynamicSVGHandler : IHttpHandler
{
public bool IsReusable
{
get
{
return true;
}
}
public void ProcessRequest( HttpContext context )
{
var request = context.Request;
var response = context.Response;
var file = context.Server.MapPath( Path.ChangeExtension( request.Url.LocalPath, ".svg" ) );
if( File.Exists( file ) )
{
var lastWrite = File.GetLastWriteTimeUtc( file );
response.Clear();
response.ContentType = "image/svg+xml";
response.Cache.SetExpires( DateTime.Now.AddMinutes( 5d ) );
response.Cache.SetCacheability( HttpCacheability.Public );
List<KeyValuePair<string, string>> replacements = new List<KeyValuePair<string, string>>();
string value;
foreach( string key in request.QueryString )
{
if( key.Length > 3 && !string.IsNullOrEmpty( value = request.QueryString[key] ) && value.Length > 3 )//Implement any custom validation here.
replacements.Add( new List<KeyValuePair<string, string>>( key, value ) );
}
if( replacements.Count > 0 )
{
string line;
using( StreamReader reader = new StreamReader( File.OpenRead( file ) ) )
{
while( (line = reader.ReadLine()) != null )
{
foreach( var replacement in replacements )
line = line.Replace( replacement.Key, replacement.Value );
response.Output.WriteLine( line );
}
}
}
else
response.WriteFile( file );
}
else
{
response.Clear();
response.StatusCode = 404;
response.End();
}
}
}
}
Make sure to register your handler in your web.config (This example is for IIS 7+, integrated mode and I used the extension .dsvg):
<configuration>
<system.webServer>
<handlers>
<add name="*.dsvg" path="*.dsvg" preCondition="integratedMode" verb="*" type="MyNamespace.DynamicSVGHandler, MyAssembly"/>
</handlers>
</system.webServer>
</configuration>
You can now reference any svg file in your application with the extension .dsvg instead of .svg and specify replacements in the URL (e.g. mysvg.dsvg?white=red to change "white" to "red").
In my SVG, I found it easiest to define the color using a style section rather than setting the fill of each shape, then add the class="svg-shape" to all the shapes.