CamanJS in SVG? - svg

I'm looking to do some client-side image manipulation using CamanJS (http://camanjs.com/guides/) or some other tool like it on an image within an <svg> element.
Sample code is like this...
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="624" height="793" id="svg_3162" style="width: 639px;">
<desc>Created with Rapha�l</desc>
<defs></defs>
<rect x="15" y="150" width="24" height="24" r="0" rx="0" ry="0" fill="#ff0000" stroke="none"></rect>
<rect x="7" y="174" width="24" height="24" r="0" rx="0" ry="0" fill="#000000" stroke="none"></rect>
MORE SVG STUFF
<image x="35" y="0" width="600" height="769" preserveAspectRatio="none" xlink:href="https://s3.amazonaws.com/path/to/image.jpg"></image>
MORE SVG STUFF
</svg>
It's getting to the <image> tag in the <svg> tag that seems to be the issue. Does anyone know if CamanJS can work with this? Or if there's something similar out there that can work in this scenario?

use foreignObject and set height, width, x, and y positions as well
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="624" height="793" id="svg_3162" style="width: 639px;">
<desc>Created with Rapha�l</desc>
<defs></defs>
<rect x="15" y="150" width="24" height="24" r="0" rx="0" ry="0" fill="#ff0000" stroke="none"></rect>
<rect x="7" y="174" width="24" height="24" r="0" rx="0" ry="0" fill="#000000" stroke="none"></rect>
MORE SVG STUFF
MORE SVG STUFF

Related

Is it possible to center align <rect>'s inside a <g> for SVG?

Is it possible to vertically center align all the rects inside a tag without having to adjust the y attributes on <rect>? (see snippet for example)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" preserveAspectRatio="none" width="100%" height="100%">
<g fill="black">
<rect x="10" y="1" width="6" height="5" />
<rect x="20" y="1" width="6" height="10" />
<rect x="30" y="1" width="6" height="20" />
<rect x="40" y="1" width="6" height="5" />
<rect x="50" y="1" width="6" height="15" />
</g>
</svg>
<h3>desired result</h3>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" preserveAspectRatio="none" width="100%" height="100%">
<g fill="black">
<rect x="10" y="8" width="6" height="5" />
<rect x="20" y="6" width="6" height="10" />
<rect x="30" y="1" width="6" height="20" />
<rect x="40" y="8" width="6" height="5" />
<rect x="50" y="4" width="6" height="15" />
</g>
</svg>
No, it's not possible to center align <rect> elements.
But it is possible to center-align <line> elements and give them a stroke-width (note the viewBox is vertically centered around 0):
<svg viewBox="0 -19 225 38" width="100%" height="100%">
<g stroke="black">
<line x1="10" x2="16" stroke-width="5" />
<line x1="20" x2="26" stroke-width="10" />
<line x1="30" x2="36" stroke-width="20" />
<line x1="40" x2="46" stroke-width="5" />
<line x1="50" x2="56" stroke-width="15" />
</g>
</svg>
You could also achieve vertically centered <rect> elements by setting a transform: translate(0, -50%) css rule.
This approach also requires a transform-box: fill-box; (or content-box) property.
All <rect>elements get a y="50%" attribute to start at the vertical center of the svg viewBox.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" width="100%" height="100%" style="border:1px solid #ccc">
<style>
rect {
transform: translate(0, -50%);
transform-origin: center;
transform-box: fill-box;
}
</style>
<g fill="black" >
<rect x="10" y="50%" width="6" height="5" />
<rect x="20" y="50%" width="6" height="10" />
<rect x="30" y="50%" width="6" height="20" />
<rect x="40" y="50%" width="6" height="5" />
<rect x="50" y="50%" width="6" height="15" />
</g>
</svg>
Browser support for transform-box is decent. (See caniuse).
However, if you need legacy browser (e.g. ie11) support, #ccprog's answer is a more robust solution.

How to include SVG within an SVG document which has JavaScript code?

