10

I have this div which acts a lens in zooming of the image. But the problem is that I want it circular. I am using this for that:

-webkit-border-radius:999px;-moz-border-radius:999px;border-radius:999px;

The problem is that it makes the div circular but does not hide the image corners which are not part of the circle and hence shows a rectangle.

The URL is: http://chokate.maninactionscript.com/chokates/

Click on the desert picture and then see the bigger image on the right for zoom effect. If you give the lens div border 1px solid red then you can see that the div is actually circular but it doesn't hide the useless part of images.

Any ideas?

Anish Gupta
  • 2,218
  • 2
  • 23
  • 37
techie_28
  • 2,123
  • 4
  • 41
  • 62
  • have you set the `overflow` property of the div to `hidden`? – Brian Driscoll Jan 06 '12 at 19:56
  • @BrianDriscoll, `overflow: hidden` does not work for rounded corners in absolutely positioned elements in chrome (or other webkit browsers). – Ben Lee Jan 06 '12 at 19:57
  • 1
    @techie_28, here's someone that had the same problem as you. They didn't answer it, but they worked around it: http://stackoverflow.com/questions/5736503/how-to-make-css3-rounded-corners-hide-overflow-in-chrome-opera – Ben Lee Jan 06 '12 at 19:58
  • 2
    off topic but i believe you can use a radius of 50% to make a circle [demo](http://jsfiddle.net/H6Rn3/) – T I Jan 06 '12 at 19:58
  • works fine for me. Chrome 16 –  Jan 06 '12 at 20:03
  • It would be helpful if you put a code sample in JSFiddle with the js lens switched off so that we can play with just the css. – gotofritz Jan 06 '12 at 20:18
  • @TomIngram That. Is. Awesome. I've been calculating 50% in pixels forever. – ThinkingStiff Jan 12 '12 at 03:53
  • it works in chrome but doesnt hides the corners of the lens – techie_28 Jan 12 '12 at 05:27

5 Answers5

6

If you have an image inside an element that has border-radius set, and you want to hide the "corners" of the image, you need to set border-radius on the image to match.

But in your case that won't work because your image is much larger than your containing element. Better is to use a <div> as the lens and set background-image to match your image.

Demo: http://jsfiddle.net/ThinkingStiff/wQyLJ/

HTML:

<div id="image-frame">
<img id="image" src="http://thinkingstiff.com/images/matt.jpg" />
<div id="lens" ></div>
<div>

CSS:

#image-frame {
    position: relative;
}

#lens {
    background-repeat: no-repeat;
    border-radius: 150px;
    height: 150px;
    position: absolute;
    width: 150px;
}

Script:

document.getElementById( 'image-frame' ).addEventListener( 'mousemove', function ( event ) {

    var lens = document.getElementById( 'lens' ),
        image = document.getElementById( 'image' ),
        radius = lens.clientWidth / 2,
        imageTop = this.documentOffsetTop,
        imageLeft = this.documentOffsetLeft,
        zoom = 4,
        lensX = ( event.pageX - radius - imageLeft ) + 'px',
        lensY = ( event.pageY - radius - imageTop ) + 'px',
        zoomWidth = ( image.clientWidth * zoom ) + 'px',
        zoomHeight = ( image.clientHeight * zoom ) + 'px',
        zoomX = -( ( ( event.pageX - imageLeft ) * zoom ) - radius ) + 'px',
        zoomY = -( ( ( event.pageY - imageTop ) * zoom ) - radius ) + 'px';

    if( event.pageX > imageLeft + image.clientWidth 
        || event.pageX < imageLeft
        || event.pageY > imageTop + image.clientHeight 
        || event.pageY < imageTop  ) {

        lens.style.display = 'none';

    } else {

        lens.style.left = lensX;
        lens.style.top = lensY;
        lens.style.backgroundImage = 'url(' + image.src + ')';
        lens.style.backgroundSize = zoomWidth + ' ' + zoomHeight;
        lens.style.backgroundPosition = zoomX + ' ' + zoomY;
        lens.style.display = 'block';

    };

}, false );

