Looping in Javascript for SVG objects - javascript

I had written a program for 14 numbers of different SVG objects.And I want to write a single loop program for each and every SVG object to get its point of center . I preferred using loop statement in my code with Javascript.
I had tried using JavaScript but it's not being looped repeatedly.
JavaScript code goes here;
var i=1;
while(i<15){
gear = document.getElementById("gear"+i);
let aa = gear.getBBox()
let a = {};
a.x = aa.x + aa.width/2;
a.y = aa.y + aa.height/2;
gear.setAttribute("style",`transform-origin:${a.x}px ${a.y}px` );
i++;
}
I had given unique id for each SVG object as (gear1, gear2, gear3,.....,gear14).
The final result must be looping the code for each and every SVG objects.

I would use querySelectorAll() for that. You can select all gears which ids start with "gear". And I wouldn't use a or aa as a variable name. It's just confusing.
let gears = document.querySelectorAll("[id^='gear']"); // get all gears
// Now convert "gears" into an array and loop it
Array.from(gears).forEach(function(gear){
let bbox = gear.getBBox();
let styles = {};
styles.x = bbox.x + bbox.width / 2;
styles.y = bbox.y + bbox.height / 2;
gear.setAttribute("style", `transform-origin:${styles.x}px ${styles.y}px`);
});

var i=1;
let gear =[]
while(i<3){
gear[i] = document.getElementById("gear"+i);
// alert(gear[i])
let aa = gear[i].getBBox();
let a = {};
a.x = aa.x + aa.width/2;
a.y = aa.y + aa.height/2;
gear[i].setAttribute("style",`transform-origin:${a.x}px ${a.y}px` );
i++;
}
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<g id="gear1">
<text x="5" y="16" transform="scale(2, 2)">Hello World!</text>
<text x="8" y="32" transform="translate(0 20) scale(1.25 1)">Hello World Again!</text>
</g>
<g id="gear2">
<text x="5" y="16" transform="scale(5, 8)">Hello World2!</text>
<text x="8" y="32" transform="translate(0 20) scale(1.25 1)">Hello World Again!</text>
</g>
<g id="gear3">
<text x="5" y="16" transform="scale(3, 5)">Hello World3!</text>
<text x="8" y="32" transform="translate(0 20) scale(1.25 1)">Hello World Again!</text>
</g>
</svg>

Related

Getting the coordinates of a moving SVG Circle which is moving over a path set in animateMotion

I need to check the response of a user by tracking the mouse movement over a moving object (in this case a circle). If the mouse is not over the circle I need to calculate the offset by comparing the mouse coordinates and the circle coordinates.
But whenever I check the circle values, they are not changing and will stay on their initial value.
Here's a simple example:
function clickCircle() {
var circle = document.getElementById("circle");
console.log('baseVal x: ' + circle.cx.baseVal.value);
console.log('animVal x: ' + circle.cx.animVal.value);
}
<p>Click on the moving circle</p>
<svg width="1200" height="1200">
<circle id="circle" cx="60" cy="60" r="20" fill="green" onclick="clickCircle();">
<animateMotion id="ani" dur="10s" repeatCount="indefinite"
path="M20, 60 C20,
-50 180, 150 180,
60 C180-60 20,
150 20, 60 z" />
</circle>
</svg>
Does anybody have any idea on how to get the coordinates from a moving circle that is being animated with animateMotion?
You could drag in an animation Icon, and track its properties
Or with JavaScript you calculate its center x,y position with:
let {width,height} = circle.getBBox();
let {x,y} = circle.getBoundingClientRect();
x = x + width/2;
y = y + height/2;
Also read: https://schneide.blog/2018/03/05/some-tricks-for-working-with-svg-in-javascript/
note! this code below will forever add circle Nodes!
<style> svg { width: 300px } </style>
<svg viewBox="0 0 300 200">
<rect width="100%" height="100%" fill="lightgreen"></rect>
<text x=10 y="20">Click the circle!</text>
<circle id="circle" cx="40" cy="40" r="40" fill="green"
onclick="clickCircle(event)">
<animateMotion id="ani" dur="10s" repeatCount="indefinite" path="m20 40c0-110 160 90 160 0c0-120-160 90-160 0z" />
</circle>
<text id="position" x="200" y="20">21</text>
</svg>
<script>
function clickCircle(evt) {
point("gold");
}
function point(color) {
let circle = document.getElementById("circle");
let {width,height} = circle.getBBox();
let {x,y} = circle.getBoundingClientRect();
let c = document.createElementNS("http://www.w3.org/2000/svg", "circle");
x = x + width/2;
y = y + height/2;
c.setAttribute("cx", x);
c.setAttribute("cy", y);
c.setAttribute("r", color == "black" ? 3 : 6);
c.setAttribute("fill", color);
circle.parentNode.append(c);
position.innerHTML = `${~~x} , ${~~y}`;
}
setInterval(() => point("black"), 250);
</script>
Or try the JSFiddle: https://jsfiddle.net/dannye/ph705b49/
Dan was Authorware toch heel wat makkelijker...
Alles goed?

