Not a developer?

You’re probably looking for the original Aviary suite.

Log in to the Aviary suite

Developers: Log in or register using this form.

Web Documentation

Aviary Web Widget Documentation

Aviary's web widget (codename: Feather) can be embedded in any website with just a few lines of Javascript, adding simple yet powerful image editing to an existing workflow. The widget works in all major browsers (Chrome, Safari, Firefox, Internet Explorer 7+) and on all devices (PCs, laptops, iPads, smartphones) that support JavaScript and either HTML5 or Flash. Try the demo here.


Contents

Get the widget!

Create your own with the Code Generator.

Editor Javascript Url

See http://feather.aviary.com/js/feather.js ("feather.js")

Note: Please always call this script directly, as there are some server-side dependencies.


Introduction - High Level

The following describes how the editor works in your webpage in the most basic terms:

  1. Load feather.js
  2. Configure your widget instance with a configuration object
  3. After the DOM is ready and your instance has loaded, launch your instance.

API Overview

The API is inspired by the jQuery plugin pattern, wherein you pass a configuration object of key/value pairs. This allows for the widget to grow and introduce new features without breaking existing implementations or being constrained by its API.


Configuration

The following configuration parameters can be specified in your iniitalization. See the example integration.

image, apiKey, and apiVersion are required

image

required

Either the image element to be edited or its ID.

Note: Make sure the DOM has loaded before attempting select an element to pass as image, or use its ID instead. The image itself must be located in a publicly-accessible web folder, otherwise the widget will not work.


apiKey

required

Get your API key from the Get Key page. Saving will not work without it!
Note: when generating your API key, provide your root domain, even if you will be using it on subdomains.


apiVersion

required

This lets Aviary know which version of the editor to load and allows you some protection from breaking changes. The latest editor version is 2.


appendTo

The widget will be inserted inside the element with the DOM ID specified.

Note: For best results, this should be a <div /> element


language

The widget's UI is being localized into many languages. You can choose from en/English (default), de/German, fr/French, ja/Japanese, it/Italian, nl/Dutch, es/Spanish, or ru/Russian today - but our collection is always growing, so stay tuned if you're looking for a different option.

Note: You can also help us translate your own language! Shoot us an email at api@aviary.com if you'd like to send us a translation for a new language.


minimumStyling

Set to true to reduce our styles to the bare minimum in order to more easily add your own styles on top. This removes most textures, shadows, rounded corners, and gradients that can be tedious to reset.


maxSize

Set a max size of drawing canvas. See Best Practices.


noCloseButton

Set to 'true' to remove the close button.


tools

Select which editing tools you would like to display in the tools panel. We recommend either omitting tools or setting it to 'all' which will automatically give you our most up-to-date selection of recommended tools without updating your integration code.

  • all: selects all Aviary-recommended tools. (default)

You can also specify one or more options by name in an array or comma-separated string. Choose from our latest set of tools below:

  • enhance (new): Autocorrect your photo with one of four basic enhancements.
  • effects (new): Choose from a variety of effects and filters for your photo.
  • stickers: Choose from a variety of stickers you can resize and place on your photo.
  • orientation (new): Rotate and flip your photo in one tool.
  • resize: Resize the image using width and height number fields.
  • crop: Crop a portion of your photo. Add presets via API. Fixed-pixel cropPresets perform a resize when applied (new).
  • brightness: Adjust the overall image brightness.
  • contrast: Adjust the overall image contrast.
  • saturation: Adjust the overall image saturation.
  • sharpness (new): Blur or sharpen the overall image in one tool.
  • draw: Add doodle overlays with a brush.
  • text: Add custom, resizable text.
  • redeye: Remove redeye from your photo with a brush.
  • whiten: Whiten teeth with a brush. (Not supported in IE7-IE8)
  • blemish: Remove skin blemishes with a brush.

Tool Order: the order in which you list the options is the order in which they will appear in the editor. The editor options will be paged, so put the most important functions up front.

Legacy support: If you are using the legacy editor (apiVersion set to 1) the new tools are unavailable to you. However, you may find substitutes in the following deprecated tools.

  • rotate (deprecated): Rotate your photo in 90 degree increments.
  • flip (deprecated): Flip and mirror your photo.
  • colors (deprecated): Adjust the overall red, green and blue tone.
  • blur (deprecated) : Add a blur to the overall image.
  • sharpen (deprecated): Adjust the overall sharpness.

initTool

The widget can start with a specific tool open by passing its name here.


cropPresets

