Можно ли создать в canvas blur эффект на фото при mousemove?

109
31 марта 2021, 12:00

Можно ли создать на canvas библиотеке Konva.js (или на каком-то другом) blur эффект на фото при mousemove?

Читал документацию к Konva js, но ничего подходящего не нашел. Искал примеры, достойных примеров не нашел.

Вот пример с встроенным фильтром в canvas ctx.filter = 'blur(5px)';.

Answer 1

Конечно можно было бы взять библиотеку, но и вручную можно добится неплохих результатов, а заодно и познакомится поближе с обработкой изображений.

Это решение использунт прямые манипуляции с пикселями.

Применяем ко всем пикселям области, которую необходимо заблюрить, так называемое "ядро свертки" (convolution kernel) - основа основ в обработке изображений.

Вот тут подробно про это написано а так же визуализировано

Запустите сниппет заново, если картинка не показательная (они псевдослучайные), в сниппете реализовано рисование блюром, как Вы просили в комментариях...

let s = 44; // size of area to be blurred 
let kernel =[[0,0,1,0,0], 
             [0,1,2,1,0], 
             [1,2,3,2,1], 
             [0,1,2,1,0], 
             [0,0,1,0,0]]; 
 
let ctx = canvas.getContext('2d'); 
let total = kernel.flatMap(i => i).reduce((a, i) => a + Math.abs(i)),  
    ks = (kernel.length-1)/2, // half of kernel size - 1 (pixels around center) 
    s2 = s/2, // half size of area to be blurred 
    sks2 = s+ks*2; // size of area of pixels needed to be processed 
 
img.onload = e => ctx.drawImage(img, 0, 0); 
addEventListener('mousedown', e => draw = true) 
addEventListener('mouseup', e => draw = false) 
addEventListener('mousemove', e => { 
  if (!window.draw) return; 
  var input = ctx.getImageData(e.layerX-s2-ks, e.layerY-s2-ks, sks2, sks2); 
  var output = ctx.createImageData(s, s);  
  for (var x = 0; x < s; x++)  
    for (var y = 0; y < s; y++)  
      handlePixel(input, output, x, y) 
  ctx.putImageData(output, e.layerX - s2, e.layerY - s2)  
}) 
 
function handlePixel(i, o, x, y) { 
    let offset = (y * s + x) * 4; // offset in output data (4=rgba) 
    for (var kx = -ks; kx <= ks; kx++)  
        for (var ky = -ks; ky <= ks; ky++) { 
            let off = ((y+ks) * sks2 + (x+ks) + kx + ky * sks2) * 4; //offset in input 
            for (var n = 0; n < 3; n++)  
                o.data[offset + n] += kernel[kx+ks][ky+ks] * i.data[off+n] / total; 
        } 
    o.data[offset + 3] = 255; // always opaque 
}
<canvas id="canvas" width="500" height="500"></canvas> 
<img id="img" src="https://picsum.photos/500/500" crossOrigin="anonymous"> 
<style>body{margin:0}img {display:none;}</style>

PS: от бага по краям надо подумать как избавиться...

READ ALSO
Как писать тесты для строк?

Как писать тесты для строк?

У меня есть функция которая берет строку и проверяет является ли она CSS функцией hslaCSS понимает разное написание этой функции — с тремя и четырьмя...

120
Как изменить атрибут src у img при наведении

Как изменить атрибут src у img при наведении

Как изменить атрибут src у img при наведении?Eсть-ли варианты реализации на чистом css?Если нет - то и js подойдёт

120
помогите переписать 2 функции в одну [закрыт]

помогите переписать 2 функции в одну [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском

105