SVG Pan and Zoom not working

Trying to carry out this svg pan and zoom for two rectangles, I can't seem to get it to work. Really new at this but I was able to come up with this but it just doesn't seem to work . I have added my javascript code as well if anyone can seem t find what is wrong, i Used the group id for the elements to try to pan and zoom based on my js but it doesn't still work
<!DOCTYPE html>
<head>
</head>
<body>
<svg width="24cm" height="16cm" viewBox="-4 -1 26 20"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="myfield" transform="scale(1,1) translate(0,0)" >
<g transform=" scale(1,-1) translate(0,-16)"><g id="togglefield">
<rect id= "rectangle1" class= "rectangles" x= 2 y= 0 width= 4 height= 6 onClick="fieldDetails(event)"></rect>
<rect id="rectangle2" class= "rectangles" x= 2 y= 6 width= 4
height= 5 onClick="fieldDetails(event)"></rect>
</g>
<g id="togglefind">
<circle class="circles" id="find1" cx= 4 cy= 1 r="0.2" onClick="findDetails(event)"></circle>
<text class="text" x= 4 y= 1 transform="translate(0 2 ) scale(-1,1) rotate(180)"> 1 </text>
<circle class="circles" id="find5" cx= 4 cy= 7 r="0.2" onClick="findDetails(event)"></circle>
<text class="text" x= 4 y= 7 transform="translate(0 14 ) scale(-1,1) rotate(180)"> 5 </text>
</g>
</g>
<rect x="12.6" y="12.4" width="3" height="3" fill="white" stroke="grey" stroke-width="0.05"/>
<text x="13" y="13.2" font-family="Arial" font-size="0.6">Legend</text>
<g id="Fieldlgd">
<rect x="12.8" y="13.6" width="0.6" height="0.6" fill="none" stroke="green" stroke-width="0.04"/>
<text x="13.6" y="14" font-family="Georgia" font-size="0.5">Field ID</text>
<text x="13" y="14" font-family="Georgia" font-size="0.5">1</text>
</g><g id="Findlgd">
<circle cx="13.1" cy="14.7" r="0.12" fill="blue" stroke="red" stroke-width="0.05"/>
<text x="13.6" y="14.85" font-family="Georgia" font-size="0.5">Find ID</text>
<text x="13.2" y="14.7" font-family="Arial" font-size="0.45">1</text>
</g>
</g>
<rect x="-4" y="0.3" width="3.2" height="12" fill="white" stroke="black" stroke-width="0" fill-opacity="0.8"/>
<text x="-4" y="0.8" font-family="San Serif" font-size="3%">Pan and Zoom </text>
<text x="-2.7" y="1.8" font-family="Georgia" font-size="4%">N</text>
<polyline id="panup" onclick="panup_click(evt)" points="-3,2 -2.5,1 -2,2 -2.3,1.9 -2.7,1.9 -3,2" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.7" y="3.4" font-family="Georgia" font-size="4%">S</text>
<polyline id="pandown" onclick="pandown_click(evt)" points="-3,2.8 -2.5,3.8 -2,2.8 -2.3,2.9 -2.7,2.9 -3,2.8" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-3.3" y="2.6" font-family="Georgia" font-size="4%">W</text>
<polyline id="panleft" onclick="panleft_click(evt)" points="-2.7,1.9 -3.7,2.4 -2.7,2.9 -2.8,2.6 -2.8,2.2 -2.7,1.9" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.1" y="2.6" font-family="Georgia" font-size="4%">E</text>
<polyline id="panright" onclick="panright_click(evt)" points="-2.3,1.9 -1.3,2.4 -2.3,2.9 -2.2,2.6 -2.2,2.2 -2.3,1.9" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.7" y="2.6" font-family="Georgia" font-size="4%">C</text>
<circle id="recenter" onclick="recenter_click(evt)" cx="-2.5" cy="2.4" r="0.3" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<polyline id="zoomcross" points="-2.6,4.2 -2.4,4.2 -2.4,4.6 -2.1,4.6 -2.1,4.8 -2.4,4.8 -2.4,5.3 -2.6,5.3 -2.6,4.8 -2.9,4.8 -2.9,4.6 -2.6,4.6 -2.6,4.2" fill="cornflowerblue"/>
<rect id="zoomIn" onclick="zoomin_click(evt)" x="-3" y="4" width="1" height="1.5" fill="white" stroke="black" stroke-width="0.05" opacity="0.2"/>
<rect id="zoomdash" x="-2.9" y="5.9" width="0.8" height="0.2"
fill="cornflowerblue"/>
<rect id="zoomOut" onclick="zoomout_click(evt)" x="-3" y="5.7" width="1" height="0.6" fill="white" stroke="black" stroke-width="0.05" opacity="0.2"/>
</svg>
// Pan left function
function panleft_click(evt) {
var root = document.documentElement;
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a
var matrix = myfield.getCTM();
// Read the translate attributes from the matrix into variable x and y
// Below is the desired leftward change
var x = (matrix.e + 2) / matrix.a ; // Divide change by current scale to remove exponential movement
var y = matrix.f / matrix.a ; // To keep motion only along one axis
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + matrix.a + "," + matrix.d + ") translate(" + x + "," + y + ")");
}
// Pan right function
function panright_click(evt) {
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a matrix
var matrix = myfield.getCTM();
// Read the translate attributes from the matrix into variable x and y
// Below is the desired rightward change
var x = (matrix.e - 2) / matrix.a; // Divide change by current scale to remove exponential movement
var y = matrix.f / matrix.a; // To keep motion only along one axis
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + matrix.a + "," + matrix.d + ") translate(" + x + "," + y + ")");
}
// Pan up function
function panup_click(evt) {
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a matrix
var matrix = myfield.getCTM();
// Read the translate attributes from the matrix into variable x and y
var x = matrix.e / matrix.a ; // Divided by scale to keep motion only along one axis
// Below is the desired upward change
var y = (matrix.f + 2) / matrix.a; // Divide change by current scale to remove exponential movement
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + matrix.a + "," + matrix.d + ") translate(" + x + "," + y + ")");
}
// Pan down function
function pandown_click(evt) {
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a matrix
var matrix = myfield.getCTM();
// Read the translate attributes from the matrix into variable x and y
var x = matrix.e / matrix.a; // Divided by scale to keep motion only along one axis
// Below is the desired downward change
var y = (matrix.f - 2) / matrix.a; // Divide change by current scale to remove exponential movement
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + matrix.a + "," + matrix.d + ") translate(" + x + "," + y + ")");
}
// Zoom in (enlarge) function
function zoomin_click(evt) {
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a matrix
var matrix = myfield.getCTM();
// Read the scale attributes from the matrix into variable x and y
// then apply an increment by multiplying
var x = matrix.a * 1.2;
var y = matrix.d * 1.2;
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + x + "," + y + ") translate(" + matrix.e + "," + matrix.f + ")");
}
// Zoom out (reduce) function
function zoomout_click(evt) {
// variable to get the group transform object
var myfield = null;
myfield = document.getElementById("myfield");
// Incase the group has no Id then get the first '<g>' element
if(myfield === null)
myfield = document.getElementsByTagName('g')[0];
var goIn = evt.target; // thus line is currently not used
// Fetch the current transform state of the group element into a matrix
var matrix = myfield.getCTM();
// Read the scale attributes from the matrix into variable x and y
// then apply a reduction in scale by dividing
var x = matrix.a / 1.2;
var y = matrix.d / 1.2;
// Set the new transform attribute for the group
myfield.setAttributeNS(null,"transform", "scale(" + x + "," + y + ") translate(" + matrix.e + "," + matrix.f + ")");
}
// Recenter/reset function
function recenter_click(evt) {
// Reset the group to the original transform
document.getElementById("myfield").setAttributeNS(null,"transform", "scale(1,1) translate(0,0)");
}
getCTM is the wrong function to use for this purpose. It includes any transforms applied to the parent SVG due to the viewBox etc. You are just wanting to manipulate the transform attribute of the "myfield" group.
I would recommend just manipulating the tranform attribute using the predefined DOM functions.
You access the transform attribute DOM by using:
<myfield DOM object>.transform.baseVal
That returns a SVGTransformList object, which is basically an array containing two SVGTramnsform objects. One for the scale() part, and one for the transform() part. Once you have those objects you can just give them new values, and the SVG will update.
function panup_click(evt) {
pan(0,-2);
}
function pandown_click(evt) {
pan(0,2);
}
function panleft_click(evt) {
pan(-2,0);
}
function panright_click(evt) {
pan(2,0);
}
// Pan function
function pan(dx, dy) {
// variable to get the group transform object
var myfield = document.getElementById("myfield");
// Fetch the current value of the transform attribute
var transformList = myfield.transform.baseVal;
var translate = transformList.getItem(1);
// Adjust the translate transform item
var tx = translate.matrix.e;
var ty = translate.matrix.f;
translate.setTranslate(tx + dx, ty + dy);
}
// Zoom in (enlarge) function
function zoomin_click(evt) {
zoom(1.2);
}
// Zoom out (reduce) function
function zoomout_click(evt) {
zoom(1 / 1.2);
}
function zoom(scaleFactor)
{
// variable to get the group transform object
var myfield = document.getElementById("myfield");
// Fetch the current value of the transform attribute
var transformList = myfield.transform.baseVal;
var scale = transformList.getItem(0);
// Adjust the translate transform item
var s = scale.matrix.a;
scale.setScale(s * scaleFactor, s * scaleFactor);
}
// Recenter/reset function
function recenter_click(evt) {
// Reset the group to the original transform
document.getElementById("myfield").setAttributeNS(null,"transform", "scale(1,1) translate(0,0)");
}
<svg width="24cm" height="16cm" viewBox="-4 -1 26 20"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="myfield" transform="scale(1,1) translate(0,0)" >
<g transform=" scale(1,-1) translate(0,-16)">
<g id="togglefield">
<rect id= "rectangle1" class= "rectangles" x= 2 y= 0 width= 4 height= 6 onClick="fieldDetails(event)"></rect>
<rect id="rectangle2" class= "rectangles" x= 2 y= 6 width= 4 height= 5 onClick="fieldDetails(event)"></rect>
</g>
<g id="togglefind">
<circle class="circles" id="find1" cx= 4 cy= 1 r="0.2" onClick="findDetails(event)"></circle>
<text class="text" x= 4 y= 1 transform="translate(0 2 ) scale(-1,1) rotate(180)"> 1 </text>
<circle class="circles" id="find5" cx= 4 cy= 7 r="0.2" onClick="findDetails(event)"></circle>
<text class="text" x= 4 y= 7 transform="translate(0 14 ) scale(-1,1) rotate(180)"> 5 </text>
</g>
</g>
<rect x="12.6" y="12.4" width="3" height="3" fill="white" stroke="grey" stroke-width="0.05"/>
<text x="13" y="13.2" font-family="Arial" font-size="0.6">Legend</text>
<g id="Fieldlgd">
<rect x="12.8" y="13.6" width="0.6" height="0.6" fill="none" stroke="green" stroke-width="0.04"/>
<text x="13.6" y="14" font-family="Georgia" font-size="0.5">Field ID</text>
<text x="13" y="14" font-family="Georgia" font-size="0.5">1</text>
</g>
<g id="Findlgd">
<circle cx="13.1" cy="14.7" r="0.12" fill="blue" stroke="red" stroke-width="0.05"/>
<text x="13.6" y="14.85" font-family="Georgia" font-size="0.5">Find ID</text>
<text x="13.2" y="14.7" font-family="Arial" font-size="0.45">1</text>
</g>
</g>
<rect x="-4" y="0.3" width="3.2" height="12" fill="white" stroke="black" stroke-width="0" fill-opacity="0.8"/>
<text x="-4" y="0.8" font-family="San Serif" font-size="3%">Pan and Zoom </text>
<text x="-2.7" y="1.8" font-family="Georgia" font-size="4%">N</text>
<polyline id="panup" onclick="panup_click(evt)" points="-3,2 -2.5,1 -2,2 -2.3,1.9 -2.7,1.9 -3,2" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.7" y="3.4" font-family="Georgia" font-size="4%">S</text>
<polyline id="pandown" onclick="pandown_click(evt)" points="-3,2.8 -2.5,3.8 -2,2.8 -2.3,2.9 -2.7,2.9 -3,2.8" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-3.3" y="2.6" font-family="Georgia" font-size="4%">W</text>
<polyline id="panleft" onclick="panleft_click(evt)" points="-2.7,1.9 -3.7,2.4 -2.7,2.9 -2.8,2.6 -2.8,2.2 -2.7,1.9" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.1" y="2.6" font-family="Georgia" font-size="4%">E</text>
<polyline id="panright" onclick="panright_click(evt)" points="-2.3,1.9 -1.3,2.4 -2.3,2.9 -2.2,2.6 -2.2,2.2 -2.3,1.9" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<text x="-2.7" y="2.6" font-family="Georgia" font-size="4%">C</text>
<circle id="recenter" onclick="recenter_click(evt)" cx="-2.5" cy="2.4" r="0.3" fill="lavender" stroke="cornflowerblue" stroke-width="0.05" fill-opacity="0.6"/>
<polyline id="zoomcross" points="-2.6,4.2 -2.4,4.2 -2.4,4.6 -2.1,4.6 -2.1,4.8 -2.4,4.8 -2.4,5.3 -2.6,5.3 -2.6,4.8 -2.9,4.8 -2.9,4.6 -2.6,4.6 -2.6,4.2" fill="cornflowerblue"/>
<rect id="zoomIn" onclick="zoomin_click(evt)" x="-3" y="4" width="1" height="1.5" fill="white" stroke="black" stroke-width="0.05" opacity="0.2"/>
<rect id="zoomdash" x="-2.9" y="5.9" width="0.8" height="0.2" fill="cornflowerblue"/>
<rect id="zoomOut" onclick="zoomout_click(evt)" x="-3" y="5.7" width="1" height="0.6" fill="white" stroke="black" stroke-width="0.05" opacity="0.2"/>
</svg>

