Fabric has a Composed
filter that can be used to mix together different effects into a single one.
This is not much different than adding more than one filter in the .filters
property of an image, but it comes handy when you want to define those 3 effects as a single block of effects with a meaning.
The duotone effect is obtained by reducing an image to two main tones that contrast with each other. This is similar to a black and white image, but mixing color A and color B rather than black to white.
Some tutorials such as this one demonstrate how to create this effect with the standard canvas api.
The logic is as follow:
What follows is a simple FabricJS implementation of this technique. Above the canvas we place two color pickers in order to change the input values to obtain different outputs.
Tip: In the JS part of the codepen, try to swap the Grayscale
filter with a BlackWhite
filter for a stronger effect.
var colorHandlerLight = function(evt) { duotoneFilter.subFilters[1].color = evt.target.value; globalImage.applyFilters(); canvas.requestRenderAll(); }; document.getElementById('colorLight').addEventListener('change', colorHandlerLight); var colorHandlerDark = function(evt) { duotoneFilter.subFilters[2].color = evt.target.value; globalImage.applyFilters(); canvas.requestRenderAll(); }; document.getElementById('colorDark').addEventListener('change', colorHandlerDark); var globalImage; var canvas = new fabric.Canvas('canvas'); var duotoneFilter = new fabric.Image.filters.Composed({ subFilters: [ new fabric.Image.filters.Grayscale({ mode: 'luminosity' }), // make it black and white new fabric.Image.filters.BlendColor({ color: '#00ff36' }), // apply light color new fabric.Image.filters.BlendColor({ color: '#23278a', mode: 'lighten' }), // apply a darker color ] }); fabric.Image.fromURL('https://ip.webmasterapi.com/api/imageproxy/http://fabric5.fabricjs.com/assets/pug.jpg', function(image) { globalImage = image; image.filters = [duotoneFilter]; image.scaleToWidth(480); image.applyFilters(); canvas.add(image); }, { crossOrigin: 'anonymous' });