DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • How to Merge HTML Documents in Java
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Creating Scrolling Text With HTML, CSS, and JavaScript
  • Mastering SSR and CSR in Next.js: Building High-Performance Data Visualizations

Trending

  • How to Ensure Cross-Time Zone Data Integrity and Consistency in Global Data Pipelines
  • Simpler Data Transfer Objects With Java Records
  • Mastering Deployment Strategies: Navigating the Path to Seamless Software Releases
  • How Can Developers Drive Innovation by Combining IoT and AI?
  1. DZone
  2. Coding
  3. JavaScript
  4. Using HTML5 Canvas with Apache Wicket

Using HTML5 Canvas with Apache Wicket

By 
Mihai Dinca - Panaitescu user avatar
Mihai Dinca - Panaitescu
·
Feb. 18, 13 · Interview
Likes (0)
Comment
Save
Tweet
Share
7.4K Views

Join the DZone community and get the full member experience.

Join For Free

This article wants to bring some hints about how to use HTML5 canvas with Apache Wicket web framework. Inside a Wicket application we want to have a panel with something drawn inside a HTML5 canvas. To make this happen we have to think about following:

  1. Do we really need HTML5?
  2. If we need HTML5, how to do it?
  3. What to do if browser version is an issue and it does not support HTML5?

1. First we should ask if we really need HTML5

If we need just an image then we should consider to draw inside a Java2D Graphics object. If we need some animation we should consider to draw inside a HTML5 canvas, but even in this case we need a simple Java2D image implementation if browser version is a concern and canvas is not supported.

Wicket has a RenderedDynamicImageResource class which is very handy for this because we can do Java2D stuff inside render(Graphics2D g2) method. A simple example may look like the following:


public class MyDynamicImageResource extends RenderedDynamicImageResource {
	
	private int width;
	private int height;
	private MyData data;						
	
	public MyDynamicImageResource (int width, int height, MYData data) {
		super(width, height);	
		this.width = width;
		this.height = height;
		this.data = data;
	}
	
	protected boolean render(Graphics2D g2) {
				
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);				

		// your code
	}
}
Because Java2d is used, we can set anti-aliasing to make the image look good.


Then we can use this dynamic resource to create our panel. We will use Wicket's NonCachingImage class, a subclass of Image that adds random noise to the url at every request to prevent the browser from caching the image. If you do not care that browser caches your image then you should use a simple Image instead.


public class MyJava2DImagePanel extends Panel {
	
		
	private MyDynamicImageResource imageResource;
	
	
	public MyJava2DImagePanel(String id, final int width, final int height, final IModel<MyData> model) {
		super(id, model);		

		NonCachingImage image = new NonCachingImage("myImage", new PropertyModel(this, "imageResource")) {
			private static final long serialVersionUID = 1L;

			@Override
			protected void onBeforeRender() {				
				imageResource = new MyDynamicImageResource(width, height, model.getObject());
				super.onBeforeRender();
			}
		};
		
		add(image);		
				
	}								

}

Markup html file for MyJava2DImagePanel will contain the image:

<wicket:panel>   
     <img wicket:id="myImage"></img>	         
</wicket:panel>

2. If we need some animation for our image, then we should think to draw it on a HTML5 canvas.

We should pay attention to draw things just once, meaning for example if we draw a text twice in same position , then our result will look ugly (pix-elated) because an anti-aliasing for canvas cannot be set as for Java2D Graphics object.

First we need to create our java script code. We can obtain a Java 2d context and use it to draw our image. I won't talk about canvas context and its methods here.

For animation we use jquery in following snippet, but you can use anything you like. Knowing two values (from, to) we can have for example a drawColor method which can paint different segments, creating this way a filling effect which takes in this example 1000ms :


var myWidget = function(id, color) {	 

    var can = document.getElementById(id);
    var ctx = can.getContext('2d');   
  
    // clear canvas
    ctx.clearRect(0, 0, can.width, can.height);	 	
	
    // draw your image on ctx
    .....    

    // animate color fill
       $({ n: from }).animate({ n: to}, {
          duration: 1000,    
          step: function(now, fx) {
             drawColor(id, now);       
          } 
       });  
    }
   
}  

Second we have to create our Wicket panel. Canvas is just a WebMarkupContainer and we set width and height through some AttributeAppenders:


public class MyHTML5Panel extends Panel {
	
	private final ResourceReference MY_JS = new JavaScriptResourceReference(MyHTML5Panel.class, "my.js");

	public MyHTML5Panel(String id, String width, String height, IModel<MyData> model) {
		super(id, model);
		WebMarkupContainer container = new WebMarkupContainer("canvas");
		container.setOutputMarkupId(true);
		container.add(new AttributeAppender("width", width));
		container.add(new AttributeAppender("height", height));		
		add(container);
	}
		
