Skip to main content

HTML5 Canvas Multiple Filters Tutorial

To apply multiple filters to an Konva.Image, we have to cache it first with cache() function. Then apply filters with filters() function.

Instructions: Use the checkboxes to toggle different filters and adjust their values with the sliders.

For all available filters go to Filters Documentation.

import Konva from 'konva';

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight,
});

const layer = new Konva.Layer();
stage.add(layer);

const imageObj = new Image();
imageObj.onload = () => {
  const image = new Konva.Image({
    x: 50,
    y: 50,
    image: imageObj,
    draggable: true,
  });

  layer.add(image);
  image.cache();

  // Create controls container
  const container = document.createElement('div');
  container.style.position = 'absolute';
  container.style.top = '20px';
  container.style.left = '20px';
  document.body.appendChild(container);

  // Filter states
  const filterStates = {
    blur: false,
    brightness: false,
    contrast: false,
  };

  const filterValues = {
    blur: 10,
    brightness: 0.3,
    contrast: 50,
  };

  // Create filter controls
  const createFilterControl = (name, min, max, step, defaultValue) => {
    const div = document.createElement('div');
    div.style.marginBottom = '10px';
    
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.id = name;
    checkbox.checked = filterStates[name];
    
    const label = document.createElement('label');
    label.htmlFor = name;
    label.textContent = ` ${name.charAt(0).toUpperCase() + name.slice(1)}: `;
    
    const slider = document.createElement('input');
    slider.type = 'range';
    slider.min = min;
    slider.max = max;
    slider.step = step;
    slider.value = defaultValue;
    slider.style.width = '200px';
    slider.disabled = !filterStates[name];
    
    div.appendChild(checkbox);
    div.appendChild(label);
    div.appendChild(slider);
    
    checkbox.addEventListener('change', (e) => {
      filterStates[name] = e.target.checked;
      slider.disabled = !e.target.checked;
      updateFilters();
    });
    
    slider.addEventListener('input', (e) => {
      filterValues[name] = parseFloat(e.target.value);
      updateFilters();
    });
    
    return div;
  };

  // Add controls
  container.appendChild(createFilterControl('blur', 0, 40, 1, filterValues.blur));
  container.appendChild(createFilterControl('brightness', -1, 1, 0.1, filterValues.brightness));
  container.appendChild(createFilterControl('contrast', -100, 100, 1, filterValues.contrast));

  function updateFilters() {
    const activeFilters = [];
    
    if (filterStates.blur) {
      activeFilters.push(Konva.Filters.Blur);
      image.blurRadius(filterValues.blur);
    }
    if (filterStates.brightness) {
      activeFilters.push(Konva.Filters.Brighten);
      image.brightness(filterValues.brightness);
    }
    if (filterStates.contrast) {
      activeFilters.push(Konva.Filters.Contrast);
      image.contrast(filterValues.contrast);
    }
    
    image.filters(activeFilters);
    layer.batchDraw();
  }
};
imageObj.src = '/images/lion.png';