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' });