views:

140

answers:

5

Let me explain a bit more, I am trying to have a large area (full screen) with a fixed size hole in it. The hole will follow the mouse around the screen. Think of having a scope focused on the page and the rest of the page grayed out.

I need this working efficiently in all browsers (inc IE 6).

My current solution uses 4 divs (top, right, bottom, left) and forms the hole in this manner. However this requires a repaint of the whole screen and this shows artifacts (divs have background image to gray out the area).

Is there a better (more efficient) way of achieving this that anyone may have encountered?

Note: The hole has to pass all events through to the elements below these divs.

Thanks all

Guido

A: 

You may want to use the canvas tag, which can work on IE using excanvas, http://excanvas.sourceforge.net/, and you would then put the text inside the canvas tag. It can react to events as it is an html element, basically.

James Black
If 4 divs perform badly canvas (especially using excanvas) will perform horribly
gatapia
Canvas can perform well, it depends on how you approach it, as you are only redrawing a tiny area. The trick is taking advantage of either layers or a z-index.
James Black
Reading between the lines, I would guess he has a page laid out in html which he wants to put behind the hole. The normal mouseover behaviors that the browser gives you for free - such as a:hover and changing the cursor icon etc, as well as clicking on links etc, I believe are what he is after. The canvas approach will not give you these things, unless you want to rebuild all the web elements from scratch in canvas.
toby
Correct toby. Thanks for clarifying
gatapia
+5  A: 

I would suggest a single div with which is partially opaque. Have it have transparent background, but black borders. As the mouse moves around, adjust the thickness of the borders. Because it's partially opaque (say 50%), the part covered by the borders will seem grayed out. Remember, borders can be as thick as you want - even hundreds of pixels. This way you don't need to use images, or modify the DOM at all - just change the style properties of the single div.

EDIT: Just noticed the requirement to let mouse events through. I believe the single div solution fails here. A four-div solution would need to be used. However, this can still be done by using black, semi-opaque divs (instead of background images). They can then be resized (via dynamically changing the style object) rather than removed and recreated (not sure if this is what OP means by "re-painting").

levik
+1 for the creativity =)
David Thomas
This does not satisfy the requirement that events must be let through the "hole".
toby
That was a great idea, shame about the events but I really like the 'outside the box thinking'. The problem with semi-opaque divs is that it gives a solid color. I'm looking for a blur effect which I can achieve with a 4px image with a mixture of opaque and semi opaque pixels. Semi-opaque also performs poorly in IE due to having to use filters.
gatapia
A: 

Unfortunately, the DOM's design doesn't allow events to "pass through" a block to anything below it. This is why toolkits which allow drag 'n drop (mootools, jquery, etc...) are so complicated. They pre-calculate the location of all "droppable" elements and do mass comparison of coordinates of the dragged object v.s. the droppable objects, tied to the onmousemove events. That's one way around the limitation you could explore. Figure out what elements you want to react to your "window" and do the coordinate comparisons, etc...

I've seen partial solutions that involve offsetting the dragged element from the mouse pointer, so that the pointer's "clear" and can properly trigger events, but that would most likely ruin the window effect you're going for.

Most likey you're stuck dragging around those 4 divs. Do they have to have the background image? CSS opacity not a candidate?

Marc B
Hi Mark, CSS opacity is great however this means using filters in IE and this is just too slow. Another problem with opacity is that it gives you a solid color where as with the bg image I'm getting a nice blur effect I'm looking for (having 100% opaque pixel with a 50% opaque pixel).
gatapia
+2  A: 
  1. Have one div which is twice as wide and twice as tall as the viewport.
  2. Inside that, put your four divs to create the fixed-width hole in the middle.
  3. In your javascript, make the outer div move around with the cursor, rather than resizing the four divs.
nickf
Hi Nick, I will try something like this now, using 4 oversized divs and moving them around. Will get back to you on how this performs (will mark as accepted if moving big divs performs better than resizing small ones).
gatapia
Ok, results are that moving 4 divs or 1 container div is 4x slower than just resizing 4 border style divs (original solution). Will add conclusions in another answer to wrap up post.
gatapia
A: 

Conclusions:

  • Having 4 divs and resizing them appears to be the fastest approach
  • Moving 4 divs is 4x slower
  • Moving 1 container div w/ 4 inner divs is just as slow (4x slower than resizing)
  • Using background-images is the only option that IE supports (as opacity filter (alpha) is too slow for whole page size divs).
  • background-image has to be solid (i.e. 1px solid colour with semi-opacity). Trying to get a solid color / semi-opaque color to achieve blur will cause screen repaint artifacts (even when not resizing/moving) divs.

Thanks for the ideas all.

Guido

gatapia