1

I have a TSkLabel that is my title on my form, but I would like to draw a colorful gradient line underneath it.

I want just a simple line that goes from one color to a different color. Perhaps multiple colors. Like a rainbow gradient divider line underneath my title.

How can this be achieved with Skia?

1 Answer 1

0

Using a TSKPaintBox.OnDraw you need to use the TSkShader.MakeGradientLinear method. It takes these Parameters

AStart : TPointF;
AEnd : TPointF;
AColors : TArray<System.UlTypes.TAlphaColor>;
APositions : TArray<System.Single>;
ATileMode : TSkTileMode;

To make the AColors array:

function TForm20.MakeColorArray( const AColor : TAlphaColor ) : TArray<TAlphaColor>;
  const
    Alpha = $00;
  {var
    TempArray : TArray<TAlphaColor>;}
     
  begin
    { Add more Colors to the array here if needed. I just needed 1 color }
    Result := [ ( AColor and $00FFFFFF ) or ( Alpha shl 24 ), AColor, ( AColor and $00FFFFFF ) or ( Alpha shl 24 )];
  end;

and in the TSkPaintbox.OnDraw event:

procedure TForm20.SkPaintBox1Draw( ASender : TObject; const ACanvas : ISkCanvas; const ADest: TRectF; const AOpacity : Single );
  var
    Shader : ISkShader;
    CentreLinePaint : ISkPaint;
    HighlightLinePaint : ISkPaint;

    CentreLineColors : TArray<TAlphaColor>;
    HighlightLineColors : TArray<TAlphaColor>;
    GradientPositions : TArray<Single>;

  begin
    CentreLineColors := MakeColorArray( $FF45494C ); {This just returns a single TAlhpaColor array}
    HighlightLineColors := MakeColorArray( $FFB5C3CB );
    GradientPositions := [0.0, 0.5, 1.0]; { The stop points for the Gradient }


    CentreLinePaint := TSkPaint.Create; { Create the Shader }
    CentreLinePaint.StrokeWidth := 4;
    CentreLinePaint.AntiAlias := True;
    CentreLinePaint.Style := TSkPaintStyle.Stroke;
    CentreLinePaint.Shader := TSkShader.MakeGradientLinear(
    TPointF.Create(50, 50), TPointF.Create(150, 50), CentreLineColors, GradientPositions, TSkTileMode.Clamp );


    ACanvas.DrawLine(TPointF.Create(50, 50), TPointF.Create(150, 50), CentreLinePaint ); { Draw the line }

    HighlightLinePaint := TSkPaint.Create; { Create another shader }
    HighlightLinePaint.StrokeWidth := 1;
    HighlightLinePaint.AntiAlias := False;
    HighlightLinePaint.Style := TSkPaintStyle.Stroke;
    HighlightLinePaint.Shader := TSkShader.MakeGradientLinear(
    TPointF.Create(50, 50), TPointF.Create(150, 50),
    HighlightLineColors, GradientPositions,
    TSkTileMode.Clamp
  );

    ACanvas.DrawLine( TPointF.Create( 50, 50 - 2), TPointF.Create( 150, 50 - 2 ), HighlightLinePaint ); { Draw some more lines }
    ACanvas.DrawLine( TPointF.Create( 50, 50 + 2 ), TPointF.Create( 150, 50 + 2 ), HighlightLinePaint );

  end;

Produces this:

GradineLine

for multicolor gradients:

var
  ColorsArray : TArray<TAlphaColor>;
  StopPoints : TArray<Single>;
begin
  ColorsArray := [$FFFF0000, $FF00FF00, $FF0000FF, $FF00FFFF];
  StopPoints := [0.0, 0.33, 0.66, 1.0];
end;

Mind you, this is just hard coded to produce a horizontal line. It would be better to create a method to draw the line so you could use the start and end points of the line to set the gradient.

procedure TForm20.DrawGradientLine( const P1, P2 : TPointF;
                                ColorArray : TArray<TAlphaColor>;
                                StopPoints : TArray<Single>;
                                Paint : ISkPaint;
                                Canvas : ISkCanvas;
                                StrokeWidth : Single );

begin
  Paint.StrokeWidth := StrokeWidth;
  Paint.Style := TSkPaintStyle.Stroke;
  Paint.AntiAlias := False;
  Paint.Shader := TSkShader.MakeGradientLinear( P1, P2, ColorArray, StopPoints, TSkTileMode.Clamp );
  Canvas.DrawLine( P1, P2, Paint );
end;


var
  RainbowColors : TArray<TAlphaColor>;
  RainbowPoints : TArray<Single>;
  RainbowPaint : ISkPaint;

begin
  RainbowColors := [$FFFF0000, $FFFF7F00, $FFFFFF00, $FF00FF00, $FF0000FF, $FF4B0082, $FF9400D3];
  RainbowPoints := [0.0, 0.16, 0.32, 0.48, 0.64, 0.8, 1.0];
  RainbowPaint := TSkPaint.Create;
  DrawGradientLine( TPointF.Create( 30, 60 ), TPointF.Create( 100, 200 ), RainbowColors, RainbowPoints, RainbowPaint, ACanvas, 10 );
end;

RainbowGradient

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.