A comma-separated list of preset crop sizes or ratios for the crop tool. It can be a 2-D array (with labels), a 1-D array (without labels), or a comma-separated string (without labels). Any sizes over your maxSize will be excluded in the UI.

Defaults:

[
    '320x240','640x480','800x600','1280x1024','1600x1200',
    '240x320','480x640','600x800','1024x1280','1200x1600',
    'Original',
    ['Square', '1:1'],
    'Custom',
    '3:2', '3:5', '4:3', '4:6', '5:7', '8:10', '16:9'
]

You can label the presets by providing each as an array:

[
    ['Photo', '4:3'],
    ['HDTV', '16:9'],
    ['Avatar', '60x50']
]

We believe most resizes are based around preset sizes, and recommend the crop tool for the best control over framing your resized photo in one step. But if you cannot predict the sizes your users will need, manually enable the resize tool.


url

This is required if the image to be edited is on a different host than the host HTML page. Otherwise it is optional.

Note - this param should be omitted if possible. Providing it is a clue to our API that your image is on another domain and you need to request origin-clean data from our server which adds to image load time. It also requires that the image at the location be publicly available as our server must download it.


postUrl

Set a location on your server for Aviary to send a server-to-server HTTP POST to on save with information about the edited photo. A publicly accessible (and not password-protected) web service should listen here. See Saving Your Work and our examples.

Aviary will make an HTTP POST to the URL specified with the following data:

  • url : URL of the saved image.
  • postdata : any additional data specified in postUrl.

Note on security - Unfortunately we cannot guarantee an IP or range of IPs to expect due to our distributed hosting. Signing could be accomplished by clever use of postData


postData

Set data to be posted to the postUrl along with the saved file's url (See Saving Your Work, below). Expect all data assigned to postData to be sent to your postUrl as the postdata param, which will be serialized as a string.


fileFormat

coming soon
Set the saved file format. Accepts: png, jpg, original


jpgQuality

coming soon
Set the save quality of the image as a JPG file type. Accepts a number between 1 - 100.


onLoad

Pass a function to run once the widget has all resources ready for a launch (such as launching as soon as possible after page load). See Best Practices.


onReady

Pass a function to be called once the editor has finished launching and is ready for user input.


onSave(imageID, newURL)

Pass a function to be called when the image save is complete. A This can be used to set the image in the DOM to point to the new source.

imageID gives you an ID to reference the original image being edited.

newURL is a link to the saved image. It will persist at this address for approximately 72 hours.

Note - this image may not yet be ready so you will have to poll this link, or alternatively handle the hi-res image server-side at the location specified by PostUrl.

Return false to this handler if you'd like to suppress the built-in save confirmation dialog.


onClose(isDirty)

Pass a function to be called when the editor is closed.

isDirty tells whether the editor was closed with unsaved changes.


onError(errorObj)

The API can notify you of errors and you have the option to notify the user. They are otherwise silent.

errorObj is an object with the following properties:

  • code : int representing the error type. 1 corresponds to an image that could not be processed.
  • message : An error message you could pass along to the user.
  • args : This is an array of additional values that varies by error type. For example, error type 1, bad image, will send the problematic URL as the only argument in the array. This could assist in debugging or helping a user correct a specific problem.

Invocation

First, call feather.js from your web page

Next, instantiate the HTML5 editor with a configuration object:

var featherEditor = new Aviary.Feather(configObj);

Once you have created your instance (in this case, featherEditor) you have a few methods at your disposal.

launch

You can open the editor on demand using its launch method:

featherEditor.launch(overrideConfigObj);

At this point you can override any of the configuration parameters except for theme, language and onLoad. Or, if all required parameters are provided, you can omit any configuration at this time.

The first two parameters define the HTML and CSS the editor will use. onLoad is no longer valid as the editor has loaded by this time.


save

The save method lets you save progress through some separate UI, such as a button on your hosting page. It is not typically necessary, as the user can always save from within the editor at any time.

featherEditor.save();

close

You can shut down the editor programmatically with the close method.

Use with care, as this will discard any unsaved changes without prompting the user. For this reason it is commonly used onSave if at all.

May be useful when noCloseButton is set to true.

featherEditor.close();

Example

Pre-integration:

<img id="editableimage1" src="http://example.com/public/images/goat.jpg"/>

Post-integration:

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


<!-- Instantiate the widget -->
<script type="text/javascript">

    var featherEditor = new Aviary.Feather({
        apiKey: '1234567',
        apiVersion: 2,
        tools: ['draw', 'stickers'],
        onSave: function(imageID, newURL) {
            var img = document.getElementById(imageID);
            img.src = newURL;
        },
        postUrl: 'http://example.com/featherposturl'
    });

    function launchEditor(id, src) {
        featherEditor.launch({
            image: id,
            url: src
        });
        return false;
    }

