mbuchetics
mbuchetics

Reputation: 1420

Draw a line with a gradient brush (fade out from start to end point)

My task is pretty simple: draw a line from point A to point B and set different colors at point A and B, e.g. White at A and Black at B to fade out the line.

I tried doing this using a LinearGradientBrush:

var brush = new LinearGradientBrush(
                    Color.FromArgb(255, 0, 0, 0),
                    Color.FromArgb(255, 255, 0, 0), new Point(0, 0), new Point(1,1));
var pen = new Pen(brush, 10.0);

dc.DrawLine(pen, new Point (300, 300), new Point(300, 100));

But this does not produce the wanted results since the GradientBrush is mapped according to the bounding box of the object. Therefore, the results for line going from 100/100 to 200/200 and a line going the opposite direction are the same (which is not what I want).

How could I solve this using WPF? Thanks.

Edit: I need to use the low level graphics functions (such as DrawLine) for performance reasons because I draw a lot of lines.

Upvotes: 0

Views: 5735

Answers (3)

Eugene Cheverda
Eugene Cheverda

Reputation: 8940

How to use a LinearGradientBrush article with examples in both XAML and C# code.

Try this approach and please tell me is that what you need. Take attention please that this lines are drawn in opposite directions.

public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();    
      var image = new Image
                    {
                      Source = new DrawingImage(CreateDrawingVisualRectangle(new Point(300,300), new Point(300,100) ).Drawing),
                      Stretch = Stretch.None,
                    };

      var image2 = new Image
                     {
                       Margin = new Thickness(10, 0, 0, 0),
        Source = new DrawingImage(CreateDrawingVisualRectangle(new Point(300, 100), new Point(300, 300)).Drawing),
        Stretch = Stretch.None,
      };

      var stackPanel = new StackPanel() {Orientation = Orientation.Horizontal};    
      stackPanel.Children.Add(image);
      stackPanel.Children.Add(image2);

      Content = stackPanel;
    }

    // Create a DrawingVisual that contains a rectangle.
    private DrawingVisual CreateDrawingVisualRectangle(Point start, Point end)
    {
      DrawingVisual drawingVisual = new DrawingVisual();

      // Retrieve the DrawingContext in order to create new drawing content.
      DrawingContext drawingContext = drawingVisual.RenderOpen();

      // Create a rectangle and draw it in the DrawingContext.
      var gradientStopCollection = new GradientStopCollection
                                     {
                                       new GradientStop(Color.FromArgb(255, 0, 0, 0), 0.0),
                                       new GradientStop(Color.FromArgb(255, 255, 0, 0), 0.75)
                                     };

      var brush = new LinearGradientBrush(gradientStopCollection);
      var pen = new Pen(brush, 10.0);

      var vector1 = new Vector(start.X, start.Y);
      var vector2 = new Vector(end.X, end.Y);

      if (vector1.Length < vector2.Length)
      {
        brush.StartPoint = new Point(1, 1);
        brush.EndPoint = new Point(0, 0);
      }

      drawingContext.DrawLine(pen, start, end);
      drawingContext.Close();
      return drawingVisual;
    }
  }

Upvotes: 1

LawMan
LawMan

Reputation: 3625

How about using a rectangle?

 <Rectangle Height="2" Margin="10,0,10,10">
    <Rectangle.Fill>
      <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
         <GradientStop Color="White" Offset="0"/>
         <GradientStop Color="Transparent" Offset="1.0"/>
       </LinearGradientBrush>
   </Rectangle.Fill>
 </Rectangle>

Upvotes: 3

ColinE
ColinE

Reputation: 70142

The MappingMode property on the brush allows you to specify absolute coordinates for the start / end points, or coordinates relative to the shapes bounds:

http://msdn.microsoft.com/en-us/library/system.windows.media.gradientbrush.mappingmode.aspx

Upvotes: 0

Related Questions