Anti-Aliased Rounded Corners with the NiftyCornersExtender Control
When I was in college I took a course on Software Construction. With 3 weeks left in the semester, the professor assigned us a project that he knew would take close to 6 weeks to implement. To meet the deadline he allowed us to leverage 3rd party components where possible. He encouraged us to think about a solution that was constructed from other components as opposed to one that we developed from scratch. This professor was good. This is exactly the same type of problem I encounter everyday.
Live Demo (IE6, IE7 and FF) | Download (Uses Toolkit Version 1.0.10920.0)
I took this construction approach on a recent project. Our team is looking to soften some of our UI elements by using the toolkit's RoundedCornerExtender control. The toolkit's rounded corner implementation does not include anti-aliasing and as a result, the corners look pretty rough. (Anti-aliasing is a technique that is used to make graphics and text easier to read. Here is an explanation from Wikipedia.) If you look at the 'rounded' corners created by the RoundedCornersExtender closely you can see the corners aren't all that round. It looks like a bunch of 1 pixel notches have been taken out of them ...
So my research assignment involved looking into what it would take to replace the default rounded corners implementation with one that included anti-aliasing. I found a number of examples of people using anti-aliasing to round panel's, but this was the best one. And because I am not one to reinvent the wheel, I wrapped the nifty corners anti-aliasing algorithm into a new toolkit extender control (NiftyCornersExtender), made a few very minor modifications to the original JavaScript source, and just like that had a brand new extender control that does a really great job of creating anti-aliased rounded corners (Thank you Steven Wittens).
See how much better that looks! If you zoom in on the corners, you can really see the difference (the anti-aliased one is on the left). The nifty corners algorithm adds additional DIV's that gradually blend the color from the foreground color (blue) to the background color (white). When viewed normally (i.e. not at 890% zoom), this gradual blend is what makes the corner appear round.
The demo site for this post contains three sample usages, each with different foreground/background color combinations. For fun, I also included a SliderExtenderControl that allows you to changes the radius of all 6 panels. This way you can play around with different radius sizes and see how the 2 controls compare.
Besides swapping out the original rounded corners algorithm (basically the buildParentDiv function) with the anti-aliased version, I also made a few other minor changes:
- In each of the RoundedCornersExtender behavior's property setters (set_Corners, set_BorderColor, set_Radius, etc...), a call to buildParentDiv was being made. Because these setters are called when the component is initializing, it was causing the rounded algorithm to run multiple times (once for every property that was set, and then again after all properties were set and the initialize function is called). I updated these property setters to check if the component is initialized or not, before calling buildParentDiv (This can be done using the Component.get_isInitialized() function).
- Because I the anti-aliasing algorithm controls the color of the border, I removed the BorderColor property
- I removed the option to selectively draw each of the four corners independently. I will most likely add this back sometime in the future
This control is still in the prototype phase, I want to see how it plays with some of the other extender controls - namely the ModalPopup and Popup controls. If you run into any bugs let me know.
That's it. Enjoy!
Comments
Very nice. I avoided using RoundedCornersExtender because of the rough edges. Your solution is excellent.
good work matt, thanks for sharing.. does it also work with control toolkit version 3.5 ?
I would much rather have a PNG image take care of this, but maybe it's just me. These client-script powered rounding techniques are causing more stress than an image would. However, with this technique you can change the size of the radius with ease, which is a pretty nice benefit.
Thanks for sharing!
Excellant, This has been a nasty blemish on asp.net ajax for to long. Thank you for taking the time to address this.
Did the same thing, but had an intermittent bug with NiftyCorners where occisionally the page would not draw at all in IE until you forced a repaint (eg. moved the mouse)
Hey Matt,
Great job on the extender, I've struggled with the RoundedCornersExtender quite a bit in IE. Unfortunately your extender similarly throws an exception when you attempt to add rounded corners to a Panel on a UserControl that's dynamically loaded in IE. I'm setting the BehaviorID to a new Guid to avoid multiple ID instances, and it throws an "Invalid property value" exception on Line 181: x.style.backgroundColor = this._blend(bk, color, coverage);
This only occurs in IE7, it works like a charm in FireFox.
Do you plan to submit this for inclusion in the official AJAX Control Toolkit?
Well done on a good job.
@Gokhan Demir -
I have not tested it using toolkit version 3.5.
Matt.
@Josh -
As usual, you touch on a good point.
If there is no need for the corner's radius to be changed dynamically on the client, you could argue that a better approach is to move this logic into a server control, or use images like you suggest.
Matt.
@Joseph Kingry -
I haven't run into this one yet. Can you reproduce the problem using my demo page?
Matt.
@Daniel Crenna -
The NiftyCornersExtender will suffer from all of the same bugs as the original RoundedCornersExtender. Have you reported this problem to the toolkit's codeplex site?
If you have a minimal repro project setup, I wouldn't mind taking a look.
Matt.
@Michael Sivers -
Quite honestly I had not thought of that (and I am not exactly sure how to go about it).
I would think there is already a toolkit bug/feature requesting anti-alised corners. I guess I will probably try to track that bug down and link it to this post.
Matt.
Hi! Good job, Matt.
I have published a similar project (NiftyDotNet) in Google code, but it is not oriented as an extender, it's a simple component. This will help you to round corners even if you are not using asp.net ajax.
Project site
Project's Blog
Best regards.
Any plans on making the rounded corners present before the page is rendered? Right now, you see the page move when using rounded corners (either the original, or yours).
The jquery/roundCorner scripts don't have this behaviour, the page doesn't move at all; the corners are simply rounded.
Thanks Matt! And to Jose I like the idea of having it separate too! That's a great project you put up.
Thanks for sharing!! A couple more shiny nuggets for my collection.
Hi Matt
Great site, thank you
The niftycornersextender is interesting, with the smooth corners. Do you know a site for newbies explaining how to import and use custom controls into VS Pro 2005? I want to try and use your control, but don't know to import it.
Thanks again
Steve
Very Nice.
This is a very nice addition to the toolkit. Thanks for all your work on this Matt.
Do you have any plans on allowing only certain corners to be rounded (for example, only the top 2)?
Also, I couldn't get a border working, is this supported? If so, could you possibly provide details at how to obtain a border?
Matt,
Great job on the rounded corners!
I was wondering, similar to the previous poster, if you have any plans to support drop shadows similar to the AJAX toolkit DropShadow control? Or, if you know of a way to add it to your existing control?
Thanks!
Jay
Matt,
I would really like to have a go at using your extender on one of my websites. However I have just moved to 3.5, do you know when you will be releasing an updated version?
Thanks
Shawn
Hi Matt,
I'm attempting to implement this against the 3.5 version of the .NET framework, like a few others above, but I have hit a snag that I haven't been able to get around. It seems the .backgroundColor property of div objects in 3.5 isn't happy with the way it is being accessed in the NiftyCornersBehavior.js (e.g. ln 181: x.style.backgroundColor = this._blend(bk, color, coverage);) throws 'Invalid Property Value' errors when a value for Radius is specified. Easily reproducible in the sample project by adding a panel, then adding the NiftyCornersExtender to the panel: BlendFromColor="" BlendToColor="" Enabled="True" TargetControlID="Panel1" Radius="10">
) I've searched high and low and I just don't see why that error is being thrown. Any nudges in the right direction would be most appreciated!
The download link and demo link is broken. I would love to have this code.
Thanks,
Hi @ all,
did anyone tried the "original" RoundedCornersControl and Matts version in a production environment?
What me interests most is the performance of a website, where you have - lets say - 8 to 10 areas rounded with this RoundedCornersControl.
Does anyone have experience regarding this question?