</script>                         

<!-- Add an edit button, passing the HTML id of the image
    and the public URL to the image -->
<a href="#" onclick="return launchEditor('editableimage1', 
    'http://example.com/public/images/goat.jpg');">Edit!</a>

<!-- original line of HTML here: -->
<img id="editableimage1" src="http://example.com/public/images/goat.jpg"/>

Saving Your Work

What happens on a save

  1. (Client) User clicks the save button.
  2. (Client) The widget posts the image data along with configuration parameters to Aviary
  3. (Server) Aviary saves the image temporarily and sends a response back to the widget with that location.
  4. (Client) On this callback, the widget will call any function passed to onSave, and then shows a confirmation dialog to the user.
  5. (Server) Aviary makes a HTTP POST to postUrl.
  6. (Server) Your postUrl service receives information from Aviary and can save the edited images locally.

Server-side Examples

Ruby

#url
#postdata: originalName
post "/save" do
    #original photo name is postdata
    orig_name = params[:postdata]
    new_name = orig_name + " (edited with Aviary)"
    # Retrieve a file object from the image URL
    image_from_web  = open(params[:url]) {|f| f.read }
    # get file name from URL
    file_name = params[:url].split("/").pop()
    # Write the file to the local filesystem
    Dir.chdir("tmp")
    File.open(file_name, 'w') {|f| f.write(image_from_web) }
    Dir.chdir("../")

end

PHP

<?php

    $image_data = file_get_contents($_REQUEST['url']);

    file_put_contents("photo.jpg",$image_data);

?>

ASP.NET

protected void Page_Load(object sender, EventArgs e)
{
    string postdata = Request["postdata"]; // an encoded reference to the file that you're updating perhaps
    string url = Request["url"]; // the url of the saved file

    string localFileDest = "..."; // file save destination

    WebClient client = new WebClient();
    client.DownloadFile(url, localFileDest);
}

Best Practices

When to embed the editor in your layout and when to let it fill the screen

You should provide a <div/> element ID to the appendTo parameter when you want full control over the editor experience (i.e. launching the editor in your own custom lightbox). It is best suited for more advanced integrations. Because the editor tries to fill the space alotted it, we recommend you specify a fixed width and height in CSS, as well as a position property of relative, absolute, or fixed so that the container is considered a positioned element.

Do not provide an element to appendTo if you want to show larger images closer to their native size, and/or your layout does not provide suitable space for the editor (at least 714px wide by 400px high). This will launch the editor in a simple lightbox that floats above the page in z-order and temporarily darkens the rest of the page until the editing is complete. It also offers users the most room for tools visible at once. This is generally the recommended approach.


Larger Images

For the best user experience, please note that this lightweight editor is meant to handle file sizes intended for web display, not original resolutions. If you are interested in working with the API in original resolutions, please contact partners@aviary.com

You can use the maxSize parameter to set the maximum size of the output image and the actual size of the editing canvas. The API only accepts one value that it uses to specify that max height and width of the canvas. This prevents the canvas from getting too wide if a taller image is rotated, for example. The default (recommended) value is 800 (800x800 pixels).


Waiting for the Widget to Initialize

Calling launch() before the widget has loaded and initialized will have no effect. A nice usability enhancement is to disable the "Edit" button and only enable it onLoad. Assuming in the examples above, the "Edit!" link has an ID of "edit-button" and a style of "display: none":

var featherEditor = new Aviary.Feather({
    onLoad: function() {
        document.getElementById('edit-button').style.display = 'block';
    }
});

Note: Make sure the callback function in either of these examples runs after the DOM is ready and the edit button is accessible with JavaScript. See jQuery's .ready() method for more details.


Custom CSS Styling

Overriding Aviary CSS selectors

Custom CSS styling of the editor is possible. Be sure to make your overrides robust enough to supercede our own styles (usually accomplished by simply prepending body to the selector).

Blank Canvas

The minimumStyling config param can be very helpful if you plan to do heavy customization as it gives you something of a blank canvas.

Style Guide

The widget can be styled according to our public style guide, but hooking into any other markup is not supported so please limit customization to the following:

