SVG: make an element's property dependent on a property of another element - variables

I have a simple SVG tree where I want the x property of rect2 to be dependent (referencing) on the width of rect1:
<rect id="rect1" style="fill:black" x="35" y="0" width="30" height="40" />
<rect id="rect2" style="fill:black" x="**rect1.width**" y="40" width="26" height="10" />
Is something like that possible in SVG, I couldn't find it in yahoogle or the SVG reference.
Another approach would be variables
**var widthOfRect1 = 30**
<rect id="rect1" style="fill:black" x="35" y="0" width="widthOfRect1" height="40" />
<rect id="rect2" style="fill:black" x="widthOfRect1" y="40" width="26" height="10" />
Is there a way to do that? I know you can pass in parameters, but that's not exactly what I'm looking for.
Ideas?

There is an option of doing this with the mutation events.
Created fiddle http://jsfiddle.net/Afhmn/
As the width of the rect1 increases the x of the rect2 is changed inside the DOMAttrModified handler.

Related

SVG -> TCPDF gradient mismatch

I have the following SVG:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="150" viewBox="0 0 800 150" xml:space="preserve">
<linearGradient id="SVGID_0" gradientUnits="userSpaceOnUse" x1="-400" y1="-150" x2="-400" y2="0">
<stop offset="0%" style="stop-color:rgb(255,64,64);stop-opacity: 1"/>
<stop offset="100%" style="stop-color:rgb(230,57,155);stop-opacity: 1"/>
</linearGradient>
<rect x="-400" y="-75" rx="0" ry="0" width="800" height="150" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: url(#SVGID_0); fill-rule: nonzero; opacity: 1;" transform="translate(400.5 75.5)"/>
</svg>
I am converting this to PDF using TCPDF:
$pdf->ImageSVG($file='images/testsvg.svg', $x=0, $y=0, $w='', $h='', $align='', $palign='', $border=0, $fitonpage=true);
As you can see from the image below, the gradient is applied wrongly.
Based on the illustrator image, it seems like TCPDF applies the center of the gradient to the bottom edge. If I manually move the center to the top edge then it looks very close to the original.
Any idea how I can fix this?
I think it's because of how the rect is positioned. It actually starts outside the viewbox and then both the gradient and the box get transformed. For example the box and the gradient x parameter are both -400. This is overly complex and I think some of the parameters are getting cancelled out by the $fitonpage=true parameter or the translations are being applied differently:
<rect x="-400" y="-75" rx="0" ry="0" width="800" height="150" style="... transform="translate(400.5 75.5)"/>
Based on the supplied examples there isn't really any point to this trickery. The only purpose appears to be modifying the gradient start and end colors. I would just move the rect to start at 0,0, remove the transforms, and then modify the gradient colors and stops to achieve the same effect the correct way:
<linearGradient y2="150" x2="0" y1="0" x1="0" gradientUnits="userSpaceOnUse" id="SVGID_0">
<stop
style="stop-color:#f13c73;stop-opacity:1"
id="stop4139"
offset="0" />
<stop
style="stop-color:#e6399b;stop-opacity:1"
id="stop4141"
offset="0.40" />
</linearGradient>
<rect
id="rect4143"
style="opacity:1;fill:url(#SVGID_0);fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none"
height="150"
width="800"
ry="0"
rx="0"
y="0"
x="0" />
The changes that matter are the removal of all the strange negative offsets on the rect and gradient and the change of the gradient stop colors and position to recreate the same gradient without the need to use cropping and transforms.

Show different images based on property value

I would like to do the following:
<Image X="0" Y="0" Width="20" Height="20" ImageFile="[Status].bmp" />
where Status is a variable. Currently this does not work, since contents of ImageFile attribute don't seem to be expanded.
I implemented a custom bafunctions.dll, but couldn't find how to get to controls via IBootstrapperEngine.
Any suggestions?
In WiX v4, you would do it like this:
<ImageControl X="0" Y="0" Width="20" Height="20" ImageFile="Status1.bmp"
VisibleCondition="Status = Status1" />
<ImageControl X="0" Y="0" Width="20" Height="20" ImageFile="Status2.bmp"
VisibleCondition="Status = Status2" />
Although, the page would not refresh automatically. You might have to use
ThemeShowPageEx(pTheme, pTheme->dwCurrentPageId, SW_SHOW, THEME_SHOW_PAGE_REASON_REFRESH);
In WiX v3, there's no supported way to do this. The bafunctions.dll would need access to the THEME but WixStdBA doesn't provide that in v3. I guess you could theoretically get the top level window and enumerate all the child controls until you find the right control to show or hide, and set them initially to not visible.
<Image X="0" Y="0" Width="20" Height="20" ImageFile="Status1.bmp" Visible="no />
<Image X="0" Y="0" Width="20" Height="20" ImageFile="Status2.bmp" Visible="no />

How to use an external image as pattern in svg-edit?

I'm a new to svg-edit, and I have a problem with using external link as pattern image.
Svg-edit delete the part
xlink:href="http://www.micromark.com/RS/SR/Product/85373_T.jpg"
when I apply modifications in the source :
<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:undefined="http:/www.w3.org/1999/xlink">
<defs>
<pattern x="0" y="0" width="100" patternUnits="userSpaceOnUse" id="testGilles" height="100" xmlns:xlink="http:/www.w3.org/1999/xlink">
<image id="svg_3" width="100" height="100" xlink:href="http://www.micromark.com/RS/SR/Product/85373_T.jpg"/>
</pattern>
</defs>
<g>
<title>Layer 1</title>
<rect id="svg_1" height="225" width="238" y="87" x="82" stroke-width="5" stroke="#000000" fill="url(#testGilles)"/>
</g>
</svg>
Does anyone knows why ?
I hope this is clear, it's not easy for me to explain it in English :)

Converting polygon to path

On a Windows app store project i have these polygons
<Polygon x:Name="AcItemTriangle" Stroke="#aa6861" Fill="#aa6861" Visibility="Collapsed" Points="0,0 28,0 14,35" />
and
<Polygon x:Name="AcItemTriangle" Points="0,0 28,0 14,35" Stroke="#67a0bb" Fill="#67a0bb" Visibility="Collapsed" />
I would like to know if there is a way i can convert my polygon points to a Path
This should work:
<Path Data="M0,0 L28,0 14,35Z" Stroke="#aa6861" Fill="#aa6861" ... />

How to create WPF UserControl having a Canvas as the "main panel"?

I want to create a UserControl having a Canvas inside it. Then I can use it like this in XAML:
<Window ...>
<Grid>
<local:MyCanvasLikeControl>
<Path .../>
<Path .../>
<Polygon.../>
</local:MyCanvasLikeControl>
</Grid>
</Window>
I have tried some things, but always get this error: "Property Content can only be set once". I know of ControlTemplates and such, but could not find my way by reading the docs by myself.
My goal is to have an equivalent to this:
<Window ...>
<Grid ...>
<Border ....>
<Canvas ...>
<Path ...>
<Path ...>
<Polygon ...>
</Canvas>
</Border>
</Grid>
</Window>
But moving the "Border / Canvas" to a UserControl named "MyCanvasLikeControl"
It's the same type of scenario as if you to stuff a bunch of elements of any other type into a control that would produce the same error like for example;
<UserControl>
<Grid/>
<StackPanel/>
<Canvas/>
<!-- you get the idea -->
</UserControl>
It's just telling you that you need to specify a parent capable of holding your content to act as the single content of its parent, which in this case would be your control. So to fix this, it's luckily simple;
<local:MyCanvasLikeControl>
<Grid>
<Path .../>
<Path .../>
<Polygon.../>
</Grid>
</local:MyCanvasLikeControl>
Or switch Grid with Canvas or whatever you want so long as it can host children elements. Hope this helps.
EDIT:
Ok, so I think the definition of requirement may have been a bit over-complicated in its explanation. If I'm understanding you correctly then here's why you're breaking.
You have your first layer of elements that contain your UserControl, but the way you're trying to insert content into it isn't the way that works, you'll need to provide that ability by specifying how you wish to allow it to be added to your control via a ContentPresenter or ContentControl etc. So instead it would be more like this inside your external UserControl;
<Border ....>
<Canvas ...>
<ContentPresenter/> or <ContentControl/> etc.
</Canvas>
</Border>
So then you can inject that stuff in there the way you want.
<Window ...>
<Grid>
<local:MyCanvasLikeControl>
<local:MyCanvasLikeControl.Content>
<Path .../>
<Path .../>
<Polygon.../>
</local:MyCanvasLikeControl.Content>
</local:MyCanvasLikeControl>
</Grid>
</Window>
Make sense?