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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
[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!