/* general font color/reset */
body .avpw *,
body .avpw a,
body .avpw a:link,
body .avpw a:hover,
body .avpw a:visited,
body .avpw a:active {
  color: #444;
}
/* "gears" background behind image */
.avpw .avpw_canvas_background {
  background: #121212 url(../images/gears_background.png);
}
/* brushed metal texture */
/* outermost widget body/parent */
body .avpw {
  background: #efefef url(../images/metal_texture.png) 50% 0%;
}
/* small icon inside an open tool */
.avpw .avpw_current_tool_icon {
  background: #efefef url(../images/metal_texture.png) 50% 25px;
}
/* popups that open within the widget */
.avpw .avpw_app_popup {
  background: #efefef url(../images/metal_texture.png) 50% 25px;
}
/* footer text */
.avpw .avpw_footer_text,
.avpw .avpw_footer_text a,
.avpw .avpw_footer_text a:link,
.avpw .avpw_footer_text a:visited,
.avpw .avpw_footer_text a:hover,
.avpw .avpw_footer_text a:active {
  color: #656565;
}
/* tool icons */
/* normal */
.avpw .avpw_tool_icon_image {
  background-color: #efefef;
}
/* hover */
.avpw .avpw_tool_icon:hover .avpw_tool_icon_image {
  background-color: #ffffff;
}
/* pressod */
.avpw .avpw_tool_icon_down .avpw_tool_icon_image,
.avpw .avpw_tool_icon_down:hover .avpw_tool_icon_image {
  background-color: #e2e2e2;
}
/* tools paging inidcator */
body .avpw .avpw_page {
  color: #3d3d3d;
}
body .avpw .avpw_page_selected {
  color: #00a5ff;
}
/* default buttons */
body .avpw .avpw_button {
  background: #efefef;
}
/* hover */
body .avpw .avpw_button:hover {
  background: #ffffff;
}
/* pressod */
body .avpw .avpw_button.avpw_button_down {
  background-color: #e2e2e2;
}
/* primary button
 * (overriding color on these links so
 * we have to be explicit)
 */
body .avpw .avpw_primary_button,
body .avpw .avpw_primary_button:link,
body .avpw .avpw_primary_button:visited,
body .avpw .avpw_primary_button:active {
  background-color: #0084cc;
  color: #ffffff;
}
/* +/- slider label/buttons */
body .avpw .avpw_slider_label {
  color: #707070;
}
/* darker, cut-out color */
.avpw .avpw_inset_background {
  background-color: #2d2d2d;
}
/* preset icons */
.avpw .avpw_preset_icon {
  border-left-color: #474747;
  border-right-color: #141414;
}
.avpw .avpw_preset_icon_active {
  background-color: #414141;
}
/* and light blue indicator */
.avpw .avpw_preset_icon_active .avpw_preset_indicator {
  background: #00a5ff;
}
/* grouped push-buttons inside tools */
.avpw .avpw_inset_button {
  border-left-color: #474747;
  border-right-color: #141414;
}
/* hover */
.avpw .avpw_inset_button:hover {
  background-color: #2a2a2a;
}
/* pressod */
.avpw .avpw_inset_button_down {
  background: #141414;
}
/* text input fields */
body .avpw .avpw_text_input {
  background: #ffffff;
  color: #bcbec0;
}
/* focus */
body .avpw .avpw_text_input_focused {
  color: #3d3f40;
}
/* palette swapped on dark background */
.avpw .avpw_inset_background .avpw_text_input {
  background: #414141;
}
/* focus */
.avpw .avpw_inset_background .avpw_text_input_focused {
  color: #ffffff;
}
/* labels palette swapped on dark background */
.avpw .avpw_inset_background .avpw_label {
  color: #ffffff;
}
/* lock icon */
/* 'unlocked'/default state */
.avpw .avpw_inset_button .avpw_lock_icon_top,
.avpw .avpw_inset_button .avpw_lock_icon_bottom {
  background: #a3a3a3;
}
.avpw .avpw_inset_button .avpw_lock_icon_top_inner,
.avpw .avpw_inset_button .avpw_lock_icon_sep {
  background: #383838;
}
/* 'locked'/down state */
.avpw .avpw_inset_button_down .avpw_lock_icon_top, 
.avpw .avpw_inset_button_down .avpw_lock_icon_bottom {
  background: #00a5ff;
}
.avpw .avpw_inset_button_down .avpw_lock_icon_top_inner,
.avpw .avpw_inset_button_down .avpw_lock_icon_sep {
  background: #141414;
}

Getting Updates from Aviary's Development Team

If you use the widget on your site, it's very important for us to be able to contact you. Please, please, please make sure to enter a valid email at the time you generate an API key. We will use this email to inform you when we are introducing new features, making any planned layout changes, and most importantly if we need to introduce any changes to our editor that might impact your site. We will not spam you or share your email with any third party services.