Animate svg elements with Javascript and JQuery

I'm trying to animate the following html elements to implement a functionality similar to a volume wheel.
<svg id="circle_svg" width="200" height="175">
<circle cx="100" cy="85" r="75" stroke="black" stroke-width="2" fill="lightgray"/>
<line id="line_alpha" x1="100" y1="85" x2="100" y2="160" style="stroke:rgb(0,0,255);stroke-width:2"/>
<circle id="dot_alpha" cx="100" cy="160" r="10" stroke="black" stroke-width="2" fill="red"/>
</svg>
The basic idea is that clicking on the red dot and moving the mouse around should result in the following behavior:
The red dot moves along the circle (even if mouse doesn't stay exactly on it).
The end point of the line on the circle follows the red dot.
A number shown somewhere else in the page gets incremented or decremented with the amount of angular displacement.
I found a demo online that allows to drag an svg circle all around the page, by binding the elements of interest to mousedown and mouseup events and rewriting the attribute cx and cy of the circle to the current location of the mouse.
However when testing the code on jsfiddle with my example (or even with the original code) something is not working. Could you please take a look and give me advice on what might be going wrong?
Jsfiddle my settings
Jsfiddle original settings
I was able to find the solution to my question (thanks to a friend) and will post it as reference for others:
The main problem with pasting the code from this online demo into jsfiddle is that the order in which JavaScript libraries and functions is not predictable.
So some binding might be called before the binded function is defined.
Also, the code from the demo is more complicated that what I needed.
Here is the code solution on jsfiddle
Below is a working snippet for SO site
var dragging = false
var updateGraphics = function (e) {
if (dragging) {
var parentOffset = $('#wheel').offset();
var relX = e.pageX - parentOffset.left;
var relY = e.pageY - parentOffset.top;
var cx = +$('#circle').attr('cx')
var cy = +$('#circle').attr('cy')
var r = +$('#circle').attr('r')
var dx = relX - cx
var dy = relY - cy
//var dx = e.clientX - cx
//var dy = e.clientY - cy
console.debug('cx: ' + cx);
console.debug('cy: ' + cy);
console.debug('dx: ' + dx);
console.debug('dy: ' + dy);
console.debug('clientX: ' + e.clientX);
console.debug('clientY: ' + e.clientY);
console.debug('relX: ' + relX);
console.debug('relY: ' + relY);
var a = Math.atan2(dy, dx)
var dotX = cx + r * Math.cos(a)
var dotY = cy + r * Math.sin(a)
$('#dot').attr('cx', dotX);
$('#dot').attr('cy', dotY);
$('#line_2').attr('x2', dotX);
$('#line_2').attr('y2', dotY);
}
}
$('svg').on('mousedown', function (e) {
dragging = true
updateGraphics(e)
})
$('svg').on('mouseup', function (e) {
dragging = false
})
$('svg').on('mousemove', updateGraphics)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="wheel" width="200" height="175" style="background-color:lightgreen;">
<circle id="circle" cx="100" cy="85" r="75" stroke="black" stroke-width="2" fill="lightgray"/>
<line id="line_1" x1="100" y1="85" x2="100" y2="160" stroke-dasharray="15,15" style="stroke:rgb(255,0,0);stroke-width:2"/>
<line id="line_2" x1="100" y1="85" x2="100" y2="160" style="stroke:rgb(0,0,255);stroke-width:2"/>
<circle id="dot" cx="100" cy="160" r="10" stroke="black" stroke-width="2" fill="red"/>
</svg>

Changing transform values in SVG with D3.js

I have a couple of 100 text elements in an SVG that come from an external SVG editor and I'd like to change their matrix transform using D3.js. They all have a horizontal scaling of 1.1 and i'd like to change it to 1.05 and put the matrix format into the form "translate(dx,dy)rotate(θ)skewX(φ)scale(kx,ky)". I've looked up on the D3 API to return the transform values but don't know how to change them and put it in the new transform form.
D3.JS API transform
Here's my code
var titles = d3.selectAll(".text-title");
for (i = 0; i < titles.length; i++) {
var titleTransform = d3.select(titles[i]).attr("transform");
var titleScale = d3.transform(titleTransform).scale;
//Change scale to 1.05 but keep the other transform values
}
Here's my svg
<svg>
<text transform="matrix(1.1 0 0 1 10 20)" class="text-title"> FOO </text>
<text transform="matrix(1.1 0 0 1 50 30)" class="text-title">
<tspan x="0" y="0">FOO</tspan>
<tspan x="-1.9" y="15">BAR</tspan>
</text>
<text transform="matrix(1.1 0 0 1 20 80)" class="text-title">
<tspan x="0" y="0">FOO</tspan>
<tspan x="-.2" y="15">BAR</tspan>
</text>
<text transform="matrix(1.1 0 0 1 100 30)" class="text-title"> GRUNGE BAR</text>
<text transform="matrix(1.1 0 0 1 100 50)" class="text-title">
<tspan x="0" y="0">FUNKY</tspan>
<tspan x="4.9" y="15">FOO</tspan>
</text>
</svg>
and a Fiddle
A selection isn't an array you can iterate over but there is an each method which is called on all elements. After that refctoring you can do something like this...
function foo(d, i) {
var titleTransform = d3.transform(d3.select(this).attr("transform"));
//Change scale to 1.05 but keep the other transform values
titleTransform.scale[0] = 1.05
d3.select(this).attr("transform", titleTransform);
}
var titles = d3.selectAll(".text-title").each(foo);
or as a fiddle

Raphael JS Question

I am following a tutorial from netuts about raphael js and I dont understand one of the examples, could some one possibly explain this to me in plainer english. I know I should learn more about javascript first.
for(var i = 0; i < 5; i+=1) {
var multiplier = i*5;
paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier); }
Thanks! Very Much
The code will create five circles
for(var i = 0; i < 5; i+=1) { // loop five times => create five circles
var multiplier = i*5; // multiply i to increase the effect in the next lines
paper.circle( 250 + (2*multiplier), // the x coordinate of the new circle
100 + multiplier, // the y coordinate
50 - multiplier); // the radius
}
Results in this SVG element:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="556" height="109">
<desc>Created with Raphaël</desc>
<defs/>
<circle cx="250" cy="100" r="50" fill="none" stroke="#000"/>
<circle cx="260" cy="105" r="45" fill="none" stroke="#000"/>
<circle cx="270" cy="110" r="40" fill="none" stroke="#000"/>
<circle cx="280" cy="115" r="35" fill="none" stroke="#000"/>
<circle cx="290" cy="120" r="30" fill="none" stroke="#000"/>
</svg>
for(var i = 0; i < 5; i+=1) {
Iterate 5 times. Store the number of times iterated so far in the variable i. The "{" begins the loop.
var multiplier = i * 5;
Multiply i by 5 and store in a variable called multiplier.
paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier);
Draw a circle with an x coordinate at 250 plus twice the multiplier, a y coordinate at 100 plus the multiplier and with a radius of 50 minus the multiplier. (Essentially a fancy way of getting distinct circles.)
}
End the loop.

Categories

Resources