2

I made a blurred banner which on mouse move became clear. For this I used 2 images, one blurred and one clear. I want to make the blur from css and use one single image but then when I put filter on this image the banner doesn't become clear on mouse move. Can anyone help me? Thanks! I tried many manners to put this filter but none works correctly.I need to use jpg or png not svg because theese are the formats that clients give me

var image = document.querySelector('.zzz img');
var imageCanvas = document.createElement('canvas');
var imageCanvasContext = imageCanvas.getContext('2d');
var lineCanvas = document.createElement('canvas');
var lineCanvasContext = lineCanvas.getContext('2d');
var pointLifetime = 9999999999999999999999999999;
var points = [];

if (image.complete) {
  start();
} else {
  image.onload = start;
}

/**
 * Attaches event listeners and starts the effect.
 */
function start() {
  document.addEventListener('mousemove', onMouseMove);
  window.addEventListener('resize', resizeCanvases);
var xxx=document.querySelector('.banner');
  xxx.appendChild(imageCanvas);
  resizeCanvases();
  tick();
}

/**
 * Records the user's cursor position.
 *
 * @param {!MouseEvent} event
 */
function onMouseMove(event) {

var rect = document.querySelector('.banner').getBoundingClientRect();

  points.push({
    time: Date.now(),
    x: event.clientX-rect.left,
    y: event.clientY-rect.top
  });
}

/**
 * Resizes both canvases to fill the window.
 */
function resizeCanvases() {
  imageCanvas.width = lineCanvas.width = 300;
  imageCanvas.height = lineCanvas.height = 250;
}

/**
 * The main loop, called at ~60hz.
 */
function tick() {
  // Remove old points
  points = points.filter(function(point) {
    var age = Date.now() - point.time;
    return age < pointLifetime;
  });

  drawLineCanvas();
  drawImageCanvas();
  requestAnimationFrame(tick);
}

/**
 * Draws a line using the recorded cursor positions.
 *
 * This line is used to mask the original image.
 */
function drawLineCanvas() {
  var minimumLineWidth = 25;
  var maximumLineWidth = 100;
  var lineWidthRange = maximumLineWidth - minimumLineWidth;
  var maximumSpeed = 50;

  lineCanvasContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
  lineCanvasContext.lineCap = 'round';
  lineCanvasContext.shadowBlur = 30;
  lineCanvasContext.shadowColor = '#000';
  
  for (var i = 1; i < points.length; i++) {
    var point = points[i];
    var previousPoint = points[i - 1];

    // Change line width based on speed
    var distance = getDistanceBetween(point, previousPoint);
    var speed = Math.max(0, Math.min(maximumSpeed, distance));
    var percentageLineWidth = (maximumSpeed - speed) / maximumSpeed;
    lineCanvasContext.lineWidth = minimumLineWidth + percentageLineWidth * lineWidthRange;

    // Fade points as they age
    var age = Date.now() - point.time;
    var opacity = (pointLifetime - age) / pointLifetime;
    lineCanvasContext.strokeStyle = 'rgba(0, 0, 0, ' + opacity + ')';
    
    lineCanvasContext.beginPath();
    lineCanvasContext.moveTo(previousPoint.x, previousPoint.y);
    lineCanvasContext.lineTo(point.x, point.y);
    lineCanvasContext.stroke();
  }
}

/**
 * @param {{x: number, y: number}} a
 * @param {{x: number, y: number}} b
 * @return {number} The distance between points a and b
 */
function getDistanceBetween(a, b) {
  return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

/**
 * Draws the original image, masked by the line drawn in drawLineToCanvas.
 */
function drawImageCanvas() {
  // Emulate background-size: cover
  var width = 300;
  var height = 250;
  
  if (height < imageCanvas.height) {
    width = imageCanvas.height / image.naturalHeight * image.naturalWidth;
    height = imageCanvas.height;
  }

  imageCanvasContext.clearRect(0, 0, imageCanvas.width, imageCanvas.height);
  imageCanvasContext.globalCompositeOperation = 'source-over';
  imageCanvasContext.drawImage(image, 0, 0, width, height);
  imageCanvasContext.globalCompositeOperation = 'destination-in';
  imageCanvasContext.drawImage(lineCanvas, 0, 0);
}
.zzz img {
  display: none;
}

.blur img{
  filter:blur(5px);
}
.zzz{
  position: absolute;
  z-index:200;

}
.banner{
  width: 300px;
  height: 250px;
  overflow: hidden;
  position: relative;
  margin:0 auto 0;
  background-image: url('http://www.dbdesign.ro/blur/a_blur.png');
/*  filter: blur(5px);
  -webkit-filter: blur(5px);*/
   /* background-image: filter(url(a.png), blur(20px));*/
/*     filter: blur(5px);
  -webkit-filter: blur(5px);*/
}
canvas{
  position: absolute;
  z-index:999;
}
<div class="banner" style="">
  

<div class="zzz"><img src="http://www.dbdesign.ro/blur/a.png"></div>

</div>

1 Answers1

1

A simple way still using the canvas API, is to use a CanvasPattern from your original image, and only fill where your mouse passed.

Now, you can position your canvas over your CSS filtered <img> and it will cover it with the clear image:

img.onload = function() {
  canvas.width = this.width;
  canvas.height = this.height;
  var rad = 30;
  var ctx = canvas.getContext('2d');
  ctx.fillStyle = ctx.createPattern(img, 'no-repeat');
  canvas.onmousemove = handlemousemove;
  function handlemousemove(evt) {
    var x = evt.pageX - canvas.offsetLeft;
    var y = evt.pageY - canvas.offsetTop;
    draw(x, y);
  }
  function draw(x, y) {
    ctx.beginPath();
    ctx.moveTo(x + rad, y);
    ctx.arc(x, y, rad, 0, Math.PI*2);
    ctx.fill();
  }
};
#banner{
  position: relative;
}
#banner img{
  filter: blur(5px);
}
#banner canvas{
  position: absolute;
  left: 0;
  top: 0;
}
<div id="banner">
<img id="img" src="https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg">
<canvas id="canvas"></canvas>
</div>
Kaiido
  • 123,334
  • 13
  • 219
  • 285