You can use the Shutterstock Editor integration to spawn the editor application in a container on a partner page. For a live demo, see JS bin.

First, include the library file on the parent page:

<script src="https://s.picdn.net/editor/image/assets/integration.js"></script>

This library exposes an Editor property on the parent window, which accepts a configuration object:

const editor = window.Editor({
    ...options
});

Example

This example code launches an instance of Editor with the default options.

<script src="https://s.picdn.net/editor/image/assets/integration.js"></script>
<script>
    window.Editor({
      apiKey: EDITOR_API_KEY
    }).launch();
</script>

API keys

The Editor instance requires an API key. For testing purposes, you can use the key XDj5YViial3ibnnevAfmGi14, which works only for local testing (when the URL starts with http://localhost). To request an API key so you can host Editor on your own domain, Contact us.

Setting options

With the options object, you can control the dimensions of the Editor instance, the preset image sizes, the starting canvas settings, and other behaviors.

<script src="https://s.picdn.net/editor/image/assets/integration.js"></script>
<script>
var editorInstance = window.Editor({
  apiKey: EDITOR_API_KEY,
  language: 'en',
  image: 'https://www2.shutterstock.com/blog/wp-content/uploads/sites/5/2015/05/volcano-header-1440x960.jpg',
  excludeFeatures: ['filters'],
  initialPanel: 'text',
  logo: true,
  logoUrl: 'https://www2.shutterstock.com/base/public/images/logos/logo-shutterstock-de64a370ef.png',
  primaryActionText: 'Save and close',
  container: document.querySelector('#editor'),
  canvas: {
    height: 500,
    width: 500,
    fill: 'rgb(62, 69, 79)'
  },
  presets: [{
    name: 'Icon',
    height: 128,
    width: 128
  }, {
    name: 'Book Cover',
    height: 1600,
    width: 2400
  }],
  onPrimaryAction: function() {
    editorInstance.ui.showActivityIndicator()
    .then(() => editorInstance.getBase64({
      format: 'jpg',
      quality: .91
    }))
    .then((base64) => {
      // do something with the base64 data
    })
    .then(editorInstance.ui.hideActivityIndicator)
    .then(editorInstance.hide);
  }
});

// Launch instance of Editor
editorInstance.launch().then(function(editor) {
  // Editor is loaded and ready for user interaction
}).catch(function(err) {
  // Handle error
});
</script>

Loading external images and logos

You can open an external image in Editor with the image parameter. If you specify a URL to the image, the image must be a JPEG or PNG file and it must have CORS headers set for https://www.shutterstock.com to be able to load the image anonymously within the iframe. Alternatively, you can specify an HTMLImageElement element on the parent page If the page that loads Editor has the proper CORS headers to load the image, Editor inherits the parent page's CORS policy. For example, this code loads the image in the element with the ID image-to-edit:

const editor = Editor({
    apiKey: EDITOR_API_KEY,
    image: document.getElementById('image-to-edit')
});

You can also use a custom logo by specifying the logo URL in the logo parameter. This image must have CORS headers set for https://www.shutterstock.com to be able to load the logo anonymously within the iframe.

Excluding features

You can hide Editor features with the excludeFeatures parameter. To hide features, include one or more of these values in the parameter:

  • preset_size
  • text
  • shapes
  • backgrounds
  • filters
  • uploads
  • search
  • pages

Initial panel

The initialPanel parameter activates a specified panel when the instance opens. You can open the following panels:

  • elements
  • pages
  • preset_size
  • search
  • text

Custom presets

You can configure one or more preset dimensions with the presets parameter. Preset height and width must be between 0 and 12,000 pixels. For example:

presets: [{
    name: 'Icon',
    height: 128,
    width: 128
}, {
    name: 'Book Cover',
    height: 1600,
    width: 2400
}]

Running headless

You can hide the Editor instance from the parent page by setting the hidden parameter to true. All operations are still available, but no user interface appears on the page. You can toggle the appearance with the hide() and show() methods. When the promise returned by .launch() resolves, the Editor instance is ready for user interaction and can be shown, as in the following example:

const editor = Editor({
    apiKey: EDITOR_API_KEY,
    hidden: true,
});
editor
  .launch()
  .then(editor.show);

Options

This table lists the options that you can set on the Editor instance:

Parameter Description Type Example
apiKey (Required) Partner API key String '89TuQL0KE6SQJ7bcCZHE12Cm'
container Container element to insert Editor into Element 'document.querySelectorAll('#e')'
debug Whether to log developer debugging information Boolean true
excludeFeatures List of features to hide Array ['filters', ...]
image The URL or image data of an image to load String, ImageData, or HTMLImageElement 'http://example.site/image.jpg'
initialPanel Panel activated by default String 'shapes'
hidden Whether to hide the UI from view (headless) Boolean true
hideCloseButton Hide or show close button Boolean true
language ISO 639‑1 supported language code String 'de'
logo Whether to show the logo Boolean true
logoUrl URL to a custom logo String 'http://example.site/image.jpg'
presets List of preset objects Array [{name: 'Icon', height: 128, width: 128}]
preventClose Whether to prevent the editor from closing when the close button is clicked Boolean true
primaryActionText Primary action button text content String 'Download'
showPrimaryActionButton Whether to show the primary action button (default: true) Boolean true
canvas
- canvas.fill Initial fill color of the canvas String '#ff0000'
- canvas.width Initial width of the design Integer 500
- canvas.height Initial height of the design Integer 200

Methods

An instance of the Editor library exposes these methods for advanced interactions with the instance:

Name Description Return value
addBackgroundImage({ image, properties }) Adds an image to the canvas as the background, replacing any existing background image. The image field can be a URL string or an ImageData object. The properties field is an optional FabricJS object properties object. Promise<Object> of FabricJS properties for the image
addImage({ image, properties }) Adds an image to the canvas. The image field can be a URL string or an ImageData object. The properties field is an optional FabricJS object properties object. Promise<Object> of FabricJS properties for the image
clear() Removes all of the elements on the canvas. Promise
close() Closes and removes the Editor instance. Promise
download({ format, quality }) Renders and downloads the image directly to the user's browser. Accepts an optional option object with format and quality fields. Be careful that calling hide() the promise resolves can make downloads fail. The format field is 'jpg', 'png', or 'webm'. The quality field is a number between 0 and 1. Promise
getBase64({ format, quality }) Returns the base64 data for the current design. Accepts an optional option object with format and quality fields. The format field is 'jpg', 'png', or 'webm'. The quality field is a number between 0 and 1. Promise<String>
getBlob({ format, quality }) Returns the blob data for the current design. Accepts an optional option object with format and quality fields. The format field is 'jpg', 'png', or 'webm'. The quality field is a number between 0 and 1. Promise<String>
getDesign() Gets the JSON data for the current design. Promise<Object>
getImageData() Returns the raw image data for the current design. Promise<ImageData>
hide() Hides the Editor UI from view. Promise
launch() Initializes the Editor instance. Promise
setDesign(json) Sets the current design to the supplied JSON data. Promise
show() Restores the Editor UI into view. Promise

Events

You can add listeners to events that happen in the Editor instance in these ways:

  • You can add the listeners to the options object:
var editorInstance = window.Editor({
  apiKey: EDITOR_API_KEY,
  language: 'en',
  image: 'https://www2.shutterstock.com/blog/wp-content/uploads/sites/5/2015/05/volcano-header-1440x960.jpg',
  onClose: function() {
    | alert('Goodbye');
  },
  onPrimaryAction: function() {
    editorInstance.getBase64({
      format: 'jpg',
      quality: .91
    }).then(function(base64) {
      // Handle base64 image data
      editorInstance.hide();
    });
  }
});
  • You can add listeners to the instance after you initialize it:
editorInstance.on('close', function() {
  alert('Goodbye.');
});

This table lists the events to which you can add listeners:

Name Description Supplied data
close Called when the Editor instance is closed none
error Called when an error occurs Error data
hide Called when the Editor instance is hidden none
open Called when the Editor instance is opened none
primaryaction Called when the primary action button is activated none
show Called when the Editor instance is shown none
designChanged Called when the user changes the design none

Dealing with CORS (Cross Origin Resource Sharing)

In order to import images into the Editor canvas, the images need to be able to added to the canvas in an "untainted" fashion. Tainting the canvas with a non-CORS image prevents Editor from functioning correctly. In order to prevent the canvas from being tainted, images loaded into Editor must be one of the following:

  • If you load the image via a URL, the web server that hosts the image must include CORS headers (and respond to the OPTIONS HTTP verb) that allow www.shutterstock.com to load the image cross-origin.
  • If you load the image in an element on the parent page and pass it to the Editor instance either by using the image option at Editor launch or by calling the addImage() or addBackgroundImage() methods, the image must still not trigger a tainted canvas. In this case, you must either serve the image from the same host name as the parent page or serve the image from a server with the corresponding CORS headers and load the image in an <img> tag with the crossorigin attribute configured.

For example, the following code extracts the image data from an image element for use with the addImage and addBackgroundImage methods:

// Create an image
const img = document.createElement('img');
img.src = someUrlToLoadImage;
img.crossOrigin = 'anonymous'; // Or 'use-credentials'
img.onload = () => {
  // Create an empty canvas element
  const canvas = document.createElement('canvas');
  // Match the canvas dimensions to the image dimensions
  canvas.width = img.naturalWidth;
  canvas.height = img.naturalHeight;

  // Copy the image contents to the canvas
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

  let imageData;
  try {
    // Get the ImageData from the canvas
    imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  } catch (e) {
    // example of errors would be CORS issues
    console.error(e);
  }
  // Use the imageData to add an image to Editor
  editor.addImage({ image: imageData });
};

Preloading Editor

Depending on network and other factors, Editor takes 6-20 seconds to load. To improve performance, you can load a hidden Editor instance on page load or during idle time and then show the instance when it is needed. The following code loads the Editor instance but does not show it until the showEditor() method is called.

let editor;

// At page load or idle
function initEditor() {
  editor = new Editor({
    ...options,
    hidden: true,
  });

  return editor.launch();
}

// at some point in the future....
function showEditor() {
  editor.show();
}

Limitations and requirements

Browser and operating system support for embedded Editor instances matches that of the core Editor application:

  • Windows (modern versions)
  • OS X (modern versions)
  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Internet Explorer 11
  • Microsoft Edge

Designs exported from Shutterstock Editor must not exceed 12,000 x 12,000 pixels in dimension.

Foreign language support

Editor supports all languages supported by Shutterstock. See https://www.shutterstock.com for a full list of languages.