SVG getIntersectionList returns null - javascript

In the context of a SVG file, the following JavaScript:
var svg = document.rootElement, hitRect, hits;
hitRect = svg.createSVGRect();
hitRect.height = 1;
hitRect.width = 1;
hitRect.y = 100;
hitRect.x = 100;
hits = svg.getIntersectionList(hitRect, null);
always assigns null to hits, regardless if there were any intersections at all (in the case of no intersections, it should've been an empty NodeList).
Has anyone stumbled in to this problem? Is there a known workaround for hit-testing a SVG in Android?
Tested on: Android default browser on Android 4.0.3 (emulator), 4.0.3 (GALAXY Note SC-05D). (Google Chrome works)
Edit
I also tried looping through all elements (document.getElementsByTagName("*")), testing each one with svg.checkIntersection, to no avail. checkIntersection just returned true for every single element.

I also encounter the problem when test of iOS Safari <= 5.0, same like it's not support SVG 1.1, so after adding following attribute to the svg element, it's no effect:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect id="r1" x="5" y="5" width="40" height="40"/>
<rect id="r2" x="105" y="105" width="40" height="40"/>
<rect id="r3" x="5" y="5" width="40" height="40"/>
<rect id="rr" x="5" y="5" width="400" height="400" fill="red"/>
<rect id="r4" x="5" y="5" width="40" height="40"/>
<rect id="r5" x="5" y="5" width="40" height="40"/>
</svg>
<script type="text/javascript">
var isTouch = ('ontouchstart' in window) || ('DocumentTouch' in window && document instanceof DocumentTouch);
var downE = isTouch? 'touchstart' :'mousedown';
var moveE = isTouch? 'touchmove' :'mousemove';
var upE = isTouch? 'touchend' :'mouseup';
window.addEventListener(downE, startTest )
function startTest (evt) {
setTimeout(function () {
var svg=document.querySelector('svg');
var r = svg.createSVGRect();
r.x = 20;
r.y = 20;
r.width = r.height = 44;
var getIntersectionList = svg.getIntersectionList(r, null );
var checkIntersection = svg.checkIntersection( document.querySelector('#r2'), r );
var elementFromPoint = document.elementFromPoint(20,20);
alert("getIntersectionList: "+getIntersectionList);
alert("checkIntersection: "+checkIntersection);
alert("elementFromPoint: "+elementFromPoint);
},1000);
}
</script>
</body>
</html>
Above test code should alert:
getIntersectionList: [object NodeList]
checkIntersection: false
elementFromPoint: [object SVGRectElement]
But in iOS Safari <=5.0 and some android it's alert:
getIntersectionList: null
checkIntersection: true
elementFromPoint: [object SVGRectElement]
So, if you want to get better compatibility, only rely on the method:
var el = document.elementFromPoint(x,y);
it's get topmost element under the point (x,y), even support IE 5.5
You can test 5 points in a small rect area(center, 4 corner) (or more points), to workaround this.

Related

Change Position of svg element using JS

Trying to make an svg rectangle that moves when button pushed. Right now I just want the x to be modified by a function.
function modX()
{
document.getElementById("rectangle").transform = 'translate(295 115)';
}
var x = 20;
var y = 20;
modX();
<svg width="1000" height="1000" >
<rect id="rectangle" x="0" y="20" width="100" height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)"></rect>
</svg>
I'm fairly new to code so please avoid css or jquery.
you can change its x by using javaScript document.getElementById("rectangle").setAttribute('x', X_value)
set the X_value to the value you want it to change.

Filling an existing svg rectangle with text

I'm trying to use JavaScript to create an SVG rectangle with text in it. I've already got the rectangle (generated by morris.js, a charting library) but can't seem to be able to get the text in.
The output I want to achieve would look a bit like this:
<svg>
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="0" y="50" font-family="Verdana" font-size="35" fill="blue">Hello</text>
</g>
</svg>
This is my code now (snippet will not run because rectangleElement is undefined here):
console.log(rectangleElement);
/* output:
<rect x="1205.5019308035712" y="0" width="193.5206919642857" height="307" r="0" rx="0" ry="0" fill="#E5E5E5" stroke="none" fill-opacity="0.8" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); fill-opacity: 0;"></rect>
*/
var t = document.createElementNS('http://www.w3.org/2000/svg', 'text');
var g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
g.appendChild(t);
g.appendChild(rectangleElement);
console.log(g);
/* output:
<g><text></text></g>
*/
As you can see, the rectangleElement isn't being added to my group (g). I'm also not getting any errors in the console when trying to append the rectangle to the group.
Any ideas on what I could be doing wrong?
I ended up fixing it myself. I'm not at all sure what the issue was, when I added the seemingly unrelated code below, it started working.
var txtElem = document.createElementNS("http://www.w3.org/2000/svg", "text");
txtElem.setAttributeNS(null,"x",20);
txtElem.setAttributeNS(null,"y",40);
var theText = "text";
var theMSG = document.createTextNode(theText);
txtElem.appendChild(theMSG);

