Sébastien Tromp Sébastien Tromp - 1 year ago 59
CSS Question

How to create a WoW-like cooldown effect?

I am currently trying to make a cooldown effect similar to the ones you can see in World of Warcraft. (See the square with the 2m text on it? The idea is to have the square ''lighten'' in a circular manner, also illustrated in http://www.youtube.com/watch?v=R51QXmkyelQ at 0:23.). I am using GWT, so I am mainly looking for a means to do this using pure CSS and/or javascript.

To achieve this, I only need to be able to create a square image similar to the dark area in 1. I could then apply this image in overlay to my main image, and use a timer to make the illusion of mouvement.

However I am at a loss as to how to create such an image. It seems possible to create shapes using CSS only, but I could not understand if, and how, creating what I needed was possible.

I also found something that uses Silverlight, but it is not an option for me.

I am not sure I have expressed my need clearly enough. If that were the case, I'd be more than happy to add clarifications.

Thanks in advance for any hint,

Sébastien Tromp

Answer Source

This is what I came up with. Basically what it does is, it encapsulates an image and a 0.5 opacity canvas on top of each other in a composite widget. The animation draws lines on the canvas from the center towards the edges in a circular fashion in a given time interval. Canvas has a clickHandler to start the animation. Hope it helps. It uses GWT Canvas so this widget may not be supported on all browsers.

Class CoolDownAnimation :

    public class CoolDownAnimation extends Animation {

    Canvas canvas;
    Context2d context;
    int centerX;
    int centerY;
    static final CssColor BLACK = CssColor.make("rgba(0,0,0,0.6)");
    static final CssColor WHITE = CssColor.make("rgba(255,255,255,0.6)");

    public CoolDownAnimation(Canvas canvas) {
        this.canvas = canvas;
        this.context = canvas.getContext2d();
        centerX = canvas.getCoordinateSpaceWidth() / 2;
        centerY = canvas.getCoordinateSpaceHeight() / 2;
    protected void onStart() {
        context.fillRect(0, 0, centerX * 2, centerY * 2);
    protected void onUpdate(double progress) {
        context.moveTo(centerX, centerY);
                centerX + 2 * centerX * Math.cos((progress * Math.PI * 2)-Math.PI/2),
                centerY + 2 * centerY * Math.sin((progress * Math.PI * 2)-Math.PI/2));
    protected void onComplete() {
        context.clearRect(0, 0, centerX*2, centerY*2);

Class CoolDownWidget :

    public class CoolDownWidget extends Composite {

    private CoolDownAnimation coolDown;
    private AbsolutePanel wrapper;
    private Image image;
    private Canvas canvas;
    private int sizeX = 50;
    private int sizeY = 50;
    private int coolDownDuration = 5000;

    public CoolDownWidget(){
        canvas = Canvas.createIfSupported();
        if (canvas==null){
            Window.alert("Fail! You dont have canvas support");
        coolDown = new CoolDownAnimation(canvas);
        image = new Image("images/icon.png");
        image.setPixelSize(sizeX, sizeY);
        canvas.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
        wrapper = new AbsolutePanel();
        wrapper.setPixelSize(sizeX, sizeY);
        wrapper.add(image, 0, 0);

finally onModuleLoad to wrap things up :

    public void onModuleLoad() {
    RootPanel.get().add(new CoolDownWidget());