HTML5 CreateJS Photo Editor with Aviary

Aviary is a service to quickly integrates a photo editor into your HTML5, IOS, Android and WP7 applications and in this article I show you a little demo to use this amazing widget into your CreateJS/HTML5 canvas mobile and desktop web app.

Aviary Website: http://www.aviary.com

In few words you can open an image from your HTML5/CreateJS application into the Aviary Widget, apply effects, filters and a lot of other stuff, and return the generated image to your canvas.

Here you can watch a short video of my first test and following the source code with some notes and suggestions.

Honestly, I admit I didn’t know this service until today, so following code is just a very crude demo I have created to show you how it’s useful : )
Furthermore the script might be hard to understand if you haven’t experience with EaselJS and Javascript.

Feel free to ask me more info if you don’t understand some EaselJS instructions. If you have any Aviary question you can get further info from Aviary Custom service:
http://www.aviary.com/support/contact
http://www.aviary.com/support/faq

CODE
In the first part of the following code I use EaselJS to display and center an image on Stage:

How it works:
- I first load and display a default image on Stage
– when the image is clicked the Aviary panel is opened and you can apply your image effects.
– when the user saves its work, the “onSave” event is fired. Then we destroy the previous image and we load and display the new generated bitmap.
– when the user closes the Aviary panel we apply a TweenJS animation to the new bitmap.

Most of the second part of the code is generated from the Aviary Service. To get it you need to subscribe their free service and create a new app from their panel.

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" 
		  content="text/html; charset=UTF-8" />

	<title>EaselJS + Aviary</title>

	<!-- import CreateJS libraries  -->
	<script src="lib/easeljs-NEXT.min.js"></script> 
	<script src="http://code.createjs.com/tweenjs-0.3.0.min.js"></script>
	
	<script>	

	// Image to load
	var url = "http://static.ddmcdn.com/gif/urban-landscape-design-1.jpg";

	var stage;
	var canvas;
	var canvasImg;
	var aviaryImgPlaceHolder ;
	

	function init() {

		canvas = document.getElementById("mycanvas");
		stage = new createjs.Stage(canvas);

		// Enable Mouse and Touch support
		if (createjs.Touch.isSupported()) { createjs.Touch.enable(stage); }
		stage.enableMouseOver (20)

		// Set Framerate and Ticker listener
		createjs.Ticker.setFPS(45);		
		createjs.Ticker.addListener(this);

		// Load the default image at startup
		loadImage(url)
	}

	/**
	 * Load the image using a PHP Proxy
	 * It's a necessary step in order to avoid security restrictions 
	 */
	function loadImage(path) {
		// Load the image into the aviary <img> placeholder 
		aviaryImgPlaceHolder = document.getElementById("aviaryImgPlaceHolder")
		aviaryImgPlaceHolder.onload = onLoadImage;
        aviaryImgPlaceHolder.src =  "php/proxy.php?url=" + path; 
	}


	/**
	 * Image Loaded event handler
	 * It's used to load the default image and to load the 
	 * generated image from Aviary service
	 */
	function onLoadImage(event) {

		// Remove the previous EaselJS Bitmap from stage
		if (stage.contains(canvasImg))
			stage.removeChild(canvasImg)

		// Create a new EaselJS Bitmap from the loaded bitmap
		canvasImg = new createjs.Bitmap(event.target)
		canvasImg.cursor = "pointer"
		canvasImg.regX = canvasImg.image.width/2;
		canvasImg.regY = canvasImg.image.height/2;
		//canvasImg.suppressCrossDomainErrors = true;
		canvasImg.x = canvas.width/2;
		canvasImg.y = canvas.height/2;

		// Enable Press event handler 
		canvasImg.addEventListener("press", function (event)
		{	
			// Open the Aviary Editor
			return launchEditor('aviaryImgPlaceHolder', url)
		})

		// Add the image to Stage
		stage.addChild(canvasImg)

	}


	/**
	 * Aviary panel SAVE event handler
	 * Invoked when the user SAVES the image from  Aviary panel
	 */
	function onAviarySaveHandler(imageID, newURL) {
		url = newURL;
		loadImage(newURL)
	}


	/**
	 * Aviary panel CLOSE event handler
	 * Invoked when the user CLOSES the  Aviary panel
	 */
	function onAviaryClose() {	

		// rotate the generated image using TweenJS
		createjs.Tween.get(canvasImg)
						  .to({rotation: 360, scaleX: 0.5}, 
						  	   1000,createjs.Ease.cubicInOut)
						  .wait(200)
						  .to({rotation: 0, scaleX: 1}, 
						  	   1000,createjs.Ease.cubicInOut)
	}
	

	 /**
	 * Tick event handler
	 */
	function tick()
	{
		// Update stage
		stage.update()	
	}


	</script>
</head>
	

<!-- 
	Most part of following code is generated from Aviary.
	Subscribe the service and create an App from the panel to get it.
	
	Website: http://www.aviary.com.
	Documentation: http://www.aviary.com/web/documentation
-->

<!-- Load Feather code -->
<script type="text/javascript" 
		src="http://feather.aviary.com/js/feather.js"></script>

<!-- Instantiate Feather -->
<script type='text/javascript'>
   var featherEditor = new Aviary.Feather({
       apiKey: '[YOUR API KEY]',
       apiVersion: 2,
       tools: 'enhance,effects,stickers,orientation,resize,warmth,crop,brightness,contrast,saturation,sharpness,draw,text,redeye,whiten,blemish',
       appendTo: '',
       onSave: onAviarySaveHandler,
       onClose: onAviaryClose,
       onError: function(errorObj) {
           alert(errorObj.message);
       }
   });
   function launchEditor(id, src) {
       featherEditor.launch({
           image: id,
           url: src
       });
      return false;
   }
</script>



<body onload="init();">	

	<canvas id="mycanvas" width="960" height="450" 
			style="background-color: #cccccc"></canvas>

	<img id='aviaryImgPlaceHolder' style="display: none"/>
</body>
</html>


I have used the EaselJS 0.5.0 “NEXT” version available on CreateJS GitHub page, required to use addEventListener and the cursor property.

Furthermore, in order to use Aviary with EaselJS, I have used two little workarounds :

1) To load images (from web and from the Aviary service) I have used a simple PHP proxy to avoid security restrictions with cross-domain content.

2) Since to open the Aviary Editor we need to pass the image ID and its URL, I have created an hidden html < img > placeholder (called “aviaryImgPlaceHolder”) and I use it to load images and to get a reference ID to pass to Aviary launchEditor method.
I have tried to dinamically create an Image object but it didn’t work with Aviary. Feel free to fix and improve this step.
My purpose was just testing this service with EaselJS and I didn’t spend a lot of time on this “issue”.

Hope you enjoy it

Comments (1)

  1. Adrian Parr (reply)

    December 12, 2012 at 2:24 pm

    Very cool Fabio. Thanks for sharing!

Leave a Reply

Your email address will not be published. Required fields are marked *

Published on: 11 December 2012
Posted by:
Discussion: 1 Comment