	@Override
    public void renderHead(IHeaderResponse response) {							
		
		response.renderOnLoadJavaScript(getJavascriptCall());
		
		//include js file
                response.renderJavaScriptReference(MY_JS);              
    }
	
	private String getJavascriptCall() {		 
		MyData data = getModel().getObject();
		StringBuilder sb = new StringBuilder();		
		sb.append("myWidget(\"").
		   append(get("canvas").getMarkupId()).
		   append("\",\"").append(data.getColor()).		   
		   append("\");");			
		return sb.toString();
	}
		

}

renderHead(IHeaderResponse response) method from Panel can use the IHeaderResponse object to render our java script call. Also, on the response object we should render our java script reference file.

We can use one of the following methods:


/**
	 * Renders javascript that is executed right after the DOM is built, before external resources
	 * (e.g. images) are loaded.
	 * 
	 * @param javascript
	 */
	public void renderOnDomReadyJavaScript(String javascript);

	/**
	 * Renders javascript that is executed after the entire page is loaded.
	 * 
	 * @param javascript
	 */
	public void renderOnLoadJavaScript(String javascript);

There are situations when we should call one or another depending on our business. As an example, if we need to expose our  wicket component to an external iframe, we must call onLoad instead of onDomReady to make it appear inside iframe because $(document).ready in the iframe seems to be fired too soon and the iframe content isn't even loaded yet.

HTML markup file MyHTML5Panel.html will contain the canvas tag:


<wicket:panel>   
     <canvas wicket:id="canvas"></canvas>         
</wicket:panel>

3. If we choose to use HTML5 panel but we also have to think about older browser that cannot support canvas tag, we will have to create both a Java2D and a HTML5 panel and see what to render by ourselves. A solution is to have a wrapper panel with a container which initially contains an EmptyPanel and we add a Wicket Behavior to the container. That behavior will choose what to render (html5 or simple image):


                .....   
                container = new WebMarkupContainer("container");
         	container.setOutputMarkupId(true);
                container.add(new EmptyPanel("image"));
		
                add(container);									           				
		add(new MyHTML5Behavior());		
                .......

The following java-script code is a way to test if canvas tag is supported by browser:


function isCanvasEnabled() {
	return !!document.createElement('canvas').getContext;
}

This function starts by creating a dummy <canvas> element which is never  attached to the page,
so no one will ever see it. As soon as we create the dummy <canvas> element, we test for the presence of a getContext() method. This method will only exist if browser supports the canvas API.
Finally, we use the double-negative trick to force the result to a Boolean value (true or false).

To call this java script and make the result available to Wicket we use wicketAjaxGet javascript method as seen in following code. We append a result parameter to callback url and inside respond method we can read the value of this parameter.

class MyHTML5Behavior extends AbstractDefaultAjaxBehavior {
    	
    	private String width;
    	private String height;

        private String PARAM = "Param";

    	    			
		public MyHTML5Behavior() {
			super();
		}

		@Override
		public void renderHead(Component component, IHeaderResponse response) {			
			super.renderHead(component, response);					
			
			//include js file
	        response.renderJavaScriptReference(MY_UTIL_JS);
	        
	        response.renderOnLoadJavaScript(getJavascript());	
		}

		@Override
		protected void respond(AjaxRequestTarget target) {
			String param = this.getComponent().getRequest().getRequestParameters().getParameterValue(PARAM).toString();					
			// test if html5 canvas tag is supported
			if (Boolean.parseBoolean(param)) {
			    container.replace(new MyHTML5Panel("image", width, height, model).setOutputMarkupId(true));
			} else {					
			    container.replace(new MyImagePanel("image", width, height, model).setOutputMarkupId(true));
			}				
			target.add(container);				
						
		}
		
		
		// this javascript call will make the PARAM available to wicket and can be read in respond method
		private String getJavascript() {
			StringBuilder sb = new StringBuilder();
			sb.append("var data = isCanvasEnabled();");
			sb.append("wicketAjaxGet('" + getCallbackUrl() + "&" + PARAM + "='+ data" 
				+ ", null, null, function() { return true; })");
			return sb.toString();
		}
    }	

These are just some hints on how to use HTML5 canvas inside Apache Wicket framework. I hope it will help others.


HTML Apache Wicket Java Script

Opinions expressed by DZone contributors are their own.

Related

  • How to Merge HTML Documents in Java
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Creating Scrolling Text With HTML, CSS, and JavaScript
  • Mastering SSR and CSR in Next.js: Building High-Performance Data Visualizations

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!