首页 > 解决方案 > Fabric JS 多重过滤器处理(更换或添加过滤器)

问题描述

我有几个滑块,每个滑块都对我的画布应用不同的过滤器(见下图)。

在此处输入图像描述

但是当我多次使用相同的滑块时,相同的过滤器会被应用到画布上。(见下filters图中的属性)。

我希望过滤器仅在它们来自相同的滑块输入时才能相互替换。ieBrightness并且Saturation可以同时存在,但永远不会有 2 个Brightness堆叠在一起。我还发现我不能依赖 in 的type属性,filters因为我的一些滑块可能会导致相同的type. 这个问题有什么顺利的解决方案吗?

以下是当前如何将过滤器应用于画布的示例代码。

function saturate(o, value){
  value = value / 100
    let filter = new fabric.Image.filters.Saturation({
      saturation: value,
    });
    if (o.filters) {
      o.filters = []
      o.filters.push(filter);
      o.applyFilters();
    }
}

**Below is the output of `canvas.toObject()` (see the `filter` attribute)**

在此处输入图像描述

标签: javascriptreactjscanvasfabricjs

解决方案


fabric.Image.filters在每个用户输入上创建一个新的,您只需初始化一次过滤器并将其注册到对象或数组中,并在需要应用更改时检索和编辑其值。

在这个演示页面中,您可以看到过滤器只创建一次,存储在一个filters对象中,并根据用户输入进行更新。

const canvas = new fabric.Canvas("c");
const filters = {};

init()
async function init() {
  const [width, height] = [window.innerWidth, window.innerHeight/2];
  
  // Setting the canvas size
  canvas.setWidth( width );
  canvas.setHeight( height );
  canvas.calcOffset();
  
  // load the image
  const img = new Image();
  img.crossOrigin = "";
  await new Promise(res => {
    img.onload = res;
    img.src = `https://picsum.photos/${width}/${height}`;
  });
  const image = new fabric.Image(img);
  canvas.add(image)
  
  // Create and register the filters in `filters` object
  const filters = {
    brightness: new fabric.Image.filters.Brightness(),
    saturation: new fabric.Image.filters.Saturation(),
    contrast: new fabric.Image.filters.Contrast(),
    hue: new fabric.Image.filters.HueRotation(),
  }
  
  // - Brightness
  // Attach the filter to the image
  image.filters.push(filters.brightness);
  const brightnessInput = document.querySelector("#brightness")
  brightnessInput.oninput = () => {
    const value = parseFloat(brightnessInput.value);
    // Edit the filter value
    filters.brightness.brightness = value;
    // Apply the changes
    image.applyFilters();
    // Display the result 
    canvas.renderAll();
  }

  // - Saturation
  // Attach the filter to the image
  image.filters.push(filters.saturation);
  const saturationInput = document.querySelector("#saturation")
  saturationInput.oninput = () => {
    const value = parseFloat(saturationInput.value);
    // Edit the filter value
    filters.saturation.saturation = value;
    // Apply the changes
    image.applyFilters();
    // Display the result 
    canvas.renderAll();
  }
  
  // - Contrast
  // Attach the filter to the image
  image.filters.push(filters.contrast);
  const contrastInput = document.querySelector("#contrast")
  contrastInput.oninput = () => {
    const value = parseFloat(contrastInput.value);
    // Edit the filter value
    filters.contrast.contrast = value;
    // Apply the changes
    image.applyFilters();
    // Display the result 
    canvas.renderAll();
  }
  
  // - Hue
  // Attach the filter to the image
  image.filters.push(filters.hue);
  const hueInput = document.querySelector("#hue")
  hueInput.oninput = () => {
    const value = parseFloat(hueInput.value);
    // Edit the filter value
    filters.hue.rotation = value;
    // Apply the changes
    image.applyFilters();
    // Display the result 
    canvas.renderAll();
  }
}
body {
  margin: 0;
  font-family: arial;
}

div {
  padding: .5em 1em;
}

p {
  display: flex;
  margin: 0 0 .5em;
}

label{
  flex:.2;
}

input {
  flex:1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/451/fabric.min.js" integrity="sha512-qeu8RcLnpzoRnEotT3r1CxB17JtHrBqlfSTOm4MQzb7efBdkcL03t343gyRmI6OTUW6iI+hShiysszISQ/IahA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<canvas id="c"></canvas>

<div>
  <p>
    <label for="brightness">Brightness</label>
    <input type="range" id="brightness" value="0" min="-1" max="1" step="0.01">
  <p>
  <p>
    <label for="saturation">Saturation</label>
    <input type="range" id="saturation" value="0" min="-1" max="1" step="0.01">
  <p>
  <p>
    <label for="contrast">Contrast</label>
    <input type="range" id="contrast" value="0" min="-1" max="1" step="0.01">
  <p>
  <p>
    <label for="hue-value">Hue</label>
    <input type="range" id="hue" value="0" min="-2" max="2" step="0.01">
  <p>
</div>


推荐阅读