Here is small application that morphs between star shapes.
The VCL project looks like this: The form color is set to “black” and it contains an TSVG2Image aligned “alClient” and a TTimer.
Also, the “DoubleBuffered” property of the form is set to “True”, otherwise we’ll end up with a lot of unwanted flicker.
Then the following code in the unit:
[code language="Delphi"] unit Unit1; // ----------------------------------------------------------------------------- // // Random SVG star // // B.J.H. Verhue // // ----------------------------------------------------------------------------- interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, BVE.SVG2Image.VCL; type TForm1 = class(TForm) SVG2Image1: TSVG2Image; Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure SVG2Image1Click(Sender: TObject); private FTime: integer; function LFO(const f: single): single; function LFO2(const s, f: single): single; public function StarPath(const aEdgeCount: integer; const aRIn, aROut, aOuterEdge: single): string; procedure Update; end; var Form1: TForm1; implementation uses Vcl.Clipbrd, System.Math; {$R *.dfm} { TForm1 } function TForm1.LFO(const f: single): single; begin // Low frequency oscilator Result := Sin(2* PI * f * FTime / 1000); end; function TForm1.LFO2(const s, f: single): single; begin // Coupled LFO's to simulate randomness Result := LFO(s * LFO(f)); end; function SVGColor(const aR, aG, aB: single): string; begin Result := '#' + IntToHex(Round(255 * Abs(aR)), 2) + IntToHex(Round(255 * Abs(aG)), 2) + IntToHex(Round(255 * Abs(aB)), 2); end; function TForm1.StarPath(const aEdgeCount: integer; const aRIn, aROut, aOuterEdge: single): string; var i: integer; InnerAngle, OuterAngle, X, Y: single; begin // Create starshaped pathdata // aEdgeCount : number of edges or points // aRIn : radius of star core // aROuter : outer radius of star // aOuterEdge : width of star point Result := ''; InnerAngle := 2 * PI / aEdgeCount; OuterAngle := arctan2(aOuterEdge, aROut); for i := 0 to aEdgeCount - 1 do begin X := aRIn * Sin(i * InnerAngle); Y := aRIn * Cos(i * InnerAngle); if i = 0 then Result := Result + Format('M%0:.2f,%1:.2f', [X, Y]) else Result := Result + Format('L%0:.2f,%1:.2f', [X, Y]); X := aROut * Sin((i + 0.5 - OuterAngle) * InnerAngle); Y := aROut * Cos((i + 0.5 - OuterAngle) * InnerAngle); Result := Result + Format('L%0:.2f,%1:.2f', [X, Y]); X := aROut * Sin((i + 0.5 + OuterAngle) * InnerAngle); Y := aROut * Cos((i + 0.5 + OuterAngle) * InnerAngle); Result := Result + Format('L%0:.2f,%1:.2f', [X, Y]); end; Result := Result + 'Z"/>'; end; procedure TForm1.SVG2Image1Click(Sender: TObject); begin Timer1.Enabled := not Timer1.Enabled; // Put SVG on clipboard if paused if not Timer1.Enabled then Clipboard.AsText := SVG2Image1.SVG.Text; end; procedure TForm1.Timer1Timer(Sender: TObject); begin // Timer interval is set to 25ms, FPS=40 Update; Inc(FTime, Timer1.Interval); end; procedure TForm1.Update; begin // Create SVG content and assign to SVG2Image SVG2Image1.SVG.Text := '<svg version="1.1" id="star"' + ' viewBox="-100 -100 200 200"' + ' xmlns="http://www.w3.org/2000/svg">' // Defs section with a random radial gradient + ' <defs>' + ' <radialGradient id="radGrad1">' + ' <stop offset="0%" stop-color="' + SVGColor(LFO2(0.01, 0.02), LFO2(0.015, 0.03), LFO2(0.008, 0.015)) + '" />' + ' <stop offset="100%" stop-color="' + SVGColor(LFO2(0.02, 0.01), LFO2(0.025, 0.015), LFO2(0.03, 0.008)) + '" />' + ' </radialGradient>' + '</defs>' // Path element with random starshape + '<path stroke="pink" fill="url(#radGrad1)" stroke-width="3" d="' + StarPath( Round(19 + 16 * LFO2(0.01, 0.01)), 50 + 30 * LFO2(0.03, 0.005), 80 + 10 * LFO2(0.008, 0.01), 16 + 16 * LFO2(0.01, 0.002)) + '"/>' + '</svg>'; SVG2Image1.Repaint; end; initialization // Set decimal seperator for "Format" function FormatSettings.DecimalSeparator := '.'; end. [/code]
Sources can be found on github. To compile the examples, you need the demo or the full version of the SVG control package.
Awesome!