0

I've been trying to rotate some gears in an svg image clockwise repeatedly using D3.js but I can't seem to understand what's wrong with the code or the image. I was able to translate and rotate each gear using this code below...

d3.selectAll(".st6")
  .transition()
  .delay(function(d, i, n) { return i * 50; })
  .on("start", function repeat() {
      d3.active(this)
        .transition()
        .duration(2500)
        .attr('transform', 'rotate(0)')
        .transition() //And rotate back again
        .duration(2500)
        .attr('transform' , 'rotate(90) ')
        .on("start", repeat); //at end, call it again to create infinite loop
  });

But when I tried using the same code that did rotate a text repeatedly for me, the image became static and not moving again...

here is the code that rotate a text repeatedly for me...

var width = 600;
var height = 300;
    
var holder = d3.select("body")
.append("svg")
.attr("width", width)    
.attr("height", height); 
    
//draw the text
holder.append("text")
  .style("fill", "black")
  .style("font-size", "56px")
  .attr("dy", ".35em")
  .attr("text-anchor", "middle")
  .attr("transform", "translate(300,150) rotate(0)")
  .text("Hi, how r u doing");
    
var i = 0;
var timeInterval = 10;
setInterval(function(){
    i += 1;
    update(i % 360) 
}, timeInterval);
    
var n;
// update the element
function update(n) {
    // rotate the text
    holder.select("text")
      .attr("transform", "translate(300,150) rotate("+n+")");
}

Here is what I tried replicating the above method but to no avail...

var width = 600;
var height = 300;
    
var holder = d3.select("body")
  .append("svg")
  .attr("width", width)    
  .attr("height", height); 
    
holder.append("svg:image")
  .attr("image-anchor", "middle")
  .attr("xlink:href", "produc.svg")
  .attr("transform", "translate(300,150) rotate(0)")
// Initial starting angle of the text
    
var i = 0;
var timeInterval = 10;
setInterval(function(){
    i += 1;
    update(i % 360) 
},timeInterval);
    
    
var n;
// update the element
function update(n) {
    // rotate the text
    holder.select("text")
      .attr("transform", "translate(300,150) rotate("+n+")");
}

Here is a working example on CodePenclick here

Paul
  • 4,160
  • 3
  • 30
  • 56
DevLayi
  • 55
  • 10
  • In your update function you haven't updated this line `holder.select("text")` - are you trying to rotate a text element or an image? – Andrew Reid Nov 30 '20 at 01:19
  • I'm trying to rotate the image but I'm not really sure what is the correct thing to put there. – DevLayi Nov 30 '20 at 07:56
  • Please turn your code into a runnable [mre], so we can debug it and provide you with better answers. You can use runnable stack snippets, or an external jsFiddle/Codepen. – Ruben Helsloot Nov 30 '20 at 07:59
  • Okay. I'll do that rightaway. – DevLayi Nov 30 '20 at 08:01
  • Kindly check the question for the codepen link – DevLayi Nov 30 '20 at 09:17
  • I think you're using a sledgehammer to crack a nut. You could probably get away with simple CSS. [Take a look at this Q/A](https://stackoverflow.com/questions/15138801/rotate-rectangle-around-its-own-center-in-svg). – Paul Nov 30 '20 at 09:26
  • My problem is rotating the gears continously – DevLayi Nov 30 '20 at 09:28
  • Then, [try this](https://stackoverflow.com/questions/5309085/how-to-specify-the-x-y-rotation-point-when-using-animatetransform). I'm sure that a quick search would help you, here, or you could try referring to the [Mozilla reference](https://developer.mozilla.org/en-US/docs/Web/SVG/Element). D3.js, though, is overkill. – Paul Nov 30 '20 at 09:34
  • ...especially as you've entered most of the code you're going to use in the attributes! – Paul Nov 30 '20 at 09:35

1 Answers1

1

As for the problem with your code (without considering if it is "a sledgehammer to crack a nut"):

You're taking working code that rotates text and not fully updating it to reflect that you are now working with an image. You have updated the append statement to append an image, but you haven't updated the update function to select that image - it's still looking for a text element:

function update(n) {
    // rotate the text
    holder.select("text")
      .attr("transform", "translate(300,150) rotate("+n+")");
}

Since there is no longer a text element, this function doesn't select anything and consequently, doesn't set any element's transform. AS noted in the comment you need to select the image:

function update(n) {
    // rotate the text
    holder.select("image")
      .attr("transform", "translate(300,150) rotate("+n+")");
}

As seen below:

var width = 600;
var height = 300;
    
var holder = d3.select("body")
  .append("svg")
  .attr("width", width)    
  .attr("height", height); 
    
holder.append("svg:image")
  .attr("image-anchor", "middle")
  .attr("xlink:href", "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/compass.svg")
  .attr("transform", "translate(200,20) rotate(0)")
  .attr("width", 100)
// Initial starting angle of the text
    
var i = 0;
var timeInterval = 10;
setInterval(function(){
    i += 1;
    update(i % 360) 
},timeInterval);
    
// update the element
function update(n) {
    // rotate the text
    holder.select("image")
      .attr("transform", "translate(200,20) rotate("+n+",50,50)");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Andrew Reid
  • 37,021
  • 7
  • 64
  • 83
  • Thanks. This works by rotating the image but still doesn't rotate it at a fixed point. I want the image to stay fixed at a point while the gears/teeth rotate as if you're spinning a bicycle tyre at a spot – DevLayi Dec 01 '20 at 21:14
  • @DevLayi, You can rotate around a point, specified as the second and third parameters of `rotate()` the image I used has a width/height of 100pixels, so `rotate(degrees,50,50)` will work here. Added that to the answer snippet. – Andrew Reid Dec 01 '20 at 21:21