views:

126

answers:

2

I am trying to create a "porthole" using CSS. When I say porthole, what I mean is to make a portion of the screen see through so you can see whatever is behind the porthole and thats it.

I was able to get the effect I wanted by setting the background color of the body to the same as the foreground color, then using a porthole image which had a circular gradient with white in the middle and black on the edges as long as all the content on the page was all the same color. This is not exactly what I want, because I would like to use color or anything behind the screen.

I came up with this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
<html>
<head>
    <title>Test See Through Mouse</title>
    <script type="text/javascript" src="jquery-1.4.1.js"></script>
    <style type="text/css">
        * { margin: 0; padding: 0; }
        html, body { height: 100%; background-color: green; }
        #cover { height: 100%; width: 100%; top: 0; position: fixed; background: url(porthole.png) no-repeat; }
    </style>
</head>
<body>
    Hi, I am behind the scenes content.  Hi, I am behind the scenes content.  Hi, I am behind the scenes content.
    <!-- repeated enough times to fill the screen with text -->

    <div id="cover"></div>
    <script type="text/javascript">
        $('#cover').live('mousemove', function(e) {
            <!-- the image is 3000px by 3000px and I want the center of the visible part where the mouse is -->
            $('#cover').css('background-position', (e.pageX - 1500) + 'px ' + (e.pageY - 1500) + 'px');
        });
    </script>
</body>
</html>

where the porthole image is a huge PNG image (multiple times the size of my screen in each direction) with an small circle (about 200px by 200px) of invisibility in the middle. This does give the effect I want, but the main problem is I don't know the screen size of the user, but I also don't want to use an image that is too large for the user because moving it around gets noticeably choppier as the image size grows.

Is there a way to make it so that I only need to provide a porthole image that is the size of the actual porthole graphic instead, using some other method to cloak out the rest of the screen? I am willing to use HTML (5 is ok), CSS and javascript only.

+3  A: 

Why not use a porthole image that is 250x250, and then surround it by divs of the same color? They could all be children of a parent div which moves.

This way, your image does not have to be huge and you can adjust to any screen size automatically. The parent div would be of width/height 200%, or if you want to get fancy, you could simply have the height/width be 100%, and use some fancy math in JS to dynamically size the divs as the port moves.

================
|     div      |
================
|div| port |div|
================
|     div      |
================
Jeff B
lol great minds thing alike... you beat me to it by about 20 seconds...
KP
Sounds like the best idea. CSS doesn’t yet do “punch-through” transparency.
Paul D. Waite
Even better would be support for openGL type blending modes. Then you could simply apply it with (ZERO, 1-SRC) blending.
Jeff B
This worked. At first I tried to do this by keeping the top and bottom divs fixed in place and just adjusting their heights, but it caused cracks across the screen when moving the mouse. Putting everything inside of 1 big div prevented that and shrunk the math a bit. Thanks a ton.
NickLarsen
A: 

If you create a number of <div> panels and position them in such as way that you have 3 rows.

First row has a div that is full width, Second row has a div, image, div pattern. Third row has a single div full width again. Conceptually:

<--------<div>--------->

<div> hole image <div>

<--------<div>--------->

Style the divs to be opaque and match the color of the porthole image.

KP
"You'll have to script the calculations of the CSS for the divs", no he won't! He could simply do: "position-top:50%;" "top: -125px" (where 125px is 50% of the middle "porthole" height"), then repeat this all the way around (same for the bottom, left: "left:50%; left:-125px;" + right).code would need adapting, but that's the theory behind it.
citricsquid
good point :) Revised to remove scripting recommendation..
KP