Author: Alexei Sokolov
Canvas widget with native support in Firefox, Safari and Opera 9. Support for Internet Exporer is provided by Google's ExplorerCanvas.
How to use it:
First, download ExplorerCanvas and include this code on your HTML host page:
<!--[if IE]><script src="js/excanvas.js" type="text/javascript"></script><![endif]-->
Now you can use it in your GWT classes like this:
final Canvas ctx = new Canvas(200, 200);
ctx.beginPath();
ctx.arc(75,75,50,0,(float)Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,(float)Math.PI,false); // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,(float)Math.PI*2,true); // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,(float)Math.PI*2,true); // Right eye
ctx.stroke();
Note: Support for Gradients and Pattern is very limited in IE.
You can leave your questions or comments here.
Source code:
Canvas.java:
/*
Round Corners Widget for GWT
Copyright (C) 2006 Alexei Sokolov http://gwt.components.googlepages.com/
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.gwt.components.client;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
public class Canvas extends Widget {
public static class DrawingStyle extends JavaScriptObject {
protected DrawingStyle(int opaque) {
super(opaque);
}
}
public static class Gradient extends DrawingStyle {
public Gradient(int opaque) {
super(opaque);
}
protected static native void addColorStop(JavaScriptObject obj,
float offset, String color) /*-{
obj.addColorStop(offset, color);
}-*/;
}
public static class LinearGradient extends Gradient {
public LinearGradient(int opaque) {
super(opaque);
}
public LinearGradient addColorStop(float offset, String color) {
Gradient.addColorStop(this, offset, color);
return this;
}
}
public static class RadialGradient extends Gradient {
public RadialGradient(int opaque) {
super(opaque);
}
public RadialGradient addColorStop(float offset, String color) {
Gradient.addColorStop(this, offset, color);
return this;
}
}
public static class Pattern extends DrawingStyle {
protected Pattern(int opaque) {
super(opaque);
}
}
private JavaScriptObject context;
public Canvas(int width, int height) {
setElement(DOM.createDiv());
Element canvas = DOM.createElement("canvas");
DOM.setAttribute(canvas, "width", String.valueOf(width));
DOM.setAttribute(canvas, "height", String.valueOf(height));
DOM.appendChild(getElement(), canvas);
setStyleName("gwt-Canvas");
init();
setFillStyle("black");
setStrokeColor("black");
}
public native static boolean isEmulation() /*-{
return (typeof $wnd.G_vmlCanvasManager != "undefined");
}-*/;
protected native void init() /*-{
var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()().firstChild;
if (typeof $wnd.G_vmlCanvasManager != "undefined") {
var parent = el.parent;
el = $wnd.G_vmlCanvasManager.fixElement_(el);
el.getContext = function () {
if (this.context_) {
return this.context_;
}
return this.context_ = new $wnd.CanvasRenderingContext2D(el);
};
el.attachEvent("onpropertychange", function (e) {
// we need to watch changes to width and height
switch (e.propertyName) {
case "width":
case "height":
// coord size changed?
break;
}
});
// if style.height is set
var attrs = el.attributes;
if (attrs.width && attrs.width.specified) {
// TODO: use runtimeStyle and coordsize
// el.getContext().setWidth_(attrs.width.nodeValue);
el.style.width = attrs.width.nodeValue + "px";
}
if (attrs.height && attrs.height.specified) {
// TODO: use runtimeStyle and coordsize
// el.getContext().setHeight_(attrs.height.nodeValue);
el.style.height = attrs.height.nodeValue + "px";
}
}
this.@com.gwt.components.client.Canvas::context = el.getContext("2d");
}-*/;
public native void saveContext() /*-{
this.@com.gwt.components.client.Canvas::context.save();
}-*/;
public native void restoreContext() /*-{
this.@com.gwt.components.client.Canvas::context.restore();
}-*/;
public native void scale(float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.scale(x, y);
}-*/;
public native void rotate(float angle)/*-{
this.@com.gwt.components.client.Canvas::context.rotate(angle);
}-*/;
public native void translate(float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.translate(x, y);
}-*/;
public native void transform(float m11, float m12, float m21, float m22,
float dx, float dy) /*-{
this.@com.gwt.components.client.Canvas::context.transform(
m11, m12, m21, m22, dx, dy);
}-*/;
public native void setTransform(float m11, float m12, float m21, float m22,
float dx, float dy) /*-{
this.@com.gwt.components.client.Canvas::context.setTransform(
m11, m12, m21, m22, dx, dy);
}-*/;
public native float getGlobalAlpha() /*-{
return this.@com.gwt.components.client.Canvas::context.globalAlpha;
}-*/;
public native void setGlobalAlpha(float alpha) /*-{
this.@com.gwt.components.client.Canvas::context.globalAlpha = alpha;
}-*/;
public native String getGlobalCompositeOperation() /*-{
return this.@com.gwt.components.client.Canvas::context.globalCompositeOperation;
}-*/;
public native void setGlobalCompositeOperation(String operation) /*-{
this.@com.gwt.components.client.Canvas::context.globalCompositeOperation =
operation;
}-*/;
public native void setStrokeStyle(DrawingStyle style) /*-{
this.@com.gwt.components.client.Canvas::context.strokeStyle = style;
}-*/;
public native void setStrokeColor(String color) /*-{
this.@com.gwt.components.client.Canvas::context.strokeStyle = color;
}-*/;
public native void setFillStyle(DrawingStyle style) /*-{
this.@com.gwt.components.client.Canvas::context.fillStyle = style;
}-*/;
public native void setFillStyle(String style) /*-{
this.@com.gwt.components.client.Canvas::context.fillStyle = style;
}-*/;
public native LinearGradient createLinearGradient(float x0, float y0,
float x1, float y1) /*-{
return this.@com.gwt.components.client.Canvas::context.createLinearGradient(
x0, y0, x1, y1);
}-*/;
public native RadialGradient createRadialGradient(float x0, float y0,
float r0, float x1, float y1, float r1) /*-{
return this.@com.gwt.components.client.Canvas::context.createRadialGradient(
x0, y0, r0, x1, y1, r1);
}-*/;
public native Pattern createPattern(Image img, String repetition) /*-{
var elem = img.@com.google.gwt.user.client.ui.UIObject::getElement()();
var ctx = this.@com.gwt.components.client.Canvas::context;
if (ctx.createPattern)
return ctx.createPattern(elem, repetition);
return null;
}-*/;
public native float getLineWidth() /*-{
return this.@com.gwt.components.client.Canvas::context.lineWidth;
}-*/;
public native void setLineWidth(float lineWidth) /*-{
this.@com.gwt.components.client.Canvas::context.lineWidth = lineWidth;
}-*/;
public native String getLineCap() /*-{
return this.@com.gwt.components.client.Canvas::context.lineCap;
}-*/;
public native void setLineCap(String lineCap) /*-{
this.@com.gwt.components.client.Canvas::context.lineCap = lineCap;
}-*/;
public native String getLineJoin() /*-{
return this.@com.gwt.components.client.Canvas::context.lineJoin;
}-*/;
public native void setLineJoin(String lineJoin) /*-{
this.@com.gwt.components.client.Canvas::context.lineJoin = lineJoin;
}-*/;
public native float getMiterLimit() /*-{
return this.@com.gwt.components.client.Canvas::context.miterLimit;
}-*/;
public native void setMiterLimit(float miterLimit) /*-{
this.@com.gwt.components.client.Canvas::context.miterLimit = miterLimit;
}-*/;
public native float getShadowOffsetX() /*-{
return this.@com.gwt.components.client.Canvas::context.shadowOffsetX;
}-*/;
public native void setShadowOffsetX(float x) /*-{
this.@com.gwt.components.client.Canvas::context.shadowOffsetX = x;
}-*/;
public native float getShadowOffsetY() /*-{
return this.@com.gwt.components.client.Canvas::context.shadowOffsetY;
}-*/;
public native void setShadowOffsetY(float y) /*-{
this.@com.gwt.components.client.Canvas::context.shadowOffsetY = y;
}-*/;
public native float getShadowBlur() /*-{
return this.@com.gwt.components.client.Canvas::context.shadowBlur;
}-*/;
public native void setShadowBlur(float blur) /*-{
this.@com.gwt.components.client.Canvas::context.shadowBlur = blur;
}-*/;
public native String getShadowColor() /*-{
return this.@com.gwt.components.client.Canvas::context.shadowColor;
}-*/;
public native void setShadowColor(String style) /*-{
this.@com.gwt.components.client.Canvas::context.shadowColor = style;
}-*/;
public native void clearRect(float x, float y, float w, float h) /*-{
var ctx = this.@com.gwt.components.client.Canvas::context;
if (typeof $wnd.G_vmlCanvasManager != "undefined") {
var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()();
if (el.currentStyle) {
var color = el.currentStyle['background-color'];
if (!color) {
color = '#ffffff';
}
ctx.save();
ctx.fillStyle = color;
ctx.fillRect(x, y, w, h);
ctx.restore();
}
} else {
ctx.clearRect(x, y, w, h);
}
}-*/;
public native void fillRect(float x, float y, float w, float h) /*-{
this.@com.gwt.components.client.Canvas::context.fillRect(x, y, w, h);
}-*/;
public native void strokeRect(float x, float y, float w, float h) /*-{
this.@com.gwt.components.client.Canvas::context.strokeRect(x, y, w, h);
}-*/;
public native void beginPath() /*-{
this.@com.gwt.components.client.Canvas::context.beginPath();
}-*/;
public native void closePath() /*-{
this.@com.gwt.components.client.Canvas::context.closePath();
}-*/;
public native void moveTo(float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.moveTo(x,y);
}-*/;
public native void lineTo(float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.lineTo(x,y);
}-*/;
public native void quadraticCurveTo(float cpx, float cpy, float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.quadraticCurveTo(cpx, cpy, x, y);
}-*/;
public native void bezierCurveTo(float cp1x, float cp1y, float cp2x,
float cp2y, float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.bezierCurveTo(
cp1x, cp1y, cp2x, cp2y, x, y);
}-*/;
public native void arcTo(float x1, float y1, float x2, float y2,
float radius) /*-{
this.@com.gwt.components.client.Canvas::context.arcTo(x1, y1, x2, y2, radius);
}-*/;
public native void rect(float x, float y, float w, float h) /*-{
this.@com.gwt.components.client.Canvas::context.rect(x, y, w, h);
}-*/;
public native void arc(float x, float y, float radius, float startAngle,
float endAngle, boolean anticlockwise) /*-{
this.@com.gwt.components.client.Canvas::context.arc(
x, y, radius, startAngle, endAngle, anticlockwise);
}-*/;
public native void fill() /*-{
this.@com.gwt.components.client.Canvas::context.fill();
}-*/;
public native void stroke() /*-{
this.@com.gwt.components.client.Canvas::context.stroke();
}-*/;
public native void clip() /*-{
this.@com.gwt.components.client.Canvas::context.clip();
}-*/;
public native boolean isPointInPath(float x, float y) /*-{
this.@com.gwt.components.client.Canvas::context.isPointInPath(x, y);
}-*/;
}
Canvas.css:
.gwt-Canvas {
width:400px;
height:400px;
border: 1px solid black;
}