Recent

Author Topic: What is the best way to change TBGRASVG properties (colors, rotation, text ...)  (Read 420 times)

Luc

  • New Member
  • *
  • Posts: 34
Hi,

I am starting to use TBGRASVG and would like to find a way to change some properties of a SVG at runtime.

I could'nt find how to do this using TSVGContent.

Here is a small SVG file (a really simple one so I could directly change the values with StringReplace on this one, but this would not work with more complicated SVG).


Quote
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48">
  <g>
    <ellipse cy="24" cx="24" ry="24" rx="24" fill="#4A62C3" />
    <path id="path1" transform="rotate(0,24,24) translate(8,10.2630004882813) scale(1,1)  " fill="#FFFFFF" d="M17.415009,11.589005L25.104004,16.893005 23.071014,18.276001 25.715027,21.865005 24.007019,23.122009 21.31601,19.469009 19.366028,20.794006z M1.3740234,8.4840088C1.2410278,8.4840088,1.131012,8.5920105,1.131012,8.727005L1.131012,25.697006C1.131012,25.831009,1.2410278,25.939011,1.3740234,25.939011L30.707001,25.939011C30.841003,25.939011,30.950012,25.831009,30.950012,25.697006L30.950012,8.727005C30.950012,8.5920105,30.841003,8.4840088,30.707001,8.4840088z M1.4170227,5.7770081C1.2820129,5.7770081,1.1720276,5.8860016,1.1720276,6.0200043L1.1720276,7.2320099C1.1720276,7.3659973,1.2820129,7.473999,1.4170227,7.473999L30.745026,7.473999C30.881012,7.473999,30.991028,7.3659973,30.991028,7.2320099L30.991028,6.0200043C30.991028,5.8860016,30.881012,5.7770081,30.745026,5.7770081z M28.364014,1.576004C28.029022,1.576004,27.758026,1.8460083,27.758026,2.1820068L27.758026,3.2720032C27.758026,3.6080017,28.029022,3.8789978,28.364014,3.8789978L29.252014,3.8789978C29.588013,3.8789978,29.859009,3.6080017,29.859009,3.2720032L29.859009,2.1820068C29.859009,1.8460083,29.588013,1.576004,29.252014,1.576004z M24.485016,1.576004C24.150024,1.576004,23.879028,1.8460083,23.879028,2.1820068L23.879028,3.2720032C23.879028,3.6080017,24.150024,3.8789978,24.485016,3.8789978L25.374023,3.8789978C25.709015,3.8789978,25.981018,3.6080017,25.981018,3.2720032L25.981018,2.1820068C25.981018,1.8460083,25.709015,1.576004,25.374023,1.576004z M20.606018,1.576004C20.271027,1.576004,20,1.8460083,20,2.1820068L20,3.2720032C20,3.6080017,20.271027,3.8789978,20.606018,3.8789978L21.495026,3.8789978C21.830017,3.8789978,22.10202,3.6080017,22.10202,3.2720032L22.10202,2.1820068C22.10202,1.8460083,21.830017,1.576004,21.495026,1.576004z M1.3330078,0L30.667023,0C31.404022,0,32,0.5960083,32,1.3330078L32,26.141998C32,26.878006,31.404022,27.473999,30.667023,27.473999L1.3330078,27.473999C0.59701538,27.473999,0,26.878006,0,26.141998L0,1.3330078C0,0.5960083,0.59701538,0,1.3330078,0z" />
  </g>
</svg>

Some code examples would be appreciated  :)

Win 8.1 (Running in Parallel VM - Mac OSX) - Lazarus 1.8.2 - i386-win32/win64

lainz

  • Hero Member
  • *****
  • Posts: 3197
    • Lainz
Using XML units I suppose?

Luc

  • New Member
  • *
  • Posts: 34
Thanks Lainz,

I came up with a solution but I am not sure this is the best way to do it:

First, I changed this line in the SVG text to add an ID:
Quote
<ellipse cy="24" cx="24" ry="24" rx="24" fill="#4A62C3" />

to
Quote
<ellipse id="ellipse1" cy="24" cx="24" ry="24" rx="24" fill="#4A62C3" />

then I use the following code to change the ellipse background color:

Code: Pascal  [Select]
  1. procedure TFormResManager.Button1Click(Sender: TObject);
  2. var
  3.   aSVGText: String;
  4.   aSVGItem: TSVGElement;
  5.  
  6.   function FindElement(aSVGContent:TSVGContent; Const aName: String): TSVGElement;
  7.   var
  8.     i: Integer = 0;
  9.     aItem: TSVGElement;
  10.     //aEl: TSVGEllipse;
  11.     S: String;
  12.   begin
  13.     Result := nil;
  14.     for i := 0 to aSVGContent.ElementCount - 1 do
  15.       begin
  16.       aItem := aSVGContent.Element[i];
  17.       if aItem is TSVGGroup
  18.         then aItem := FindElement(TSVGGroup(aItem).Content, aName);
  19.       S := aItem.ID;
  20.       S := aItem.fill;
  21.       S := aItem.transform;
  22.       if SameText(aName, aItem.ID) then
  23.         begin
  24.         Result := aItem;
  25.         Break;
  26.         end;
  27.       end;
  28.   end;
  29.  
  30. begin
  31.   aSVGText := SVGImage.SVG.AsUTF8String;
  32.   if aSVGText <> '' then
  33.     begin
  34.     aSVGItem := FindElement(SVGImage.SVG.Content, 'ellipse1');
  35.     if aSVGItem <> nil then
  36.       begin
  37.       aSVGItem.fill := '#A92989';
  38.       SVGImage.RedrawBitmap;
  39.       end;
  40.     end;
  41. end;
  42.  

If someone has an easier or faster solution, he/she is very welcome  :)
« Last Edit: July 13, 2019, 10:01:12 am by Luc »
Win 8.1 (Running in Parallel VM - Mac OSX) - Lazarus 1.8.2 - i386-win32/win64

lainz

  • Hero Member
  • *****
  • Posts: 3197
    • Lainz
Nice, I think is the way to go, the same is done in css, using an id or a class... so is the propper way.

Sorry I don't know too much about that units, because that my answer was quite generic.

Luc

  • New Member
  • *
  • Posts: 34
This opens up many possibilities for lazarus users.
We now have a very flexible way to design interactive charts or UI.
Is @Circular working on a SVG manipulation library to add specific effects or animations?
Win 8.1 (Running in Parallel VM - Mac OSX) - Lazarus 1.8.2 - i386-win32/win64

lainz

  • Hero Member
  • *****
  • Posts: 3197
    • Lainz
This opens up many possibilities for lazarus users.
We now have a very flexible way to design interactive charts or UI.
Is @Circular working on a SVG manipulation library to add specific effects or animations?

I don't think so. In what he is working is always visible in the dev branch of bgrabitmap and lazpaint. Currently in a vector tool (to be included in lazpaint I think) and lazpaint new version, as always fixes to bgrabitmap.

But you can ask him if you want to do something like that, as well he receives patches to the library from people after reviewing them, if you know how or want to contribute.

And yes, we have some svg controls, an SVG viewer plus SVG Button in BGRAControls. But again, maybe you find a way to improve them we're adding user contributions as well, for example the SVG button was contributed by user Josh in the forum, based on the SVG viewer I started and circular improved and finished with his great knowlege.

circular

  • Hero Member
  • *****
  • Posts: 2954
    • Personal webpage
Hi

I've added TBGRASVG.FindElementById function on the dev branch.

AsUTF8String will never be empty. If you want to check if the SVG is empty you can check SVG.Content.ElementCount <> 0

I suppose that finding an element could also be done using CSS definition or functions similar to DOM in Javascript. What would be most suitable for you?
Conscience is the debugger of the mind