2

I would love to code simple image painting in HTML, CSS and probably jQuery also.

Let's say I have a original image, and I want make it colorized but only in part of hover (or 10x10px square or circle of image where cursor is).

I applied some filters to make it grayscale with CSS, but I have no idea how to colorize only hover part (not whole picture).

Example image of best result (keeping colorized advice would be great, but not necessarily).

enter image description here

3
  • 2
    Please include the code you have tried keep it simple to reproduce the issue. Commented Jan 9, 2015 at 16:03
  • Stackexchange isn't really the best place to brainstorm ideas like this. It's more for troubleshooting what you've already attempted. Some issues I can identify for you: targeting where the cursor is, (.mousemove()) creating a mask for the colorized photo (background-clip), etc. Commented Jan 9, 2015 at 16:10
  • 9
    You could possibly use this - but alter it to fit your needs jsfiddle.net/4WP2C/19 Commented Jan 9, 2015 at 16:10

4 Answers 4

6

You could do this using svg's mask and filter.

CodePen

var img = document.getElementById('img');
img.addEventListener('mousemove', function(e) {
  document.getElementById('c').setAttribute('cx', e.clientX - img.getBoundingClientRect().left);
  document.getElementById('c').setAttribute('cy', e.clientY - img.getBoundingClientRect().top);
})
<svg id="img" width="600" height="300" viewBox="0 0 600 300">
  <defs>
    <filter id="f" filterUnits="userSpaceOnUse">
      <feColorMatrix type="saturate" values="0" />
    </filter>
    <mask id="m" maskUnits="userSpaceOnUse" x="0" y="0" width="600" height="300">
      <circle id="c" cx="-40" cy="-40" r="40" fill="white" />
    </mask>
  </defs>
  <image filter="url(#f)" width="600" height="300" xlink:href="http://www.lorempixel.com/600/300" />
  <image mask="url(#m)" width="600" height="300" xlink:href="http://www.lorempixel.com/600/300" />
</svg>


You could also get a smooth transition on the circle edges by using radialGradient.

CodePen

enter image description here

var img = document.getElementById('img');
img.addEventListener('mousemove', function(e) {
  var x = e.clientX - img.getBoundingClientRect().left;
  var y = e.clientY - img.getBoundingClientRect().top;
  document.getElementById('r').setAttribute('fx', x);
  document.getElementById('r').setAttribute('fy', y);
  document.getElementById('r').setAttribute('cx', x);
  document.getElementById('r').setAttribute('cy', y);
});
<svg id="img" width="600" height="300" viewBox="0 0 600 300">
  <defs>
    <radialGradient id="r" gradientUnits="userSpaceOnUse" cx="300" cy="150" r="400" fx="300" fy="150">
      <stop offset="0%" stop-color="white" />
      <stop offset="10%" stop-color="white" />
      <stop offset="12%" stop-color="black" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
    <filter id="f" filterUnits="userSpaceOnUse">
      <feColorMatrix type="saturate" values="0" />
    </filter>
    <mask id="m" maskUnits="userSpaceOnUse" x="0" y="0" width="600" height="300">
      <path d="M0,0 h600 v300 h-600z" fill="url(#r)" />
    </mask>
  </defs>
  <image filter="url(#f)" width="600" height="300" xlink:href="http://www.lorempixel.com/600/300" />
  <image mask="url(#m)" width="600" height="300" xlink:href="http://www.lorempixel.com/600/300" />
</svg>

Sign up to request clarification or add additional context in comments.

Comments

2

I suggest avoiding CSS filters, as it is not supported in IE at all, and doesn't look like it is in the pipeline either.

I also would prefer to greyscale my images in photoshop, to have more control over the color balance and contrast. (But I'm a designer as well).

Instead, I'm going to layer a full color image over a grayscale image, fix the position of the colorful background image, and move the position of the top div with jQuery:

HTML

<div class="greykitty">
  <div class="colorfulkitty" style="top: 150px; left: 280px;">
  </div>
</div>

SCSS with normalize.css

body{
  background-color:whitesmoke;
}

div{
  height: 400px;
  width: 600px;
  background-repeat: no-repeat;
}


.greykitty{
  background-image: url("http://lorempixel.com/g/600/400/cats/10/");
}

.colorfulkitty{
    background-image: url("http://lorempixel.com/600/400/cats/10/");
  $circlesize: 150px;
  height:  $circlesize;
  width:  $circlesize;
  border-radius:   $circlesize;
  background-attachment: fixed;
  position: absolute;

}

JS with jQuery

$('.greykitty').mousemove(function (colorize) {
    var X = colorize.clientX;
    var Y = colorize.clientY;
    $('.colorfulkitty').css("top", (Y - 75) + 'px');
    $('.colorfulkitty').css("left", (X - 75) + 'px');
});

And my codepen: http://codepen.io/fontophilic/pen/XJpVje/

Comments

2

You can wrap you image in a HTML Element and add a div element element with box-shadow

$("figure").on('mousemove', function(e){
    $('.shadow').css({
       left: e.pageX - $(this).offset().left - 40,
       top: e.pageY - $(this).offset().top -40
    });
});
figure{
    position: relative;
    margin: 20px auto;
    width: 480px;
    height: 480px;
    overflow: hidden
}
figure:hover .shadow{
    opacity: 1
}
img{
    width: 100%
}

.shadow{
    position: absolute;
    left: 80px;
    top: 60px;
    z-index: 1;
    background: transparent;
    width: 100px;
    height: 100px;
    opacity: 0;
    transition: opacity .3s ease;
    border-radius: 50%;
    box-shadow: 0 0 0 60em rgba(0,0,0,.5)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<figure>
    <img src=http://i.imgur.com/orn8Dgf.jpg />
    <div  class=shadow></div>
</figure>

4 Comments

To those down voting this please comment it will help me thank you.
I'm not the one who downvoted, but I think the reason is it doesn't work right when it is Full Page.
It's a fine solution, but not exactly what was being asked. OP wants a desaturated image, not just darkened.
@fontophilic From what I read, the OP wants a gray image which should be colorized on hover. I upvoted this answer because it's not using svg so it provides additional way to do this. P.S as I upvoted the svg answer as well.
1

Base on this, i have solution for your problem:

  • Use mark to overlay image

    <div class="container">`
        <div class="bg-image"></div>
        <div class="highlight-region"></div>
    </div>
    
  • Grayscale on mark instead of image's container

     .container .bg-image { 
           opacity:0.3;
        -moz-filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
             -o-filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
             -webkit-filter: grayscale(100%);
             filter: gray;
             filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
        height:455px;
        width:606px;
    }
    
  • set opacity = 0 on highlight-region

    .container div.highlight-region {
        height:150px; 
        width:150px;
        border-radius: 50%;
        opacity:0;
    }
    

Demo can see here: http://jsfiddle.net/MT4T7/438/

1 Comment

It looks like bug come from backgroundPositionX not supported on firefox, i fixed it, view at jsfiddle.net/MT4T7/438.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.