Thursday, November 3, 2011

Non intrusive shadow effect for translucent area

NeXXeuS asked a very interesting question. In WPF, you have DropShadowEffect which displays a shadow of a geometry/shape. But if the geometry/shape is translucent (0 < Opacity < 1),  then you can see the shadow through.

The question was posted on SO as:

Ques: I have a DropShadowEffect on a Rectangle with a fill that's slightly transparent. The problem is, the drop shadow also shows up inside the fill, which is what I don't want. Anyways to solve this? I tried this, but it doesn't work for me.

My answer:
This is very tricky. You need to customize the shadow effect for this. This solution gives the desired effect.
This is a sample Grid with yellow background. I've drawn two intersecting rectangles of 100x100 dimension on it. You may need to customize the size according to your need. One rectangle is gray rectangle (to show shadow), and the other is a red rectangle (the actual semi-transparent rectangle that you want to display). The shadow depth has been hard coded as 5 pixels here. Please customize it at:
  • RectangleGeometry Rect="5,5,100,100"
  • RectangleGeometry Rect="0,0,95,95"
So, the grid looks like:
   1:  <Grid Background="Yellow">
   2:      <!-- A rectangle for shadow -->
   3:      <Rectangle Fill="Gray" Width="100" Height="100" Opacity=".7">
   4:          <Rectangle.Clip>
   5:              <CombinedGeometry GeometryCombineMode="Exclude">
   6:                  <CombinedGeometry.Geometry1>
   7:                      <RectangleGeometry Rect="5,5,100,100"/>
   8:                  </CombinedGeometry.Geometry1>
   9:                  <CombinedGeometry.Geometry2>
  10:                      <RectangleGeometry Rect="0,0,95,95"/>
  11:                  </CombinedGeometry.Geometry2>
  12:              </CombinedGeometry>
  13:          </Rectangle.Clip>
  14:          <Rectangle.Effect>
  15:              <!-- For nice soft shadow effect -->
  16:              <BlurEffect Radius="5" />
  17:          </Rectangle.Effect>
  18:      </Rectangle>
  20:      <!-- Actual rectangle which is translucent -->
  21:      <Rectangle Fill="Red" Width="100" Height="100" Opacity=".6" >
  22:          <Rectangle.Clip>
  23:              <RectangleGeometry Rect="0,0,95,95"/>
  24:          </Rectangle.Clip>
  25:      </Rectangle>
  26:  </Grid>

Hope this is interesting to you as much as I had fun creating it! :)