window.Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

window.Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

Output:

enter image description here

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
  • This is a neat demo, but it only seems to work in Chrome. Was that the intention? It doesn't work properly for me in Firefox 9.0.1... – Jonah Bishop Jan 12 '12 at 03:06
  • @JonahBishop Ooops: `event.x`. It's fixed now. – ThinkingStiff Jan 12 '12 at 03:12
  • Awesome demo. There's some wonky-ness at the right and bottom edges of the image, but this is a slick little demo. Nice job! – Jonah Bishop Jan 12 '12 at 03:15
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/6752/discussion-between-thinkingstiff-and-techie-28) – ThinkingStiff Jan 16 '12 at 06:59
  • @techie_28 I think I solved it! I updated the demo link (if it works I'll update my answer). It's calculating the top/left differently. Be sure to add the two new functions at the bottom. – ThinkingStiff Jan 17 '12 at 18:10
  • @ThinkingStiff yes it works fine thanks.You did a great favor to me.Now please do another one and explain the code to me so that i dont have to ask ne one again. – techie_28 Jan 22 '12 at 23:10
  • @techie_28 It's blowing up the image four times its size and making it the background of the lens. It has to move the background over, so it lines up with where you are on the image. P.S. Let's clean up all these comments since we weren't in chat. I deleted a bunch of mine. – ThinkingStiff Jan 22 '12 at 23:31
  • @ThinkingStiff i need an explanation like how are you doing it there.what does a specific line indicates in the code what are pageX and pageY what is clientWidth and clientHeight?Please do it if that is easy for you.Thank you. – techie_28 Jan 23 '12 at 04:56
  • @techie_28 Here is an explanation of the Event object: http://www.w3schools.com/jsref/dom_obj_event.asp – ThinkingStiff Jan 23 '12 at 05:25
2

Instead of having an image in that lens div, try applying it as a background-image on the container. Background images seem to be friendlier with Chrome border-radii than img tags.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
1

OK, to redeem myself, I think that this can be fixed in chrome by nesting the image inside another div. In Chrome the rounded corners will not hide overflow if the div is absolutely position, but if you put in a non-absolutely positioned div and apply the rounded corner css to that and set overflow hidden, it should work OK:

<div style='position:absolute'>
   <div style='-webkit-border-radius:999px;-moz-border-radius:999px;border-radius:999px;overflow:hidden'>
      <img src='' />
   </div>
</div>

Something similar here: How to make CSS3 rounded corners hide overflow in Chrome/Opera

Community
  • 1
  • 1
Ben D
  • 14,321
  • 3
  • 45
  • 59
1

The border IS rendered correctly (you can see that by setting the background to red and turning off the image) - the issue is that the image punches through. I think you need to simplify your implementation. Why not just have one div, with the image as background, and no inner div nor image. From this complicated code, with all that CSS

<div style="position: absolute;
    overflow-x: hidden;
    overflow-y: hidden;
    width: 200px;
    height: 200px;
    left: 971px;
    top: 311px;
    display: none; ">
    <div style="position: relative;
             border-top-left-radius: 200px 200px;
             border-top-right-radius: 200px 200px;
             border-bottom-right-radius: 200px 200px;
             border-bottom-left-radius: 200px 200px;
             left: -934px; top: 716px; ">
          <img src="/img/rsz_desert_mid.jpg" style="width: 660px; height: 548px; ">
     </div>
 </div>

To

<div id="lens" style="background-position: -513px -12px; top: 100px; left : 100px;"></div>

with css

#lens {
    background-image : url( .... );
    background-repeat: no-repat;
    width : 200px;
    height : 200px;
    border-radius : 200px;
    -mox-border-radius : 200px;
    -webkit-border-radius : 200px;
    position : absolute;
 }

and have the JS change the background-position and top / left of the #lens element

gotofritz
  • 3,341
  • 1
  • 31
  • 47
0

You have a bug with your implementation where it shows the previous zoom.

buggy zoom http://www.vertigrated.com/images/buggyzoom.png