Archive for January, 2012

January 31, 2012

Creating a simple pie chart with HTML5 Canvas Part 3

Over the last two weeks, we have created a simple pie chart and then added some functionality. This week we will focus on some design aspects to improve the presentation of the chart.

While contrasting colors for each slice of the pie can be used for a clear distinction between slices, using a border for each one generally looks nicer. This is easily accomplished using the .stroke method.

 

ctx.lineWidth = 1;

ctx.strokeStyle = “#fff”;

ctx.stroke();

 

Another simple way to improve the appearance of the chart is to add some color gradient for each slice. Using color gradients will give the chart a more modern look and are extremely simple to add. The first step is to define the gradient as follows.

 

var gradient = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

gradient.addColorStop( 0, “#ddd” );

gradient.addColorStop( 1, colors[i] );

 

Once the gradient is defined, we can set it as the fillStyle for the context and call the fill method.

 

ctx.fillStyle = gradient;

ctx.fill();

 

Last week we added rendering of the pie slice values at the bottom of the screen. While that does the job of giving the user information about the slice, it forces them to look away from the chart. To improve on that, we will have the value of the slice be rendered at the position of the mouse. The effect will be that the value follows the user as they hover over the slices.

 

ctx.fillStyle = ‘#fff’;

ctx.font = ‘bold 10px verdana’;

ctx.fillText(pieData[slice][‘value’], x, y, 20);

 

While adding these improvements may seem trivial, they are worth mentioning due to the fact that they transform what was a simple and dull chart into one that is more functional, intuitive, and professional.

For the full source and a working demo, please follow the link below.

 http://yojimbocorp.com/demos/pieChart3.html

Advertisement
January 24, 2012

Creating a simple pie chart with HTML5 Canvas Part 2

Last week we created a pie chart using HTML5’s Canvas element. This week we will utilize jQuery to add some simple functionality.  For this exercise, we want to be able to visualize the exact values of each slice of the pie when the user positions the mouse over them. To do this, we will use the .mousemove event from jQuery to update text on the page.

The first step is to include jQuery.

 

<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js”></script&gt;

 

Next, we will need to refactor the script from last week a bit in order to reference it from the mousemove event. To do this, we will create an array to store the data for each slice.

 

var pieData = [];

for(var i in data) {

                pieData[i] = [];

                pieData[i][‘value’] = data[i];

                pieData[i][‘startAngle’] = 2 * Math.PI * lastPosition;

                pieData[i][‘endAngle’] = 2 * Math.PI * (lastPosition + (data[i]/total));

                lastPosition += data[i]/total;

}

 

Now that the data is stored a bit differently than last week, we will need to update the script that renders the pie chart. Specifically, we will change the ctx.arc call to reference the data we just stored in the pieData array.

 

for(var i = 0; i < data.length; i++)

{

                ctx.beginPath();

                ctx.moveTo(center[0],center[1]);

                ctx.arc(center[0],center[1],radius,pieData[i][‘startAngle’],pieData[i][‘endAngle’],false);

                ctx.lineTo(center[0],center[1]);

                ctx.closePath();

                ctx.fillStyle = colors[i];

                ctx.fill();

}

 

Next we will add some text to the page that will be used to display the value of the pie chart that the user is currently hovering over with the mouse.

 

<div>

        Hover over a slice

</div>

 

Now that we have a placeholder for the text, we can add the mousemove event that will first evaluate whether the user is within the radius of the chart and then do a bit of math to determine which slice the mouse is over.

 

$(“#canvas”).mousemove(function(e) {

                var x = Math.floor((e.pageX-$(“#canvas”).offset().left));

                var y = Math.floor((e.pageY-$(“#canvas”).offset().top));

                var fromCenterX = x – center[0];

                var fromCenterY = y – center[1];

                var fromCenter = Math.sqrt(Math.pow(Math.abs(fromCenterX), 2) + Math.pow(Math.abs(fromCenterY), 2 ));

 

                if (fromCenter <= radius) {

                                var angle = Math.atan2(fromCenterY, fromCenterX);

                                if (angle < 0) angle = 2 * Math.PI + angle; // normalize

 

                                for (var slice in pieData) {

                                                if (angle >= pieData[slice][‘startAngle’] && angle <= pieData[slice][‘endAngle’]) {

                                                                $(“div.sliceValue”).text(“The value for the slice is ” + pieData[slice][‘value’]);

                                                                return;

                                                }

                                }

                }

});

 

If all went well, you should now have a working demo. If not, you can view the source of the working demo linked below.

 

http://yojimbocorp.com/demos/pieChart2.html

January 17, 2012

Creating a simple pie chart with HTML5 Canvas

This week we take a look at how to use the HTML5 canvas element to create a simple pie chart. To begin, we need to define the element using the canvas tag. Please note the id, height, and width are required.

<canvas id=”canvas” width=”400″ height=”300″></canvas>

In order to interact with this canvas through Java script, we will need to first get the element by Id and then create a context.


<script type="text/javascript">

var canvas = document.getElementById(‘canvas’);

var ctx = canvas.getContext(“2d”);

</script>

These two steps are essentially all that is required to start drawing to the canvas. For this example, we will be drawing a simple pie chart, so let’s add some data. We’ll use some hard coded values for data in the interest of simplicity.

 

var data = [75,68,32,95,20,51];

var colors = [“#7E3817”, “#C35817”, “#EE9A4D”, “#A0C544”, “#348017”, “#307D7E”];

var center = [canvas.width / 2, canvas.height / 2];

var radius = Math.min(canvas.width, canvas.height) / 2;

var lastPosition = 0, total = 0;

 

Next we will need to get the total value of all the data being represented in the pie chart. This is required in order to scale the size of each slice correctly. To do this, we simply need to loop through the data array and add each value into the ‘total’ variable defined above.

 

for(var i in data) { total += data[i]; }

 

And finally, we are ready start using canvas to draw each slice of the pie. To do this, we will loop through the data array again and call the canvas methods to create and fill the shapes.

 

for (var i = 0; i < data.length; i++) {

ctx.fillStyle = colors[i];

ctx.beginPath();

ctx.moveTo(center[0],center[1]);

ctx.arc(center[0],center[1],radius,lastPosition,lastPosition+(Math.PI*2*(data[i]/total)),false);

ctx.lineTo(center[0],center[1]);

ctx.fill();

lastPosition += Math.PI*2*(data[i]/total);

}

 

Loading the page in an HTML5 enabled browser should result in our chart being rendered as follows.

 

pie_chart

 

Next week we will take a look at adding labels to the chart as well as adding some user interaction with animation.

January 12, 2012

Large WCF Requests, Don’t forget httpRuntime settings

Recently, I was working on a project where the client was passing an array of bytes (byte[]) into a WCF service method. The array represented a file the user wanted to upload to the server. The WCF service was throwing cryptic error messages when the user attempted to upload a large file. There are obvious issues with this approach, but without a redesign of the upload process, my client was looking for a quick fix. There are many articles that cover the various options that one has to adjust under serviceBehaviors for WCF (e.g. maxReceivedMessageSize), but increasing all of those to their maximum value DID NOT solve the problem.

After looking at the issue through a packet filter, I finally figured out that IIS was rejecting the request at a level above WCF and then I remember the httpRuntime config section. You can read about it here:
http://msdn.microsoft.com/en-us/library/e1f13641

The relevant attribute is maxRequestLength

The default is 4096KB as of the writing of this post.

Obviously, no matter what other settings you tweak, if you run into this limit, IIS will block the request.

This can also come up when writing plain old vanilla ASP.NET file upload if you’re not streaming the file to the server.

Streaming files to your server would avoid running into these problems, but if you’re in a pinch and working on an internal application used by a small number of users, this is the quick and dirty way to get around the limit.

Tags: ,
January 11, 2012

Homegrown Dynamic IP Tracking

I often need to remotely access my home computer. Since dynamic DNS services are not always available to me, I needed a way to be notified when my ISP issued a new IP address. The first task was to choose one of the many services that happily provide your public address. The ideal candidate would be one that gives a relatively easy to parse response. After a bit of searching, I found that the nice folks over at http://dyndns.org offer just that with http://checkip.dyndns.org

The .Net WebClient provides an easy means to retrieve the response:

var client = new WebClient();
var response = client.DownloadString("http://checkip.dyndns.org");

After a bit of simple parsing, we have our public IP address:

const string startToken = "Current IP Address: ";
var startIndex = response.IndexOf(startToken);
startIndex += startToken.Length;
var endIndex = response.IndexOf("&lt;/body&gt;");
var ip = response.Substring(startIndex, endIndex - startIndex);

Now that we have the public IP address, notification becomes a task for the .Net SmtpClient. Using email as the notification method certainly isn’t the only solution, but has the benefit of being private. For this particular project, I’m using an App.config to populate properties of the SmtpClient.

var appSettings = ConfigurationManager.AppSettings;
var email = Convert.ToString(appSettings["EmailAddress"]);
var displayName = Convert.ToString(appSettings["DisplayName"]);
var fromAddress = new MailAddress(email, displayName);
var toAddress = new MailAddress(email, displayName);
var fromPassword = Convert.ToString(appSettings["EmailPassword"]);
var smtp = new SmtpClient
            {
                Host = Convert.ToString(appSettings["EmailHost"]),
                Port = Convert.ToInt32(appSettings["EmailPort"]),
                EnableSsl = Convert.ToBoolean(appSettings["EnableSsl"]),
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)</p>
            };

And now, sending the message is simply a matter of constructing a .Net MailMessage and passing it to the SmtpClient Send method.

var subject = "Current Home IP Address: " + ip;
var body = subject;
using (var message = new MailMessage(fromAddress, toAddress)
{
    Subject = subject,
    Body = body
})
{
    smtp.Send(message);
}

It is certainly feasible to schedule a daily task for this to run, but I decided to wrap it into a service so notification emails are only sent if the public IP changes. The entire project can be found in our brand new github repository linked below.

https://github.com/yojimbocorp/blog-posts

January 2, 2012

How to get the value of a custom attribute in C#

In a recent project, I needed to get the value of a custom attribute that was set on various class properties. More precisely, the custom attribute was a string that needed to be evaluated programmatically to see if it matched a given value. This particular case came up during unit testing of localized strings in a web application, but may be applicable to a wide variety of use cases involving custom attributes.

In this example, there is a class that sets a custom attribute like this:

public class UserAccount
{
    [LocalizedDisplayName(&quot;SOME_RESOURCE_ID&quot;)]
    public string UserAccountName { get; set; }
    ...
}

This attribute is referenced throughout the application to display the correct text for the current culture, but the problem is that there is no inherent mechanism to get the actual string value of the resource associated with the given class property for testing purposes. The solution was to create a utility method which does just that:

public static object GetAttributeValue(Type objectType, string propertyName, Type attributeType,

string attributePropertyName)
{
    var propertyInfo = objectType.GetProperty(propertyName);
    if (propertyInfo != null)
    {
        if (Attribute.IsDefined(propertyInfo, attributeType))
        {
            var attributeInstance = Attribute.GetCustomAttribute(propertyInfo, attributeType);
            if (attributeInstance != null)
            {
                foreach (PropertyInfo info in attributeType.GetProperties())
                {
                    if (info.CanRead &amp;&amp;
                      String.Compare(info.Name, attributePropertyName,
                      StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        return info.GetValue(attributeInstance, null);
                    }
                }
            }
        }
    }
    return null;
}

This method is in an AttributeUtil class. An example call to the method looks like this:

var value = AttributeUtil.GetAttributeValue(typeof(UserAccount), &quot;UserAccountId&quot;,
                                             typeof(LocalizedDisplayNameAttribute),&quot;DisplayName&quot;);

It was surprisingly hard to find relevant information for this particular problem, so I hope you found this useful. A complete example project is available in our codeplex repository.

GetAttributeValue

As an exercise to the reader, you may choose to package GetAttributeValue as an extension method on the Attribute class itself. Also, beware that this will not work against attributes whose value is an array type, because we’re passing NULL as the second parameter to PropertyInfo.GetValue method.

Tags: