My favorites | Sign in
Google
                
Search
for
Updated Sep 10, 2008 by jaime...@google.com
GWTCanvas  
Provides cross Browser Vector Graphics support in the spirit of the Javascript canvas element API.

Introduction

Vector graphics have made their way to the GWT Incubator. The GWTCanvas Widget exposes an API for drawing and transforming shapes and images, as well as for defining paths to create custom shapes. GWTCanvas currently supports:

See the live demo: http://google-web-toolkit-incubator.googlecode.com/svn/trunk/demo/GWTCanvasDemo/GWTCanvasDemo.html

Setup Instructions

Just add the following line to your module.gwt.xml file:

  <inherits name='com.google.gwt.widgetideas.GWTCanvas'/>

You can specify your own stylesheet to further customize the look and feel of GWTCanvas.

Using Images

In order for GWTCanvas to draw images, they must first be loaded by the browser. We provide an ImageLoader class in the same package as GWTCanvas to take care of this for you. Please refer to the Sample Code below for examples on how to use ImageLoader.

Sample Code

Please refer to the source code of the live demo (which can be found in the incubator trunk) for more detailed examples.

Drawing a rectangle using paths.

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MyEntryPoint implements EntryPoint {

  public void onModuleLoad() {
    // Make a new canvas 400x400 pixels
    GWTCanvas canvas = new GWTCanvas(400,400);
    
    canvas.setLineWidth(1);
    canvas.setStrokeStyle(Color.GREEN);
    
    canvas.beginPath();
      canvas.moveTo(1,1);
      canvas.lineTo(1,50);
      canvas.lineTo(50,50);
      canvas.lineTo(50, 1);
      canvas.closePath();
    canvas.stroke();
    
    RootPanel.get().add(canvas);
    
  }

}

Drawing an image (Scaling THEN translating before drawing).

Please note that you must put all drawing code involving the image in the supplied callback. Drawing order for images and paths is guaranteed only within the callback method when working with images (since they have to be loaded first, and it can not be known ahead of time how long that will take).

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.google.gwt.widgetideas.graphics.client.ImageHandle;
import com.google.gwt.widgetideas.graphics.client.ImageLoader;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MyEntryPoint implements EntryPoint {

  public void onModuleLoad() {
    // Make a new canvas 400x400 pixels
    final GWTCanvas canvas = new GWTCanvas(400,400);
    
    String[] urls = new String[] {"gwt_logo.jpg"};
    
    ImageLoader.loadImages(urls, new ImageLoader.CallBack() {

      public void onImagesLoaded(ImageHandle[] imageHandles) {
        ImageHandle img = imageHandles[0];
        
        canvas.translate(40, 40);
        canvas.scale(0.5f, 0.5f);
        canvas.drawImage(img, 0, 0);
        
      }
      
    });
   
    RootPanel.get().add(canvas);
  }

}

Drawing two rectangles, with different colors, in different locations.

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MyEntryPoint implements EntryPoint {

  public void onModuleLoad() {
    // Make a new canvas 400x400 pixels
    GWTCanvas canvas = new GWTCanvas(400,400);
    
    canvas.setLineWidth(1);
    canvas.setStrokeStyle(Color.GREEN);
    
    canvas.saveContext();

      canvas.setLineWidth(1);
      canvas.setStrokeStyle(Color.RED);
    
      canvas.translate(100, 100);
      canvas.strokeRect(0, 0, 100, 100);
    canvas.restoreContext();
    
    canvas.strokeRect(1, 1, 80, 80);
    
    RootPanel.get().add(canvas);
    
  }

}

Important Caveats


Comment by sebastian.l.baltes, Mar 10, 2008

Would it be possible to add setGlobalCompositeOperation like

public native void setGlobalCompositeOperation(String operation) /-{
(this.@com.google.gwt.widgetideas.graphics.client.impl.GWTCanvasImplDefault::canvasContext).globalCompositeOperation = operation;
}-
/;

I think this is not possible or easy for IE, but for other browsers it would be great. I use a different implementation for IE anyway. My problem is just, I have no way to set this for Firefox other than to patch GWTCanvas. If the implementation for IE just does nothing, that would be enough.

Comment by oliver.z...@googlemail.com, Apr 01, 2008

For me the IE implementation doesn't look right (at least for this demo - haven't seen the source), blurry squares, strokes too thin, etc...

I've done something similar, take a look at http://code.google.com/p/gwt-canvas/

It is not complete, however it looks almost pixel-perfect on IE for me. So please feel free to merge it into GWTCanvas (or the other way around) if it helps ;)

Comment by markww, Apr 21, 2008

I've downloaded the latest version of the incubator to try the GWTCanvas out, but:

com.google.gwt.widgetideas.graphics

doesn't seem to appear anymore? Where is the canvas class located now?

Thanks

Comment by dirsow, Apr 23, 2008

I' like to ask the same question as markww. It doesn't look to be anywhere. And It looks an amazing job!

thanks, Dirso

Comment by markww, Apr 23, 2008

dirsow, it's not in the compiled jar they have up on the site. I had to build the whole incubator myself, it's in the trunk of the repository!

Comment by dolcraith, Jun 22, 2008

So this is dependent on the canvas element support being present correct? This will not work in hosted mode on the linux platform because GWT currently uses the antiquated mozilla 1.7 for its rendering (correct me if i'm wrong).

Comment by jaimeyap, Jul 03, 2008

@dolcraith

You are correct. We are working on addressing that though :). For now, if you have access to a Mac, you should be able to develop in hosted mode just fine. Otherwise (and I realize that this is non-optimal) you will have to debug in web mode.

Comment by sun.johnsonworld, Aug 03, 2008

I want draw line on a piece of image, how did i do?

Comment by eroberts00, Oct 20, 2008

Is it possible for a GWTCanvas to receive any events, such as mouse or click events?

Comment by nvaneijck, Oct 30, 2008

@eroberts00

I extended the GWTCanvas class to implement mouse listening events:

public final class Canvas extends GWTCanvas {

    private MouseListener listener;

    public Canvas() {
        super(620, 620);
	sinkEvents(Event.MOUSEEVENTS);
    }

    @Override
    public void onBrowserEvent(Event event) {
        super.onBrowserEvent(event);
        if (listener != null) {
            int x = event.getClientX() - getAbsoluteLeft();
            int y = event.getClientY() - getAbsoluteTop();
            switch (event.getTypeInt()) {
                case Event.ONMOUSEDOWN:
                    listener.onMouseDown(this, x, y);
                    break;
                case Event.ONMOUSEMOVE:
                    listener.onMouseMove(this, x, y);
                    break;
                case Event.ONMOUSEUP:
                    listener.onMouseUp(this, x, y);
                    break;
            }				
        }
    }

    public void setListener(MouseListener listener) {
        this.listener = listener;
    }
}
Comment by eroberts00, Nov 03, 2008

@nvaneijck

Thanks, that worked great.

Comment by mpedzi...@stuart.iit.edu, Nov 14, 2008

How do you render/draw Text using GWTCanvas?

Comment by srfarley, Nov 21, 2008

I have added click events and multiple listeners to nvaneijck's contribution:

import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.ClickListenerCollection;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseListenerCollection;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;

public class Canvas extends GWTCanvas {
  private MouseListenerCollection mouseListeners;
  private ClickListenerCollection clickListeners;

  public Canvas() {
    super();
  }

  public Canvas(int coordX, int coordY) {
    super(coordX, coordY);
  }

  public Canvas(int coordX, int coordY, int pixelX, int pixelY) {
    super(coordX, coordY, pixelX, pixelY);
  }

  @Override
  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    if ((clickListeners != null && clickListeners.size() > 0) ||
        (mouseListeners != null && mouseListeners.size() > 0)) {
      int x = event.getClientX() - getAbsoluteLeft();
      int y = event.getClientY() - getAbsoluteTop();
      switch (event.getTypeInt()) {
        case Event.ONCLICK:
          if (clickListeners != null) {
            clickListeners.fireClick(this);
          }
          break;
        case Event.ONMOUSEDOWN:
          if (mouseListeners != null) {
            mouseListeners.fireMouseDown(this, x, y);
          }
          break;
        case Event.ONMOUSEMOVE:
          if (mouseListeners != null) {
            mouseListeners.fireMouseMove(this, x, y);
          }
          break;
        case Event.ONMOUSEUP:
          if (mouseListeners != null) {
            mouseListeners.fireMouseUp(this, x, y);
          }
          break;
      }
    }
  }
  
  public void addClickListener(ClickListener listener) {
    if (clickListeners == null) {
      clickListeners = new ClickListenerCollection();
      sinkEvents(Event.ONCLICK);
    }
    clickListeners.add(listener);
  }
  
  public void addMouseListener(MouseListener listener) {
    if (mouseListeners == null) {
      mouseListeners = new MouseListenerCollection();
      sinkEvents(Event.MOUSEEVENTS);
    }
    mouseListeners.add(listener);
  }
  
  public void removeClickListener(ClickListener listener) {
    if (clickListeners != null) {
      clickListeners.remove(listener);
    }
  }
  
  public void removeMouseListener(MouseListener listener) {
    if (mouseListeners != null) {
      mouseListeners.remove(listener);
    }
  }
}
Comment by WChunming, Nov 28, 2008

