Keilly: Resizable Background

Friday, May 25, 2007

Resizable Background

The better widgets resize. The apple guidelines here do a nice job of describing how to add the resize corner and code, but to get it to look nice at any size is tricky.

By default Dashcode will create a widget with a nice background image that can have rounded corners, gradient fills, and glass effects. This image does not dynamically resize.

One super simple way to get these effects plus enable resizing is to replace the background image with a canvas, and render draw the background on the fly. It's pretty simple. This code will render a black rounded rectangle at any size...

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);

var x = 0;
var y = 0;
var x1 = window.innerWidth - 20;
var y1 = window.innerHeight - 28;
var round = 10; // The roundness of the corners

context.lineJoin = "round";
context.fillStyle = '#000000'; // background color

context.arc(x1-round,y+round, round, -Math.PI/2,
0, 0);
context.arc(x1-round,y1-round, round, 0,
Math.PI/2, 0);
context.arc(x+round,y1-round, round, Math.PI/2,
Math.PI, 0);
context.arc(x+round,y+round, round, Math.PI,
3*Math.PI/2, 0);

The steps to add this to a widget are

- Replace the background image with a canvas
- Size the canvas component to it's largest possible size
- Call size and the rendering code when the widget is shown.

Sizing is canvas is the tricky thing. Dashboard initializes the canvas drawing area to a fixed size when the component is first created - so sizing the canvas later does not increase the available area for drawing - leading to possible clipping. The workaround is to initially size the canvas as large as your widgets maximum size, and to add some code to resize the canvas down to the desired size after creation - but just before the widget is shown (i.e. call it in function show()).

The canvas is quite powerful at drawing, and nice effects can be quickly achieved with its API. This image of an unreleased widget is all drawn on canvases, with some text and and buttons added..

Take a look at the code of the ZX Spectrum widget for a working example of a widget with a resizable canvas

No comments: