Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: Luc on July 12, 2019, 06:30:06 pm

Title: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: Luc on July 12, 2019, 06:30:06 pm
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  :)

Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: lainz on July 12, 2019, 09:06:21 pm
Using XML units I suppose?
Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: Luc on July 13, 2019, 09:59:09 am
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  :)
Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: lainz on July 13, 2019, 05:25:51 pm
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.
Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: Luc on July 13, 2019, 06:34:23 pm
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?
Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: lainz on July 13, 2019, 10:41:18 pm
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.
Title: Re: What is the best way to change TBGRASVG properties (colors, rotation, text ...)
Post by: circular on July 17, 2019, 10:20:06 pm
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?
TinyPortal © 2005-2018