Please understand this question properly before marking as duplicate.
There are many questions like this one in StackOverflow, but my question is slightly different from those.
I have a chakra.svg file, whose code is this:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="b">
<circle cx="50" cy="50" r="45" stroke-width="2" stroke="blue" fill="none"/>
<script>
<![CDATA[
for(i=0;i<24;i++)
{
var l=document.createElementNS("http://www.w3.org/2000/svg","line");
l.setAttributeNS(null,"x1","50");
l.setAttributeNS(null,"y1","50");
l.setAttributeNS(null,"x2","5");
l.setAttributeNS(null,"y2","50");
l.setAttributeNS(null,"stroke-width",2);
l.setAttributeNS(null,"stroke","blue");
l.setAttributeNS(null,"transform","rotate("+(i/24*360)+",50,50)");
document.querySelector("#b").appendChild(l);
}
]]>
</script>
</svg>
The output is rendered as expected, like this:
I have another file, India_flag.svg whose code is this:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="170" height="100">
<rect x="0" y="0" height="33" width="180" fill="#f93"/>
<rect x="0" y="33" height="34" width="180" fill="white"/>
<rect x="0" y="67" height="33" width="180" fill="green"/>
</svg>
The output of this file is also rendered as expected:
But, now the problem is, when I am trying to insert the chakra.svg file inside the India_flag.svg file using the image tag like this:
<image xlink:href="chakra.svg" x="70" y="35" height="30" width="30"/>
The output should have been that the wheel is placed at the centre of the flag, but I am getting this output:
The chakra.svg file is rendered, but the JavaScript code in that file did not run, only the circle is rendered. What am I doing wrong and how to achieve my objective?
SVG documents when loaded inside an <image> tag (or HTML <img> for that matter) are sand-boxed and won't allow the execution of scripts, nor will they be interactive (i.e no user-event).
To circumvent that, you need an other way to append you svg. The simple solution would be to copy its markup directly in the main one:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="170" height="100">
<rect x="0" y="0" height="33" width="180" fill="#f93"/>
<rect x="0" y="33" height="34" width="180" fill="white"/>
<rect x="0" y="67" height="33" width="180" fill="green"/>
<svg x="70" y="35" height="30" width="30" id="b" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="45" stroke-width="2" stroke="blue" fill="none"/>
<script>
<![CDATA[
for(i=0;i<24;i++) {
var l=document.createElementNS("http://www.w3.org/2000/svg","line");
l.setAttribute("x1","50");
l.setAttribute("y1","50");
l.setAttribute("x2","5");
l.setAttribute("y2","50");
l.setAttribute("stroke-width",2);
l.setAttribute("stroke","blue");
l.setAttribute("transform","rotate("+(i/24*360)+",50,50)");
document.querySelector("#b").appendChild(l);
}
]]>
</script>
</svg>
</svg>
An other solution, would have been to do the inverse: load your flag image from the one with the script: plnkr.

How to make vertical svg rect height start from the bottom?

Desired behaviour
Make a "bar chart" style icon with vertical bars.
Actual Behaviour
The following displays the desired result if I flip it with scaleY().
/* uncomment below for desired appearance */
/*
svg {
transform: scaleY(-1);
}
*/
<svg style="background: yellow" width="20" height="20" viewbox="0 0 20 20">
<rect x="2" y="0" width="1" height="5" style="fill:rgb(0,0,0)"/>
<rect x="7" y="0" width="1" height="8" style="fill:rgb(0,0,0)"/>
<rect x="12" y="0" width="1" height="15" style="fill:rgb(0,0,0)"/>
<rect x="17" y="0" width="1" height="10" style="fill:rgb(0,0,0)"/>
Sorry, your browser does not support inline SVG.
</svg>
Question
What is the correct way to start the height from the bottom, rather than the top?
SVG's Y axis goes from the top down to the bottom (source)[https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Positions#The_grid].
In order to display the bars from the bottom of the icon, you need to calculate each bar's y coordinate accordingly: iconHeight - barHeight.
Adapted snippet:
/* uncomment below for desired appearance */
/*
svg {
transform: scaleY(-1);
}
*/
<svg style="background: yellow" width="20" height="20" viewbox="0 0 20 20">
<rect x="2" y="15" width="1" height="5" style="fill:rgb(0,0,0)"/>
<rect x="7" y="12" width="1" height="8" style="fill:rgb(0,0,0)"/>
<rect x="12" y="5" width="1" height="15" style="fill:rgb(0,0,0)"/>
<rect x="17" y="10" width="1" height="10" style="fill:rgb(0,0,0)"/>
Sorry, your browser does not support inline SVG.
</svg>

