首页 > 解决方案 > 动态更改画布的 feColorMatrix 值

问题描述

feColorMatrix在画布 2D 渲染上下文中使用 SVG 过滤器。我希望能够动态更新矩阵的values属性,以动态更改颜色映射。但是,当我使用setAttribute更新矩阵时,它对画布的后续绘制没有影响。

下面的示例重现了该问题。该矩阵最初交换了红色和绿色通道,并且正确应用了此过滤器,以便左侧的正方形以绿色而不是红色绘制。预期的结果是,将filter的values属性改为redToBlue矩阵后,右边的方块应该是蓝色的;实际结果是,尽管更新了矩阵值,右侧的方块仍保持绿色。

let redToBlue = '0 0 1 0 0  0 1 0 0 0  1 0 0 0 0  0 0 0 1 0';

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let filter = document.getElementById('filter');

ctx.fillStyle = 'red';
ctx.filter = 'url(#filter)';
ctx.fillRect(10, 10, 80, 80);
filter.setAttribute('values', redToBlue);
ctx.fillRect(110, 10, 80, 80);
<svg>
  <filter id="filter">
    <feColorMatrix type="matrix" values="0 1 0 0 0  1 0 0 0 0  0 0 1 0 0  0 0 0 1 0" />
  </filter>
</svg>
<canvas id="canvas" width="200" height="100"></canvas>

JSFiddle 链接

我试过filter.values = ...代替setAttribute,在更新属性后重新分配ctx.filter = 'url(#filter)',并重置画布或 SVG 宽度以“强制”更新;这些都没有效果。

理想情况下,我正在寻找一种不需要创建新元素并将其添加到 DOMfilter的解决方案。feColorMatrix在实际应用中,矩阵值将被动态计算,因此不可能预先编写不同的过滤器并根据id.

标签: javascripthtml5-canvassvg-filters

解决方案


您正在定位<filter>元素以设置新值。但是你需要定位<feColorMatrix>

let redToBlue = '0 0 1 0 0  0 1 0 0 0  1 0 0 0 0  0 0 0 1 0';

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let filter = document.querySelector('#filter feColorMatrix');

ctx.fillStyle = 'red';
ctx.filter = 'url(#filter)';
ctx.fillRect(10, 10, 80, 80);
filter.setAttribute('values', redToBlue);
ctx.fillRect(110, 10, 80, 80);
<svg>
  <filter id="filter">
    <feColorMatrix type="matrix" values="0 1 0 0 0  1 0 0 0 0  0 0 1 0 0  0 0 0 1 0" />
  </filter>
</svg>
<canvas id="canvas" width="200" height="100"></canvas>


推荐阅读