Search code examples
javascriptsvgrotationsvg-animate

JavaScript rotate a SVG object around specific point `transform: rotate()`


I've the below code that is functioning properly, create the path, and rotate it upon the click.

I want to rotate the path about specific point, when i use the rotate(45 50 50) below instead of the rotate(x) i get this error: VM267:85 Uncaught SyntaxError: missing ) after argument list what shall I do?

Note NOt interested to use any ready library to handle the task, need to so it using the standard API only. thanks

var NS="http://www.w3.org/2000/svg";  
var SVG=function(el){
    return document.createElementNS(NS,el);
}
 
 svg = SVG('svg');
  svg.setAttribute("width", "100%");
  svg.setAttribute("height", "100%");
 //   svg.width='50em';  // Not working
document.body.appendChild(svg);
var bbox = svg.getBoundingClientRect();
     var center = {
          x: bbox.left + bbox.width/2,
          y: bbox.top  + bbox.height/2
     };

class myPath {
     constructor(cx,cy) {
     this.path=SVG('path');
   //  https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
   //  https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
     var d="M" + cx + " " + cy; 

     d = d + "L175 120 L125 120 Z";
     this.path.setAttribute("d", d);
     this.path.setAttribute("fill", "#F7931E");
     this.path.addEventListener("click",this,false);
   }
   get draw(){
       return this.path;
   }
 }
 
 myPath.prototype.rotate = function(x) {
 /*
   var path = this.path.getBoundingClientRect();
     var Pc = {
          x: bbox.left + bbox.width/2,
          y: bbox.top  + bbox.height/2
     };  */
   return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().rotate(x));
   // https://developer.mozilla.org/en/docs/Web/SVG/Attribute/transform
}

myPath.prototype.animate = function() {
       self = this.path;
       self.transform.baseVal.appendItem(this.rotate(5));
};

 myPath.prototype.handleEvent= function(evt){
  self = evt.target;  
  console.log(self.getAttribute('d'));
     
 self.move = setInterval(()=>this.animate(),100);
       
}

svg.appendChild(new myPath(center.x,center.y).draw);


Solution

  • I was able to solve it using translate(<x>, <y>) rotate(<a>) translate(-<x>, -<y>) as per this link

    var NS="http://www.w3.org/2000/svg";  
    var SVG=function(el){
        return document.createElementNS(NS,el);
    }
     
     svg = SVG('svg');
      svg.setAttribute("width", "100%");
      svg.setAttribute("height", "100%");
      svg.setAttribute("fill", "green");
    document.body.appendChild(svg);
    bbox = svg.getBoundingClientRect();
    center = {
              x: this.bbox.left + this.bbox.width/2,
              y: this.bbox.top  + this.bbox.height/2
         };
    
    class myPath {
         constructor(cx,cy) {
         this.path=SVG('path');
       //  https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
       //  https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
         var d="M" + cx + " " + cy; 
    
         d = d + "h75 v75 h-75 z";
         this.path.setAttribute("d", d);
         this.path.setAttribute("fill", "#F7931E");
         this.path.addEventListener("click",this,false);
    
         this.Pbox = svg.getBoundingClientRect();
         this.Pc = {
              x: this.Pbox.left + this.Pbox.width/2,
              y: this.Pbox.top  + this.Pbox.height/2
         };
       }
       get draw(){
           return this.path;
       }
     }
     
     myPath.prototype.rotate = function(x) {
       return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().rotate(x));
       // https://developer.mozilla.org/en/docs/Web/SVG/Attribute/transform
    }
    
     myPath.prototype.move = function(x,y) {
       return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
       // https://developer.mozilla.org/en/docs/Web/SVG/Attribute/transform
    }
    
    myPath.prototype.animate = function() {
           self = this.path;
                self.transform.baseVal.appendItem(this.move(this.Pc.x,this.Pc.y));
                self.transform.baseVal.appendItem(this.rotate(5));
                self.transform.baseVal.appendItem(this.move(-this.Pc.x,-this.Pc.y));
    };
    
     myPath.prototype.handleEvent= function(evt){
      self = evt.target;  
      console.log(self.getAttribute('d'));
         
     self.move = setInterval(()=>this.animate(),100);
           
    }
    
    svg.appendChild(new myPath(center.x,center.y).draw);