How to create an SVG with support of more than one Pixel Ratio?

I would like to create resolution independent SVG that uses <image> element. Is it possible to test for actual pixel ratio of the user agent? Please look at the example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="480">
<defs>
<pattern id="test" patternUnits="userSpaceOnUse"
x="0" y="0" width="130" height="100"
viewBox="0 0 130 100" >
<IF PIXEL RATIO = 2>
<image xlink:href="test_2x.png" id="svg_1" height="100" width="130" y="0" x="0"/>
<ELSE>
<image xlink:href="test.png" id="svg_1" height="100" width="130" y="0" x="0"/>
<END IF>
</pattern>
</defs>
<rect id="rectangle" stroke="rgb(29, 29, 255)" fill="url(#test)" x="50" y="47" width="320" height="240" />
</svg>
I only have found Switch Element in the documentation but it doesn't seem to be very helpful since there is no "retina display" feature. Or is there? :)
You could use CSS media selectors to detect retina displays. Using the display property, you can switch the images on and off depending on the device.
I don't have an Apple retina device at hand to test, but I think something like this should work:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="480">
<style type="text/css">
#media all {
#test_2x_png {display:none}
}
#media (-webkit-min-device-pixel-ratio: 2) {
#test_png {display:none;}
#test_2x_png {display:inline;}
}
</style>
<defs>
<pattern id="test" patternUnits="userSpaceOnUse"
x="0" y="0" width="130" height="100"
viewBox="0 0 130 100" >
<image xlink:href="test_2x.png" height="100" width="130" y="0" x="0" id="test_2x_png"/>
<image xlink:href="test.png" height="100" width="130" y="0" x="0" id="test_png"/>
</pattern>
</defs>
<rect id="rectangle" stroke="rgb(29, 29, 255)" fill="url(#test)" x="50" y="47" width="320" height="240" />
</svg>

Imagemagick svg conversion

I have a svg file which I want to be converted into jpg/png. Probem is that conversion is fine if there is no background image. But when I try to put some background image its not being rendered in the converted image and showing plain background color.
content of svg:
<svg height="370" version="1.1" width="350" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: relative; left: -0.5px;">
<defs>
<pattern id="38A07B9C-47E8-4E02-A005-E6E4443FE5D0" x="0" y="0" patternUnits="userSpaceOnUse" height="300" width="300" patternTransform="matrix(1,0,0,1,0,0) translate(0,20)">
<image x="0" y="0" href="/home/mahad/public_html/svg/user-backgrounds/4f41f6a2a75dc_back.png" width="300" height="300"/>
</pattern>
</defs>
<rect x="0" y="0" width="350" height="370" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style=""/>
<rect x="0" y="20" width="350" height="350" r="0" rx="0" ry="0" fill="url(#38A07B9C-47E8-4E02-A005-E6E4443FE5D0)" stroke="none" style="fill: url("#38A07B9C-47E8-4E02-A005-E6E4443FE5D0") rgb(0, 0, 0); opacity: 0.38;" opacity="0.38"/>
<rect x="0" y="20" width="14" height="14" r="0" rx="0" ry="0" fill="#000000" stroke="none" style=""/>
<text style="text-anchor: middle; font: 12px "Arial"; opacity: 1;" x="100" y="100" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ff0000" font-size="12px" opacity="1" transform="matrix(1,0,0,1,73,92)">
<tspan dy="4.5">helllloooo...</tspan>
</text>
</svg>
conversion command:
echo exec("/usr/bin/convert /home/public_html/qr.svg /home/public_html/qr.png");
please help
In my case, installing librsvg2-bin fixed the problem:
sudo apt-get install librsvg2-bin

Resources