SVG Click Handling Inconsistent With Displayed Location - javascript

I am building a web based, world domination game. The backbone of the game is a three level zoomable map of thirty-eight territories.
I built the map with SVG paths. The global view has a widescreen aspect ratio. When displaying the map on a square screen, for the sake of aesthetics, the entire SVG must be centered vertically using an animation tag. I've gotten the centering to work perfectly, the part I don't understand comes in when I click to zoom the map. It seems as though for the purposes of clicking, the map is a few (about 25) pixels above where it is displayed. For example, if I were to click on the grey background slightly above Russia, it would zoom me to the Asian continent. It seems more interesting to me when I consider the fact that I use transforms on every path for territorial and continental zoom levels, and the same problem does not occur.
The HTML looks as such:
<div class="test1" width="100%" height="100%">
<div id="renderedSprites"></div>
<div id="background"></div>
<div id="continentFilter" class="filter"></div>
<div id="territoryFilter" class="filter"></div>
<svg
preserveAspectRatio="xMinYMin meet"
class="territoryImage"
id="continentalSVG"></svg>
<svg
preserveAspectRatio="xMinYMin meet"
class="territoryImage"
id="territorialSVG"></svg>
<%= render partial: "images" %>
</div>
The images partial contains the global SVG, which is too long to show but follows this format:
<svg
preserveAspectRatio="xMinYMin meet"
class="territoryImage"
id="globalSVG">
<g>
<path
class="continentName"
id="territoryName"
d="..."
inkscape:connector-curvature="0" />
</g>
37 More paths and animations...
</svg>
The zooming JS is simple and pretty much irrelevant. I just clone the paths for the desired piece of the map into the proper SVG for that level. I then display that SVG at a higher z-index and put a filter or set of filters in between displayed levels. Here it is though, anyways (sorry it's so packed and disgusting):
var zoomLevel = ["global","globe"];
//renderObject("encampment",zoomLevel);
//renderObject("fort",zoomLevel);
$(".territoryImage").click( function(e) {
if ($(document.elementFromPoint(e.pageX,e.pageY)).is("path") == true) {
if (zoomLevel[0] == "global") {
var continent = $(".".concat($(document.elementFromPoint(e.pageX,e.pageY)).attr("class")))
for (i = 0; i < continent.length; i++) {
$("#continentalSVG").append($(continent[i]).parent().clone())
}
var box = $("#continentalSVG")[0].getBoundingClientRect()
var newScaleFactor
if (box.width/$(window).width() > box.height/$(window).height()) {
newScaleFactor = ($("#background").width()*parseFloat($("#continentalSVG").children("g").attr("transform").split(")")[0].replace("scale(","")))/box.width*0.95;
console.log(newScaleFactor);
}
else {
newScaleFactor = ($("#background").height()*parseFloat($("#continentalSVG").children("g").attr("transform").split(")")[0].replace("scale(","")))/box.height*0.95;
console.log(newScaleFactor);
}
$("#continentalSVG").children("g").attr("transform","scale(" + newScaleFactor + ")");
var scaledBox = $("#continentalSVG").offset();
scaledBox.top = ((scaledBox.top - $("#background").offset().top)/newScaleFactor) - (($("#background").height()/2) - ($("#continentalSVG")[0].getBoundingClientRect().height/2))
scaledBox.left = ((scaledBox.left - $("#background").offset().left)/newScaleFactor) - (($("#background").width()/2) - ($("#continentalSVG")[0].getBoundingClientRect().width/2))
$("#continentalSVG").children("g").attr("transform", $("#continentalSVG").children("g").attr("transform") + " translate(" + -1*scaledBox.left + ", " + -1*scaledBox.top + ")")
$("#continentalSVG").css("z-index","2");
$("#continentFilter").css("display","inline");
zoomLevel = ["continental",$("#continentalSVG").children("g").attr("class")];
//renderObject("encampment",zoomLevel);
//renderObject("fort",zoomLevel);
}
else if (zoomLevel[0] == "continental") {
var territory = "#" + document.elementFromPoint(e.pageX,e.pageY).id;
$("#territorialSVG").append($(territory).parent().clone())
var box = $("#territorialSVG")[0].getBoundingClientRect();
var newScaleFactor
if (box.width/$(window).width() > box.height/$(window).height()) {
newScaleFactor = ($("#background").width()*parseFloat($("#territorialSVG").children("g").attr("transform").split(")")[0].replace("scale(","")))/box.width*0.95;
}
else {
newScaleFactor = ($("#background").height()*parseFloat($("#territorialSVG").children("g").attr("transform").split(")")[0].replace("scale(","")))/box.height*0.95;
}
$("#territorialSVG").children("g").attr("transform","scale(" + newScaleFactor + ")");
var scaledBox = $("#territorialSVG").offset()
//console.log(scaledBox)
scaledBox.top = ((scaledBox.top - $("#background").offset().top)/newScaleFactor) - ($("#background").height() - ($("#territorialSVG")[0].getBoundingClientRect().height))/(newScaleFactor*2)
scaledBox.left = ((scaledBox.left - $("#background").offset().left)/newScaleFactor) - ($("#background").width() - ($("#territorialSVG")[0].getBoundingClientRect().width))/(newScaleFactor*2)
//console.log(($("#background").width() - ($("#territorialSVG")[0].getBoundingClientRect().width))/(newScaleFactor*2))
$("#territorialSVG").children("g").attr("transform", $("#territorialSVG").children("g").attr("transform") + " translate(" + -1*scaledBox.left + ", " + -1*scaledBox.top + ")")
$("#territorialSVG").css("z-index","4");
$("#territoryFilter").css("display","inline");
zoomLevel = ["territorial",territory, zoomLevel[1]];
//renderObject("encampment",zoomLevel);
//renderObject("fort",zoomLevel);
}
}
else {
if (zoomLevel[0] == "continental") {
$("#continentalSVG").children().remove();
$("#continentFilter").css("display","none");
$("#continentalSVG").css("z-index","-1");
zoomLevel = ["global","globe"];
//renderObject("encampment",zoomLevel);
//renderObject("fort",zoomLevel);
}
else if (zoomLevel[0] == "territorial") {
$("#territorialSVG").children().remove();
$("#territoryFilter").css("display","none");
$("#territorialSVG").css("z-index","-1");
$("#continentalSVG").css("z-index","2");
zoomLevel = ["continental", zoomLevel[2]];
//renderObject("encampment",zoomLevel);
//renderObject("fort",zoomLevel);
}
}
});
Here is the relevant part:
function setOriginalZoom() {
//this first part scales all the SVG's as well as the background, the filters, and a div I use for sprites
$(".territoryImage").attr("viewBox", "0 0 " + $(window).width()*0.95 + " " + $(window).height()*0.95);
$(".territoryImage").attr("width", $(".territoryImage").attr("viewBox").split(" ")[2]);
$(".territoryImage").attr("height", $(".territoryImage").attr("viewBox").split(" ")[3]);
$("#background").css("width", $(".territoryImage").width())
$("#renderedSprites").css("height", $(".territoryImage").height())
$("#renderedSprites").css("width", $(".territoryImage").width())
$("#background").css("height", $(".territoryImage").height())
$(".filter").css("width", $(".territoryImage").width())
$(".filter").css("height", $(".territoryImage").height())
$("g").attr("transform", "scale(" + $(".territoryImage").attr("viewBox").split(" ")[2]/3508 + ")")
//this part vertically centers the global SVG. The part that seems to trip things up.
$("#globalSVG").children("g").attr("transform", $("#globalSVG").children("g").attr("transform") + " translate(0 " + (($("#background").height()/2) - ($("#globalSVG")[0].getBoundingClientRect().height/2) + ($("#globalSVG").offset().top - $("#background").offset().top))/(($(".territoryImage").attr("viewBox").split(" ")[2]/3508)*2) + ")")
}
I call this function on page load, and it centers all of the displayed elments. It also scales the SVG's for the global view. The last bit I commented out, was written to vertically center the map.
It has occurred to me that the way I listen for clicks on the map may be responsible for the bug. This piece of code, included in the zooming section above, is what i'm talking about:
$(".territoryImage").click( function(e) {
if ($(document.elementFromPoint(e.pageX,e.pageY)).is("path") == true) {
I wrote it that way because the simpler way,
$("path").click( function() {...});
would fire whenever someone clicks on the SVG. For whatever reason that solution registered the path as being the defined size of the SVG (in terms of height and width attributes which I set to a percent of the window size), while the other implementation only fired when a filled part of the path was clicked.
Now if anyone can figure this out, I would really appreciate it. If you have any questions, really please ask I'll respond asap.
Thanks,
-Alex

Related

Calculate absolute position for d3 graph nodes

I have a d3 force layout. Each node in this force layout has a label, which is a <div> code(can have table inside) and should follow it all the time. I defined the <div>'s position to be absolute and set their position like this:
var updateNode = function() {
label_xOffset=10;
label_yOffset=10
this.attr("transform", function(d,i) {
//this is where I set their position
//d.num declare corresponding div in node_lables_divs array
node_labels_divs[parseInt(d.num)].style("left",(d.x+label_xOffset)+"px").style("top",(d.y+label_yOffset)+"px");
return "translate(" + d.x + "," + d.y + ")";
});
}
function tick(e) {
node.call(updateNode);
}
Everything is good now as long as I don't pan or zoom in my SVG. But I need those features too. So in my zoom function I handled it like this:
var zoomer = d3.behavior.zoom().scaleExtent([0.1,10]).
x(xScale).
y(yScale).on("zoom", redraw);
function redraw() {
var translation=" translate(" + d3.event.translate[0] + "px,"+d3.event.translate[1]+"px)";
d3.selectAll("div.node_lables_html").style("transform",translation)
.style("-webkit-transform",translation)
.style("-ms-transform",translation);
//vis is the <g> tag that contains the whole nodes and links
vis.attr("transform","translate(" + d3.event.translate + ")"+" scale(" + d3.event.scale + ")");
}
Now every thing good when I drag and pan the SVG. But it is very bad when I try to zoom in the SVG, lables are going in different direction and they are not following the nodes. I print out the d3.event.translate and it seems that it has different scale in times of zoom and panning.
I also tried the d3 foreignElement but it seems that the transform attribute doesn't work for the foreignElements. How should I calculate the correct value to transform htmls?
As per this solution to a similar question (it's not a duplicate, quite), you need to:
Put the div into a foreignObject SVG element (which allows arbitrary HTML inside an SVG)
add the foreignObject to a group, along with anything else that needs to be with the label
Only apply the tranforms to the group

How to get the click coordinates relative to SVG element holding the onclick listener?

I haven't been able to calculate the click coordinates (x and y) relative to the element triggering the event. I have not found an easy example online.
I have a simple svg (with 100px left margin) in an HTML page. It contains a group (translated 30px 30px) which has an onclick listener attached. And inside that group I have a rect with 50px width and height.
After I click any part of the group element, I get an event object with coordinates relative to the HTML page (evt.clientX and evt.clientY).
What I need to know is where exactly the user clicked inside the group element (the element holding the onclick listener).
How do I convert clientX and clientY coordinates to the group element coordinates. So say, if I click the top leftmost part of the rect it should give me x=0 and y=0.
Here is currently what I have:
<!DOCTYPE html>
<html>
<head>
<style>
body{
background:black;
}
svg{
fill:white;
background:white;
position: absolute;
top:100px;
left:100px;
}
</style>
<script>
function clicked(evt){
alert("x: "+evt.clientX+" y:"+evt.clientY);
}
</script>
</head>
<body>
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<g transform="translate(30 30)" onclick="clicked(evt)">
<rect x="0" y="0" width="50" height="50" fill="red"/>
</g>
</svg>
</div>
</body>
</html>
Tolokoban's solution has the limitation that it doesn't work if your viewBox deviates from the default, that is if it is different from viewBox="0 0 width height". A better solution that also takes viewBox into account is this:
var pt = svg.createSVGPoint(); // Created once for document
function alert_coords(evt) {
pt.x = evt.clientX;
pt.y = evt.clientY;
// The cursor point, translated into svg coordinates
var cursorpt = pt.matrixTransform(svg.getScreenCTM().inverse());
console.log("(" + cursorpt.x + ", " + cursorpt.y + ")");
}
(Credit goes to Smerk, who posted the code)
If the viewBox is not set or set to the default, this script will return the same values as Tolokoban's script. But if you have an SVG like <svg width="100px" height="100" viewBox="0 0 200 200">, only this version will give you the correct results.
Try to use getBoundingClientRect(): http://jsfiddle.net/fLo4uatw/
function clicked(evt){
var e = evt.target;
var dim = e.getBoundingClientRect();
var x = evt.clientX - dim.left;
var y = evt.clientY - dim.top;
alert("x: "+x+" y:"+y);
}
The proposed solutions are great, but they won't work in all scenarios.
The OP's post is titled
How to get the click coordinates relative to SVG element holding the
onclick listener?
So if you put the onclick listener onto your root svg element, whenever you click on any of its child elements, getBoundingClientRect will give you the child's Rect and you won't get the click coordinates relative to the root svg.
This was my case as I needed the coordinates relative to the root at all times, and the solution that worked for me was to use e.target.farthestViewportElement. Here's an excerpt from my (JSX) code:
const onClickSvg = e => {
const { farthestViewportElement: svgRoot } = e.target;
const dim = svgRoot.getBoundingClientRect();
const x = e.clientX - dim.left;
const y = e.clientY - dim.top;
console.log(`x: ${x}, y: ${y}`);
};
<svg onClick={onClickSvg}>...</svg>
Adding notes after many researchs (and fails!).
For a css translated svg, to get the coordinates of a clicked point for drawing.
In my case, using a mouse wheel event to translateX, so the actual rendering depends of the screen size and of the actual translated value.
I recommend for your use case to make a little drawing like the following, it will help a lot for figuring out what's going on.
Let's say my svg has for id: shoke
To get the total computed width, in pixels:
shoke.getBoundingClientRect()["width"]
Need to know the actual translateX value. (From the right, so it is a negative number, on this case)
shoke.style.transform.substr(11).slice(0,-3)
Note that it return a string and not an integer, so:
+shoke.style.transform.substr(11).slice(0,-3)
Now to get the coordinates of the mouse, related to the pixel x0 of the screen.
let pt = document.querySelector('svg').createSVGPoint();
pt.matrixTransform(shoke.getScreenCTM().inverse())["x"]
So, at the end, to obtain the precise x point:
svg_width - (svg_width + translated) + from_pixel x0 of the screen_click
Is something like this:
shoke.getBoundingClientRect()["width"] - (shoke.getBoundingClientRect()["width"] + +shoke.style.transform.substr(11).slice(0,-3)) + pt.matrixTransform(shoke.getScreenCTM().inverse())["x"]
createSVGPoint is deprecated according to Mozilla. Use static method of DOMPoint.fromPoint(svg_element);
function dom_track_click(evt) {
//<svg onclick='dom_track_click(event); >
let pt = DOMPoint.fromPoint(document.getElementById('svg_canvas'));
pt.x = evt.clientX;
pt.y = evt.clientY;
// The cursor point, translated into svg coordinates
let cursorpt = pt.matrixTransform(document.getElementById('svg_canvas').getScreenCTM().inverse());
console.log("(" + cursorpt.x + ", " + (cursorpt.y) + ")");
}

Convert an SVG element to a g element using d3.js

I am using D3 in a page where my objective is to superimpose two groups of paths : I have the earth coastlines as a background map (imported from a GeoJSON file), and I want to superimpose an old map on it, which is a separate SVG : http://bl.ocks.org/bperel/9943623/250fc9af2e09bf176f6d510e0b59fe643d792287
The SVG loading went well, however I would like my two maps to be included inside the same SVG element : it will be easier if I want the maps to be panned or zoomed. The issue here is that the external SVG has a specific viewbox, so if I move its <g> elements to the other SVG, the coordinates get messy. Hence my question : is there a way to convert the 2nd SVG to a <g> element that I could include in the first SVG ? Maybe d3 knows how to do that but I couldn't find such a tool in the documentation.
If you are going to zoom/pan the superimposed SVG's, Include both svg's in a <g> container element and attach zoom behavior to the <g> container.
Essentually, you will have:
<svg id=topSVG>
<g id=container>
<svg id=projection1>
....
</svg>
<svg id=projection2>
....
</svg>
</g>
</svg>
Below is a snippet relating to my mouswheel zoom for d3:
var myZoom=d3.behavior.zoom().scaleExtent([.1, 1000]).on("zoom", mouseWheelZoom)
function callZoomBehavior()
{
//---attach to root svg---
d3.select("#"+SVGId)
.call(myZoom)
//---reset from previous file call---
myZoom.translate([0,0])
myZoom.scale(1)
PrevScale=1
}
var PrevScale //--previous scale event---
function mouseWheelZoom()
{
//--place in d3 object--
var zoomG=d3.select("#topZoomG")
if(PrevScale!=d3.event.scale) //--transition on scale change--
{
zoomG.transition().attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")
}
else //--no transition on pan---
{
zoomG.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")
}
PrevScale=d3.event.scale
}
originalSVG = the SVG element you want to clone and convert into g element
quasiClone = the result of that
parentOfClone = parent below you want to put your new g element
var quasiClone = parentOfClone.append("g");
for (var i=0; i<originalSVG.childNodes.length; i++){
var child = originalSVG.childNodes[i];
var childClone = child.cloneNode(true);
quasiClone.node().appendChild(childClone);
}

Separating HTML elements into columns with proper spacing (JQuery and CSS)

I am trying to make a Windows 8 like interface for my webpage. I have created articles that act as tiles and have a random generator that makes the tile small or large. I am trying to make these look like they are in columns depending on the width of the screen. When I change the screen width the tiles do not seem to be properly spaced which is driving me nuts. I am new to css and jquery so I am still learning and always open to learning new ways to do things. I would really appreciate some help on this column and spacing issue.
NOTE: My tiles usually have pictures and after I changed the code just to show up as color tiles. Now they are not always showing but I will fix that issue.
For example: each column should have a width of one double box or two single box's. And depending on the screen width...if bigger the more columns will display and the smaller the less amount of columns it will display.
Here is my current code:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="http://code.jquery.com/jquery-2.1.0.min.js" type="text/javascript"></script>
<script src="Script/jquery.lorem.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function ()
{
var colors = ["#2672ec", "#00a300", "#97009f", "#094db5", "#da532c", "#af1a3f", "#613cbc", "#008ad2"];
var doubleBoxFlag = [true, false, false, false, false, false];
var pictures = ["Images/1.jpg", "Images/2.jpg", "Images/3.jpg", "Images/4.jpg", "Images/5.jpg", "Images/6.jpg", "Images/7.jpg", "Images/8.jpg", "Images/9.jpg", "Images/10.jpg", "Images/11.jpg"];
var defaultClass = '.box';
for (var i = 0; i < Math.floor((Math.random() * 64) + 34) ; i++)
{
var rand = Math.floor(Math.random() * pictures.length);
var boxRand = Math.floor(Math.random() * doubleBoxFlag.length);
var currentClass = defaultClass + i;
var currentClassJ = 'box' + i;
//For picture tiles:
//$("#Interface").append("<article class=" + currentClassJ + " " + "style='background-image: url(" + pictures[rand] + ")" + "'><span>" + i + "</span>");
//For Color Tiles:
$("#Interface").append("<article class=" + currentClassJ + " " + "style='background-color:" + colors[rand] + "'><span>" + i + "</span>");
if (doubleBoxFlag[boxRand]) {
$(currentClass).css("width", "374px");
$(currentClass).css("padding-right", "20px");
}
else
$(currentClass).css("width", "187px");
$(currentClass).css("height", "187px");
$("article").css("float", "left");
$("article").css("margin", "11px");
$("span").css("display", "block");
$("span").css("padding-top", "167px");
$("span").css("padding-left", "12px");
}
//if (screen.width <= 480)
// $("#Interface").css("width", "470px");
//if (screen.width >= 1000 && screen.width <= 1799)
// $("#Interface").css("width", "470px");
//if (screen.width >= 1800)
// $("#Interface").css("width", "470px");
// This line below should be adding the random word to each of the articles
$('span').lorem({ type: 'words', amount: '1', ptags: false });
});
</script>
</head>
<body background = "Images/bg.png">
<div id="Interface"></div>
</body>
</html>
Now that I understand your problem, I propose to you start using css media queries. Basicaly for three reasons:
It's one way to solve your problem (duh)
This scripty resising and calculations will run slower when it comes to the real world.
It's much more clear and painless.
Make a css file with all rules that you want at determined screen size, then do this again for as many screen sizes you want to match. Remeber you can use all css tricks available to one determined screen size to achieve the look & feel that you want, because rules aplied under a media query will not mess with your css in other screen sizes.
After all, organize all the stylesheets in a single files and wrap them inside a proper media query.
Give it a try, you'll love it.
And yes, it's supported in at least the three earlier versions of IE, I guess.

Change svg polygon attributes via Javascript

I am trying to scale and translate svg polygon elements, depending on the browser window size.
Calculating how much I want to scale and translate is not the problem, but changing the polygons is for me.
I am hoping you can help...
I have broken the issue down so that I count the number of polygons (this is ok):
function countnumberofPolygons() {
numberofPolygons = document.getElementsByTagName("polygon").length;
return numberofPolygons;
}
and a function that creates a string for determining the transform="" attribute of the polygon - the transform attribute can be say - transform="translate(800,00) scale(1.2)"
function createsvgtransformattribute(){
transformattribute = '"translate('+ translateAmount +',0) scale(' + scaleAmount + ')"';
}
but looping through them and setting their attributes doesn't seem to work. I've broken it all down and built it back up - but end up with this - which is wrong, probably in some simple way....
function changeattributes(numberofPolygons, transformattribute){
for (var q=0;q< numberofPolygons;q++){
document.getElementsByTagname("polygon")[q].setAttribute("transform", transformattribute);
}
}
But even when inserting the value of the string transformattribute manually, it doesn't work. Can you help please?
When you set a transform attribute using setAttribute you don't put it in double quotes. So what you need is
transformattribute = 'translate('+ translateAmount +',0) scale(' + scaleAmount + ')';
In the html I used the document read Jquery function and onresize to call svgscale().
There are a few oddities in the script - like the left side nudge - but hopefully it should work for others.
I have converted images in image tags to a div that has the image as a background-image. The image maps are then pulled into svg. Then this script uses the transform attribute of the svg to scale and translate the polygons of the image map accordingly.
var winWidth;
var winHeight;
var MainImageHeight;
var MainImageWidth;
var HeightRatio;
var imageWidth;
var leftoffset;
var ImgVsOriginal;
var offsetnudge;
var offsetnudgescaled;
var los;
var translateAmount;
var scaleAmount;
var numberofNodes;
var numberofPolygons;
var polygonArray;
var transformattribute;
function setVariables(){
//Browser window widths and heights
winWidth = window.innerWidth;
winHeight = window.innerHeight;
//Widths and heights of the element with the MainImage id
MainImageHeight = document.getElementById('MainImage').offsetHeight;
MainImageWidth = document.getElementById('MainImage').offsetWidth;
//Establishes the ratio between the height of the element and the background image it displays,
//which has a height of 920px
//The MainImage resizes the background image so the ratio is needed to scale the svg/imagemap
HeightRatio = MainImageHeight/920;
//This establishes the width of the background image as presented - the background image file is 1400px
imageWidth = HeightRatio*1400;
//The Background image is centered and covers the screen. So there is space either side of the background image
//This space is worked out here, and halved to work out the left-hand side portion of the space
leftoffset = (winWidth-imageWidth)/2;
//The original imagemap was created based on an image displayed as 960px by 653px. This calculates the ratio between them.
ImgVsOriginal = MainImageHeight/653;
//The original image was based on images with a small border each side. This is a hard-adjustment for this.
offsetnudge = 30;
//Scales the offset for this border based on the background image size vs the original
offsetnudgescaled = offsetnudge*ImgVsOriginal;
//Creates an easy to type variable based on
//los = leftoffset + offsetnudgescaled;
translateAmount = leftoffset + offsetnudge;
scaleAmount = ImgVsOriginal;
//Creates variable for idname
var idname;
}
function createsvgtransformattribute(){
transformattribute = 'translate('+ translateAmount +',0) scale(' + scaleAmount + ')';
return transformattribute;
}
function countchildNodes(){
numberofNodes = document.getElementById("svgstuff").childNodes.length;
}
function printnumberofnodes(){
document.write('<span>Number of Nodes:' + numberofNodes + '</span>');
}
function countnumberofPolygons(){
numberofPolygons = document.getElementsByTagName("polygon").length;
return numberofPolygons;
}
function getpolygonArray(){
polygonArray = document.getElementsByTagName("polygon");
}
function printnumberofPolygons(){
document.write('<span>Number of Polygons:' + numberofPolygons + '</span>');
}
function changeattributes(){
document.getElementById('test1').innerHTML='changed';
for(q=0; q<polygonArray.length; q++){
//document.getElementsByTagName('polygon')[q].setAttribute("class", "blue");
document.getElementsByTagName('polygon')[q].setAttribute("transform", transformattribute);
}
}
function svgscale(){
setVariables();
getpolygonArray();
createsvgtransformattribute(translateAmount, scaleAmount);
changeattributes();
}
Here are some example polygons for you:
<div id="MainImage">
<svg onresize="svgscale()" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="position:absolute;"
width="2000" height="2000"
pointer-events="visible">
<a xlink:href="1.htm" xlink:title="1">');
<polygon id="p1" class="" points="736,378 680,363 680,233 736,209 736,378" transform="" fill="" >
</polygon>
</a>
<a xlink:href="2.htm" xlink:title="2">
<polygon id="p2"class="area" points="839,161,742,204,739,513,831,587,839,161" transform="" fill="">
</polygon>
</a>
<a xlink:href="3.htm" xlink:title="3">');
<polygon id="p3" class="area" points="521,286,521,296,557,297,555,287,521,286" transform="" fill="" >
</polygon>
</a>
<a xlink:href="4.htm" xlink:title="4">');
<polygon id="p4" class="area" points="562,218,562,240,657,242,657,219,562,218" transform="" fill="" >
</polygon>
</a>
<a xlink:href="5.htm" xlink:title="5">');
<polygon id="p5" class="area" points="952,273,909,275,905,276,902,347,858,344,846,351,845,356,855,361,845,542,849,546,849,572,846,573,845,575,841,652,954,652,952,273" transform="" fill="" >
</polygon>
</a>
</svg>
</div>
I put some ids in the polygons in case I couldn't cycle through by TagName, but it works by obtaining the polygons by tagname and cycling through via a for loop. :-)
The css for the #MainImage div is basically:
#MainImage {background-image: url('pix/file.jpg'); background-size: auto 100%;}

Categories

Resources