Rendering on canvas is fast on firefox/chrome, but on IE it is extremely slow. I found that GWTCanvas's vml implementation on IE is the cause: passing the string to browser every time you want to render something. I suggest GWTCanvas can have some "compile list" function as OpenGL, so that we can manipulate the attribute of some compile element rather than pass string to browser every time. I think some dojo code may inspire GWTCanvas developer:

var node = document.createElement("div");
document.body.appendChild(node);
var surfaceWidth = 120;
var surfaceHeight = 220;
var surface = dojo.gfx.createSurface(node,surfaceWidth, surfaceHeight);
var rect = { x: 100, y: 0, width: 100, height: 100 };
var circle = { cx: 150, cy: 160, r: 50 };
var group = surface.createGroup();
var blueRect = group.createRect(rect)
    .setFill([0, 0, 255, 0.5]) .applyTransform(dojo.gfx.matrix.identity); 

var greenCircle = group.createCircle(circle)
    .setFill([0, 255, 0, 1.0]) .setStroke({color: "black", width: 4, cap:   "butt", join: 4}) .applyTransform(dojo.gfx.matrix.identity); 

this piece of code is copy from: http://www.thinkvitamin.com/features/design/create-cross-browser-vector-graphics

Comment by lobais, Dec 04, 2008

Is this likely to go into 1.5, or will we have to wait for 1.6?

Comment by dobra9, Mar 06, 2009

I would like to congratulate nvaneijck, for the mouse listner implementation, and srfarley for improving it. It helped me a lot in a college project. Thanks!

Comment by memeplex, Mar 26, 2009

Hi - I have the same question/need as stated above: can I somehow render text on the gwtcanvas? Thanks a lot! Axel

Comment by matt.d.hilliard, May 12, 2009

In GWT 1.6, the classes srfarley uses are deprecated. The new event system is a lot cleaner. Here's an example for mouse down events:

import com.google.gwt.event.dom.client.HasMouseDownHandlers;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;

public class Canvas extends GWTCanvas implements HasMouseDownHandlers {

  public Canvas() {
    super();
  }

  public Canvas(int coordX, int coordY) {
    super(coordX, coordY);
  }

  public Canvas(int coordX, int coordY, int pixelX, int pixelY) {
    super(coordX, coordY, pixelX, pixelY);
  }

  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
  	return addDomHandler(handler, MouseDownEvent.getType());
  }
}

Then you can add an extended handler class and it'll get fired by GWT for you. In the callback functions, use getAbsoluteLeft() and getAbsoluteTop() as in nvaneijck's original to convert from screen coordinates to canvas coordinates.

Comment by bosang...@yahoo.com, Jun 03, 2009

Hi all,

Check out my application using gwt canvas : its http://gwt-mind-mapping.appspot.com/

Its only a alpha prototype version.

Thx

Comment by rwiatr, Jul 10, 2009

Hi, How can I make a canvas transparent to a lower level canvas? I mean two or more canvases one upon another. Thx

Comment by swtbclement, Sep 07, 2009

If anybody is interested in drawing text in GWTCanvas take a look at the Google code project swtbcanvasfont

Comment by Linton.Galloway, Sep 24, 2009

Hi,

Does anyone know if the library has been distributed to a maven repo?

Many thx

Comment by hao1300, Oct 15, 2009

I have recently created a project gwt-g2d (http://code.google.com/p/gwt-g2d/) that branches off from gwt-canvas and provide some newer features for canvas, such as text drawing, shadow, and pixel manipulation. The IE implementation uses excanvas and is working reasonably well (text drawing and linear gradient are working). It works best on Firefox 3.5 and Safari, but also pretty decently on Chrome and to some extent Opera. You can see the demo here (http://gwt-g2d.appspot.com/)

Comment by cris.goncalves84, Oct 22, 2009

Hi everyone,

I have a problem with key events over GWTCanvas on Web mode. I add KeyPress? and KeyDown? events to canvas and they work fine in Hosted Mode, but when I compile to WebMode? KeyEvents? just don't work.

The MouseEvents? works fine in both Hosted and WebMode?... Can anyone help me?

I've done a simple app to demonstrate that... You can download it from http://dl.getdropbox.com/u/1353013/GWT_Canvas_Demo.rar

You just have to right setup the gxt and gwt-incubator on the app built-path. I hope someone can help me.

Thanks, Cheers.

Comment by lakshmithiru, Oct 27, 2009

Hi ,

Is it possible to render the drawings on a gwtcanvas to a png image format or a pdf format?

Thx

Comment by meera.bavadekar, Nov 04, 2009

Is it possible to draw text? I like to draw a rectangle - and on top of the rectagle draw a text such as 'OK' or 'Cancel'.


Sign in to add a comment