How To Use Canvas4Z Part2

From Documentation
DocumentationSmall Talks2012FebruaryHow To Use Canvas4Z Part2
How To Use Canvas4Z Part2

Jimmy Shiau, Engineer, Potix Corporation
February 29, 2012
ZK 5, Canvas4Z 0.9.0


Canvas4Z is an experimental component that leverages HTML 5 for free-style drawing. In the previous small talk How To Use Canvas4Z Simon showed us how to use Canvas4Z, this small talk will extend the previous small talk with some additional new features such as

  1. Adding an image as a background
  2. Drawing an arrow
  3. Selecting and moving objects
  4. Saving canvas objects with its background as an image


Make canvas paint board as a macro component

In the previous smalltalk, we handled drawing at the client side and when finish drawing, client side will send the shape data to the server side controller, where the controller will then add a new shape that you drew on the canvas component. In this demo we have packed the code that handles this drawing process into a macro component, so that you can use it in your application more easily.

Here are the steps to pack the macro component;

  1. Add Component Class and Client Widget
  2. Add to your class path, and add paintDiv.js to your WebContent folder.

  3. Import javascript
  4. Add the following javascript to your zul file.

    <?script type="text/javascript" src="/zkpaint/scripts/paintDiv.js"?>
    • paintDiv.js adds a client widget for handling the canvas drawing at the client side and the sends the shape data back to the server.

  5. Declare Macro Component
  6. Declare paintDiv component in your zul file.

    <?component name="paintDiv" class="org.zkoss.canvas.zkpaint2.PaintDiv"?>
    • PaintDiv retrieves the shape date from client-side, then pack the shape info into a Drawable java object, then send the object to an event listener for manipulating the Drawable object.

  7. Use paintDiv Component in your zul file
  8. The paintDiv component is now ready, and you can use it in your zul file. For example,

    <?script type="text/javascript" src="/zkpaint/scripts/paintDiv.js"?>
    <?component name="paintDiv" class="org.zkoss.canvas.zkpaint2.PaintDiv"?>
    <?link rel="stylesheet" type="text/css" href="zkpaint/css/zkpaint.css"?>
    	<window id="zkpaintWindow" apply="org.zkoss.canvas.zkpaint2.PaintController" ...>
    		<paintDiv id="paintDiv" width="800px" height="500px"/>

Using paintDiv

The following section illustrates how you can use the paintDiv component to add a background image and edit your objects.

Add an image as a background

Add an Image object to paintDiv.

paintDiv.setContent((Image) media);

Then, listen the onImageReady event to retrieve an ImageSnapshot object when the image is loaded.

public void onImageReady$paintDiv(ForwardEvent event) {
	Map data = (Map) event.getOrigin().getData();
	paintDiv.addDrawable((ImageSnapshot) data.get("image"));

Set Shape Category to paintDiv

List<Shape> _shapes = new ArrayList<Shape>();
_shapes.add(new Rectangle(0, 0, 1000, 1000));
_shapes.add(new Path().moveTo(0, 0).lineTo(1000, 1000).closePath());

After setting Shape Category to paintDiv, you can now use shapeIndex to inform canvas what shape to draw. This makes it easier to plug in new shapes to the component.

Set Font Property

You can define the font type and size as you wish as illustrated in the following code snippet

paintDiv.setFont("30px serif");

Set Arrow Property

You can define the arrow property by using setArrowAttributes.

paintDiv.setArrowAttributes(5, 20, 25);//arrowWidth, tipWidth, tipLength

onAddShape, onAddText and onAddArrow Event

You can listen to onAddShape, onAddText and onAddArrow events, and retrieve a Drawable object from the event data, then add the object to paintDiv component.

public void onAddText$paintDiv(ForwardEvent event) {
	Map data = (Map) event.getOrigin().getData();
	paintDiv.addDrawable((Text) data.get("text"));
public void onAddShape$paintDiv(ForwardEvent event) {
	Map data = (Map) event.getOrigin().getData();
	paintDiv.addDrawable((Shape) data.get("shape"));

public void onAddArrow$paintDiv(ForwardEvent event) {
	Map data = (Map) event.getOrigin().getData();
	paintDiv.addDrawable((Shape) data.get("arrow"));

Select and Move

The actions of selecting and moving shapes are handled by, you do not have to handle it by yourself in your controller.


Saving edited images

Call paintDiv.exportPng() to save the canvas as an image. paintDiv.js will then export the canvas into a base64 string, and will receive the strings from the client-side. Then, we use Apache base64 to decode the strings into byte array format, then post an event with the byte data to the component.

Finally, you can retrieve the image that's in the form of a byte array in the event listener:

public void onExportPng$paintDiv(ForwardEvent event) {
	Map data = (Map) event.getOrigin().getData();
	byte[] byteData = (byte[]) data.get("byteData"); , "png", "canvas.png");


In this HTML5 canvas demo, we have illustrated the capabilities of adding an image as a background, drawing an arrow, selecting and moving objects, and exporting edited images. It now works like a simple web painting tool! Also, we have moved all the drawing processes out of the controller and organized the server and client implementation as a macro component. With this change it is now much easier to use this canvas4z component and maintain your application.



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.