Snap SVG: String to Element

In jQuery you can simply creating an element by providing a string, like so:
var newElement = $('<div></div>');
How can I do the same thing in Snap SVG? I have a string like
<rect x="100" y="100" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 1825.4047 1024.3746)" fill="#7EC242" width="230.02" height="56.723" stroke="#64bc46"/>
And I need an Element I can append to an already existing Snap document. I tried fragments, but they don't have all functions I need to manipulate the element afterwards.
I believe you can do it with parse (I removed the transform so the code could work in the small SO snippet window):
var s = Snap("#svg");
var string = '<rect x="100" y="100" fill="#7EC242" width="230.02" height="56.723" stroke="#64bc46"/>'
var rect = Snap.parse(string);
s.append(rect);
<script src="http://cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script>
<svg id="svg" width="400" height="200">
</svg>

How to interrogate snap svg event object to get viewbox coordinate?

I have a simple svg file containing 2 rectangles and a text :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg id="mySvg" onload="init()" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="100%" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 1371.4286 773.5047">
<script xlink:href="snap.svg-min.js" type="text/ecmascript"/>
<rect id="blackRect" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto" ry=".16344" height="773.5" width="1371.4" y="161.71" x="-371.43" fill="#ffb380"/>
<rect id="hoverTarget" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto" ry=".098402" height="177.14" width="286.62" y="369.51" x="180" fill="#008080"/>
<text id="viewboxText" style="word-spacing:0px;letter-spacing:0px" font-weight="bold" xml:space="preserve" font-size="27.5px" line-height="125%" y="810.93359" x="-3.165039e-005" font-family="sans-serif" fill="#000000"><tspan id="tspan3348" x="-3.165039e-005" y="810.93359">Viewbox :</tspan></text>
</svg>
and before the closing </svg> tag i added this script:
<script><![CDATA[
var mySvg, hoverTarget, viewboxText;
function init(){
mySvg=Snap("#mySvg");
hoverTarget=mySvg.select("#hoverTarget");
viewboxText=mySvg.select("#viewboxText");
hoverTarget.mousemove(hoverCursor);
}
function hoverCursor(evt){
var cursorX, cursorY;
if(evt.type==="mousemove"){
cursorX=...;
/*this is my question : how to interrogate the evt object to get X position of the cursor
according to mySvg viewbox?*/
cursorY=...;
//and, of course, how to get Y position from the evt object..
//and after that, display it on the text...
viewboxText.attr({text : "X : " + cursorX + ", Y : " + cursorY});
}
}
]]></script>
My question is : is there any way to interrogate snap event object of the event handler function to obtain viewbox coordinate of the svg parent element?
If there is, what is the syntax?
This is what I think you may be after...
First we get the inverse matrix from the element to the screen
var m = Snap.matrix( evt.target.getScreenCTM().inverse() )
// you may want to use this instead, but should be same for this case
// var m = Snap.matrix( mySvg.node.getScreenCTM().inverse() )
var newX = m.x( cursorX, cursorY )
var newY = m.y( cursorX, cursorY )
m.x(), m.y() convert the x,y coordinates with the new matrix.
jsfiddle

how to scale the element created by use by keeping the fixed position in svg

I want to scale the element created by use by keeping the fixed position in svg.
I read this
but my element is created by use
so it shows
Simply I can remove the old one and create a new one ,but I feel this a bit trouble.
So I wonder whether it exists any convenient way?
function tableBindMouseClick(parametersObject)
{
var table = document.getElementById("PointsTable");
var length = $('#PointsTable tbody tr').length;//get table rows number
for(var i =0;i<length;i++)
{
var id = i;
$($('#PointsTable tbody tr')[i]).bind('click',
(function(id)
{
return function()
{
var p = parametersObject.pointArray[id];
var x = p[0] -5;//coordinate x
var y = p[1] -5;//coordinate y
var icon = document.getElementById("point"+id);
icon.setAttributeNS(null, "transform", "translate("+-x+"," + -y +") scale(3) translate("+x+","+y+")");
};
})(id));
}
I do not know whether it is enough.
I am still modifying it.It can run but its effect is still incorrect.
The result
I can not see the error...
PS:Unfortunately,I use the defs element instead of symbol element to create icon.I also want to know difference in them,including g element.
I complete it by this parameters:
icon.setAttributeNS(null, "transform", "translate("+-2*x+"," + -2*y +")" + " scale(3)" );
I think the post makes some mistakes...
This example may make sense.
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Scalable Vector Graphics (SVG) 1.1 (Second Edition)</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" width="5000" height="5000" viewBox="0 0 5000 5000">
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"
transform ="translate(-230,-230 ) scale(3)" />
</svg>
</body>
</html>

Categories