RadialGradientBrush on Rounded-Corner Rectangle
Asked Answered
C

2

5

I have a Rectangle with rounded corners (but not an ellipse), something like this:

    <Rectangle Stroke="Black" StrokeThickness="2" RadiusX="50" RadiusY="100">
        <Rectangle.Fill>
            <RadialGradientBrush RadiusY="0.5">
                <GradientStop Color="Black" Offset="1" />
                <GradientStop Color="White" Offset="0.8" />
            </RadialGradientBrush>
        </Rectangle.Fill>
    </Rectangle>

I want to use a gradient fill from black to white. How can I specify this in order to make the fill keep the shape of the rounded rectangle, instead of being an ellipse?

Cleanlimbed answered 2/5, 2011 at 12:55 Comment(0)
I
6

For a rounded rectangle you can do it all in XAML using radial gradients for the corners and linear gradients for the sides.

The example uses a ViewBox so the Size doesn't need to be set both on the grid and its clip path. If you need it to resize keeping the same border radius you could bind RectangleGeometry.Rect and use a ValueConverter. The gradient and the RadiusX and RadiusY properties can be easily changed in one place.

    <Viewbox Stretch="Fill">
        <Grid Width="100" Height="100">
            <Grid.Resources>
                <Color x:Key="inside">White</Color>
                <GradientStopCollection x:Key="gradient">
                    <GradientStop Color="Black" Offset="1"/>
                    <GradientStop Color="{DynamicResource inside}" Offset="0.2"/>
                </GradientStopCollection>
            </Grid.Resources>
            <Grid.Clip>
                <RectangleGeometry RadiusX="15" RadiusY="30" Rect="0,0,100,100" x:Name="clip" />
            </Grid.Clip>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="{Binding RadiusX, ElementName=clip}" />
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="{Binding RadiusX, ElementName=clip}" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="{Binding RadiusY, ElementName=clip}"/>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="{Binding RadiusY, ElementName=clip}"/>
            </Grid.RowDefinitions>
            <Rectangle Grid.Column="1" Margin="-1,0">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0,0" MappingMode="RelativeToBoundingBox" StartPoint="0,1" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Column="2" Grid.Row="1" Margin="0,-1">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="1,0" MappingMode="RelativeToBoundingBox" StartPoint="0,0" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Column="1" Grid.Row="2" Margin="-1,0">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Row="1" Margin="0,-1">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0,0" MappingMode="RelativeToBoundingBox" StartPoint="1,0" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Column="1" Grid.Row="1" Margin="-1">
                <Rectangle.Fill>
                    <SolidColorBrush Color="{DynamicResource inside}" />
                </Rectangle.Fill>
                </Rectangle>
            <Rectangle>
                <Rectangle.Fill>
                    <RadialGradientBrush Center="1,1" RadiusX="1" RadiusY="1" GradientOrigin="1,1" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Column="2">
                <Rectangle.Fill>
                    <RadialGradientBrush Center="0,1" RadiusX="1" RadiusY="1" GradientOrigin="0,1" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Column="2" Grid.Row="2">
                <Rectangle.Fill>
                    <RadialGradientBrush Center="0,0" RadiusX="1" RadiusY="1" GradientOrigin="0,0" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Grid.Row="2">
                <Rectangle.Fill>
                    <RadialGradientBrush Center="1,0" RadiusX="1" RadiusY="1" GradientOrigin="1,0" GradientStops="{DynamicResource gradient}" />
                </Rectangle.Fill>
            </Rectangle>
        </Grid>
    </Viewbox>

If you need to a gradient to follow more complex shapes you can do it with a V3.0 PixelShader.

Innoxious answered 2/5, 2011 at 16:26 Comment(0)
L
6

Here is a simple example composing a rounded-rectangle gradient out of more primitive gradients:

<Canvas>
    <Canvas.Resources>
        <GradientStopCollection x:Key="stops">
            <GradientStop Color="White" Offset="0"/>
            <GradientStop Color="Black" Offset="1"/>
        </GradientStopCollection>
        <RadialGradientBrush x:Key="cornerBrush" GradientStops="{StaticResource stops}"/>
        <LinearGradientBrush x:Key="topBrush" StartPoint="0,1" EndPoint="0,0" GradientStops="{StaticResource stops}"/>
        <LinearGradientBrush x:Key="leftBrush" StartPoint="1,0" EndPoint="0,0" GradientStops="{StaticResource stops}"/>
        <LinearGradientBrush x:Key="rightBrush" StartPoint="0,0" EndPoint="1,0" GradientStops="{StaticResource stops}"/>
        <LinearGradientBrush x:Key="bottomBrush" StartPoint="0,0" EndPoint="0,1" GradientStops="{StaticResource stops}"/>
    </Canvas.Resources>
    <Ellipse Canvas.Left="0" Canvas.Top="0"  Width="100" Height="100" Fill="{StaticResource cornerBrush}"/>
    <Ellipse Canvas.Left="200" Canvas.Top="0"  Width="100" Height="100" Fill="{StaticResource cornerBrush}"/>
    <Ellipse Canvas.Left="0" Canvas.Top="200"  Width="100" Height="100" Fill="{StaticResource cornerBrush}"/>
    <Ellipse Canvas.Left="200" Canvas.Top="200"  Width="100" Height="100" Fill="{StaticResource cornerBrush}"/>
    <Rectangle Canvas.Left="50" Canvas.Top="0" Width="200" Height="50" Fill="{StaticResource topBrush}"/>
    <Rectangle Canvas.Left="0" Canvas.Top="50" Width="50" Height="200" Fill="{StaticResource leftBrush}"/>
    <Rectangle Canvas.Left="250" Canvas.Top="50" Width="50" Height="200" Fill="{StaticResource rightBrush}"/>
    <Rectangle Canvas.Left="50" Canvas.Top="250" Width="200" Height="50" Fill="{StaticResource bottomBrush}"/>
    <Rectangle Canvas.Left="50" Canvas.Top="50" Width="200" Height="200" Fill="White"/>
</Canvas>

which produces this effect:

rounded rectangle gradient

Logroll answered 2/5, 2011 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.