I'm creating several click-able maps - and have been unsuccessful in trying to find how to access a tag for a path so that I can make all the different counties in the map clickable. (the SVG file is incredibly complicated... this is the structure and I can't change it - it's getting automatically generated for all the different states):
<svg width="932.25827pt" height="569.25354pt" viewBox="0 0 932.25827 569.25354" enable-background="new 0 0 932.25827 569.25354"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<g id="Layers">
<g id="Ohio_Counties">
<clipPath id="SVG_CP_1">
<path d="M0,569.25354L0,0L932.25827,0L932.25827,569.25354L0,569.25354z"/>
</clipPath>
<path clip-path="url(#SVG_CP_1)" fill="none" stroke="#4E4E4E" stroke-width="0.48003" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" d="
M374.18483,441.14215L375.38491,440.90214L375.62493,440.90214L376.58499,440.66213L376.82501,440.66213L377.54505,440.42212
L378.02508,440.42212L378.2651,440.42212L378.74513,440.42212L379.46518,440.66213L381.14529,440.66213L381.38531,440.66213L
381.62532,440.66213L382.10536,440.66213L382.8254,440.66213L384.50551,440.90214L384.74553,440.90214L386.18563,440.90214L386.42564,441.38217
L386.42564,441.62218L386.42564,441.86219L386.66566,441.86219L386.90567,441.86219L386.90567,442.1022L386.90567,442.34221L"/>
</path>
</g>
</g>
/* There are about 87 more paths in the file... this is just a part of one.*/
I'm using jquery.svg - but haven't found the solution in the documentation.
Here's the javascript:
function changeState(newState){
nS = newState.replace(/\s/g, '');
try {
var map = 'mapLayers/AEP'+nS+'Counties.svg';
$("#contentCounties").empty();
var currentCountyMap = $('#contentCounties').svg({loadURL: loc, onLoad: addClickEvents(this)});
} catch(err){
alert("the map " + currentCountyMap + " does not exist");
}
}
function addClickEvents(){
// this is where I want to put the code to
// add click events to the individual paths.
// Whether it's running a loop or using a jquery selector
// I'm fine with either.
// This is, in theory, what I think I want - but alas, it is wrong:
var svg=document.getElementByTagName("path");
alert(svg);
}
Looks like you've just left the s out of getElementsByTagName
Related
I have this code snippet:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" stroke="#000" stroke-linecap="round" stroke-linejoin="round" fill="none" fill-rule="evenodd">
<path d="M377.4528 264.0669q3.7795-113.3858 151.1811-113.3858m0 0q0 11.3386 0 11.3386 0 139.8425-41.5748 139.8425m3.7795 0q-37.7953 0-37.7953 0 56.6929 0 56.6929 113.3858-132.2835 0-132.2835-79.3701"/>
<path d="M377.4528 335.878q0 79.3701-132.2835 79.37-3.7795-113.3857 56.6929-113.3857-75.5905 0-75.5905-151.1812 151.1811 0 151.1811 113.3859"/>
<ellipse cx="377.4528" cy="284.8543" rx="3mm" ry="16.5mm"/>
</svg>
<script type="text/javascript">
d3.json("./data.json").then(function(data){
var svg = d3.select("body")
.selectAll("svg")
.... something here
})
</script>
</body>
I cannot update, with values from data.json file, for example cx, cy, rx etc... and most of all values contained in path string. Someone can help me? Thanks to all.
In the example below I'm using a mock API to simulate your d3.json() request and then making up a new value for rx and ry for the ellipse. I've used timeout just for demonstration purposes so that you can see the ellipse changes - you wouldn't need to do that in your code.
So, once you have the new data, you can use a selection e.g. d3.select("svg ellipse") so you can then update the attributes of the selection.
If your new data has new d attributes for the path elements, then you can use the same approach e.g. path.attr("d", newD). If you want to change datapoints within the path definition, it would depend on your incoming data and better asked as a separate question.
// mock api to make this snippet work
const url = "https://jsonplaceholder.typicode.com/todos/1";
// wait for 1.5s and apply new attributes to ellipse
setTimeout(function() {
// get the new data
d3.json(url).then(function(data) {
// mock up some data
data = [{rx: "5mm", ry: "20mm"}];
changeEllipse(data[0]);
});
}, 1500);
function changeEllipse(data) {
// select the ellipse with a selector
const ellipse = d3.select("svg ellipse");
// change attributes
ellipse
.attr("rx", data.rx)
.attr("ry", data.ry);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" stroke="#000" stroke- linecap="round" stroke-linejoin="round" fill="none" fill-rule="evenodd">
<path d="M377.4528 264.0669q3.7795-113.3858 151.1811-113.3858m0 0q0 11.3386 0 11.3386 0 139.8425-41.5748 139.8425m3.7795 0q-37.7953 0-37.7953 0 56.6929 0 56.6929 113.3858-132.2835 0-132.2835-79.3701"/>
<path d="M377.4528 335.878q0 79.3701-132.2835 79.37-3.7795-113.3857 56.6929-113.3857-75.5905 0-75.5905-151.1812 151.1811 0 151.1811 113.3859"/>
<ellipse cx="377.4528" cy="284.8543" rx="3mm" ry="16.5mm"/>
</svg>
Let's say that we have the following simple SVG element:
const svg = `<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M100 100C100 44.7715 55.2285 -1.95703e-06 0 -4.37114e-06L-4.37114e-06 100L100 100Z" fill="current"/>
</g>
</svg>`
The svg variable is a string and I want to extract all the child nodes from the svg (the <g> element for the specific example but can be more elements).
How can I do that without using a DOM manipulation library like JQuery?
Version 2
You can use str.split() to extract all the child elements from the <svg> as a string.
Working Example:
const svg = `<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M100 100C100 44.7715 55.2285 -1.95703e-06 0 -4.37114e-06L-4.37114e-06 100L100 100Z" fill="current"/>
</g>
</svg>`;
let g;
g = svg.split('xmlns="http://www.w3.org/2000/svg">')[1];
g = g.split('</svg>')[0];
g = g.trim();
console.log(g);
Version 1
I want to extract the content from the <svg> which is the
element inside it.
If I've understood correctly:
you want to extract only the <g> element
you know that the <svg> contains a <g> element
you know that there is only one <g> element
you can use str.split() to extract the <g> from the <svg>.
Working Example:
const svg = `<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M100 100C100 44.7715 55.2285 -1.95703e-06 0 -4.37114e-06L-4.37114e-06 100L100 100Z" fill="current"/>
</g>
</svg>`;
let g;
g = svg.split('<g ')[1];
g = g.split('</g>')[0];
g = '<g ' + g + '</g>'
console.log(g);
Either use JavaScripts built in DOMParser
var p= new DOMParser()
var d= p.parseFromString(svg,"text/html")
var g= d.querySelector("svg g")
OR make your own html/xml parser from scratch by looping through each character, checking for <, if found look for some letters next for the tag, if found look for other >, get all content in between for attributes, rinse and repeat
As the title says I have a object in my HTML which is the SVG
<object data="images/parallax_2/buildings_1.2.svg" type="image/svg+xml" id="building_1">
That SVG is of a building I made in illustrator. As I scroll down the page I want certain windows of that building to change colour as if someone inside were turning a light on.
Within the SVG file these are the windows I want to change:
<g>
<polygon id="WINDOW_x5F_1" class="st107" points="583.3,1114.5 583.4,1047.9 607.4,1052 607.3,1118.7 "/>
<polygon class="st107" points="628.1,1122.3 628.2,1055.7 652.2,1059.8 652.1,1126.5 "/>
<polygon class="st107" points="672.9,1130.1 673,1063.4 697,1067.6 696.9,1134.2 "/>
<polygon class="st107" points="717.6,1137.8 717.7,1071.1 741.8,1075.3 741.6,1142 "/>
<polygon class="st107" points="762.4,1145.6 762.5,1078.9 786.5,1083.1 786.4,1149.7 "/>
<polygon class="st107" points="807.2,1153.4 807.3,1086.7 831.3,1090.9 831.2,1157.5 "/>
<polygon class="st107" points="851.9,1161.1 852.1,1094.5 876.1,1098.7 876,1165.3 "/>
<polygon class="st107" points="896.7,1168.9 896.8,1102.2 920.9,1106.4 920.7,1173.1 "/>
<polygon class="st107" points="941.5,1176.6 941.6,1110 965.6,1114.2 965.5,1180.8 "/>
</g>
As you can see I changed the ID of one of them so I can then target it with my Javascript on my index.html page:
window.onscroll = function changeClass(){
var scrollPosY = window.pageYOffset | document.body.scrollTop;
// Get the Object by ID
var a = document.getElementById("building_1");
// Get the SVG document inside the Object tag
var svgDoc = a.contentDocument;
// Get one of the SVG items by ID;
var svgItem = svgDoc.getElementsByClassName('st107');
// Set the class to something else
if(scrollPosY > 100) {
svgItem.className = ('st1071');
} else if(scrollPosY <= 100) {
svgItem.className = ('st1071');
}
}
Unfortunately this isn't working for me. I'm not getting any errors from this, just nothing is happening.
I was wondering if any of you would know how to succeed at this?
Any responses would be massively appreciated!!
Many, many thanks,
Adam
So I create a paperjs path object and put it in a group:
let path = new paper.Path.Rectangle(originpoint, deviceWidth, deviceHeight);
let ret = new paper.Group();
ret.addChild(path);
And then I export the ret to SVG as follows:
let svg = ret.exportSVG({
asString:true
});
But the output of this is only coming as :
<g xmlns="http://www.w3.org/2000/svg" fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,85000v-85000h135000v85000z"/></g>
As you can notice there is no <svg> element here. How can I get the standard SVG header without having to manually splice it into the code. I'm obviously missing something because the project I am working on generates SVG's of whats displayed on the canvas with the <svg> elements with the following header:
<svg width="135mm" height="85mm" viewBox="0 0 135000 85000" xmlns="http://www.w3.org/2000/svg">
Im sure I'm missing some detail of how paper.js works, its seems like paper.js has specific objects that it puts into the svg container. Does anyone know what it is ? or What I might be doing wrong....
Thanks!
I am not a paper.js user or something but just playing around with the library I realized that exportSVG is inherited from paper prototype, so if you call it from current project paper.project then it seems to work as intended:
paper.setup(new paper.Size(300, 200));
let path = new paper.Path.Rectangle([0,0], 100, 100);
let ret = new paper.Group();
ret.addChild(path);
let svg = paper.project.exportSVG({
asString:true
});
console.log(svg);
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="200"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g><path d="M0,100v-100h100v100z"/></g></g></svg>
FIDDLE: https://jsfiddle.net/ibowankenobi/juem7f80/1/
Scroll to the bottom to see the snippet.
I have an svg file containing a group with a single line element. I can make use of the use element and make several reference copies in any position I want them. However, I want to use javascript to add and remove the use element dynamically. Is there a way to use javascript to insert an svg use element of my line into my group?
<svg version="1.1" id="ex1-3rds-quarter-s" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="323.333px" height="55.333px" viewBox="0 0 323.333 55.333" enable-background="new 0 0 323.333 55.333"
xml:space="preserve">
<g id="ledgerlines">
<line id="MidCLine1" fill="none" stroke="#000000" stroke-width="0.75" stroke-miterlimit="10" x1="48.09" y1="41.694" x2="57.924" y2="41.694"/>
</g>
</svg>
var svgns = "http://www.w3.org/2000/svg";
var xlinkns = "http://www.w3.org/1999/xlink";
// Get a reference to the <g> element
var g = document.getElementById("ledgerlines");
// Create a <use> element
var use = document.createElementNS(svgns, "use");
// Add an 'href' attribute (using the "xlink" namespace)
use.setAttributeNS(xlinkns, "href", "#MidCLine1");
// Offset the line down by 10
use.setAttribute("y", "10"); // offset = y+10
// Add the <use> to the <g>
g.appendChild(use);
Demo here