在 mousemove - 画布上应用灰度和棕褐色滤镜
Posted
技术标签:
【中文标题】在 mousemove - 画布上应用灰度和棕褐色滤镜【英文标题】:Apply grayscale and sepia filters on mousemove - canvas 【发布时间】:2020-04-05 14:39:09 【问题描述】:我正在尝试在鼠标移动时在画布上应用灰度和棕褐色滤镜。 我正在使用 CanvasRenderingContext2D.filter 来应用过滤器。 这是示例代码
var radgrad = this.ctx.createRadialGradient(x, y, 50 / 8, x, y, 50 / 2);
radgrad.addColorStop(0, 'rgb(0, 0, 0)');
radgrad.addColorStop(1, 'rgb(0, 0, 0, 1)');
this.ctx.filter = "grayscale(100%) blur(5px) opacity(50%)";
this.ctx.fillStyle = radgrad;
this.ctx.beginPath();
this.ctx.arc(x, y, 50, 0, Math.PI * 2);
this.ctx.fill();
问题是当我尝试应用灰度时无法实现它,但 blur(5px)
正在被应用。
在上述方法中如何应用灰度或棕褐色滤镜的任何解决方案。
Here's a sample fiddle
解决方案的任何线索都会有所帮助。谢谢
【问题讨论】:
请注意rgb(0, 0, 0, 1)
无效。
那么您想要的是您当前绘制的圆圈以该圆圈的形状绘制背景图像,但经过过滤?你希望它是累积的吗? (即如果您在同一位置两次通过光标,过滤器将应用两次)
我只需要在鼠标移动的路径上获得灰度或棕褐色。现在即使应用过滤器也是全黑的。
【参考方案1】:
我不太清楚你想要什么,所以我假设你想要一些累积的东西,因为在同一位置移动两次将应用过滤器两次。
为此,最简单的方法是从您的图像创建一个CanvasPattern。这样您就可以使用该图像作为填充样式来填充子路径,同时在这个新绘图上应用您的过滤器:
const img = new Image();
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/1024px-Sunset_2007-1.jpg";
img.onload = begin;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
const rad = 25;
function begin()
canvas.width = img.width;
canvas.height = img.height;
// first draw the original image
ctx.drawImage( img, 0, 0 );
// create a CanvasPattern from it
const patt = ctx.createPattern(img, 'no-repeat');
// set the fillStyle to this pattern
ctx.fillStyle = patt;
// and the filter
ctx.filter = "grayscale(100%) blur(5px) opacity(50%)";
// now at each mousemove
document.onmousemove = e =>
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// we just draw a new arc
ctx.beginPath();
ctx.arc( x, y, rad, 0, Math.PI * 2 );
// this will use the filtered pattern
ctx.fill();
;
<canvas id="canvas"></canvas>
如果您不希望它是累积的(如刮刮卡),那么您可以创建一个大子路径并在每一帧重绘所有内容。
const img = new Image();
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/1024px-Sunset_2007-1.jpg";
img.onload = begin;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
const rad = 25;
const points = [];
const filter = "grayscale(100%) blur(5px) opacity(50%)";
function begin()
canvas.width = img.width;
canvas.height = img.height;
const patt = ctx.createPattern(img, 'no-repeat');
ctx.fillStyle = patt;
draw();
// now at each mousemove
document.onmousemove = e =>
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// store that point
points.push( x, y );
// and redraw
draw();
;
function draw()
// remove the filter
ctx.filter = "none";
// so we can draw the background untouched
ctx.drawImage( img, 0, 0 );
// we'll now compose a big sub-path
ctx.beginPath();
points.forEach( ( x, y ) =>
ctx.moveTo( x, y );
ctx.arc( x, y, rad, 0, Math.PI * 2 )
);
// with the filter
ctx.filter = filter;
ctx.fill();
<canvas id="canvas"></canvas>
请注意,此代码假定您使用的是现代浏览器,该浏览器确实将鼠标事件限制为帧速率。如果您的目标是较旧的浏览器,您可能需要自己做。
【讨论】:
这是我需要的,createPattern 就是我需要的东西。 除此之外,您知道如何将 ColorMatrixFilter 应用于上下文吗?? 当然,context.filter 也接受url(#filter_id)
css 语法。所以你必须在你的文档中有一个 以上是关于在 mousemove - 画布上应用灰度和棕褐色滤镜的主要内容,如果未能解决你的问题,请参考以下文章
scss 灰度和棕褐色滤镜SASS mixin(支持SVG滤镜)
粒子在mousemove上跟随光标(Javascript-画布)
使用Jquery或Javascript触发mousemove事件