【问题标题】:moving SVG 'g' tag using JavaScript使用 JavaScript 移动 SVG 'g' 标签
【发布时间】:2016-11-16 10:15:20
【问题描述】:

我知道 SVG <g> 标签没有 X 和 Y 属性,传输它的唯一方法是使用 transformtransform="translate(x,y)"transform="rotate(45 50 50)"

我正在尝试使用 JavaScript 执行相同的可编程操作,我想在其中移动具有 recttext 组合的 g 标签,下面是我的代码,所以我犯了什么错误@ 987654329@点击后不移动/翻译?

var NS="http://www.w3.org/2000/svg";     
var SVG=function(h,w){
    var svg=document.createElementNS(NS,"svg");
    svg.width=w;
    svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);

class myRect {
  constructor(x,y,h,w,fill,name) {
   this.g= document.createElementNS(NS,"g");
   this.name=name;
   this.SVGObj= document.createElementNS(NS,"rect");
   self = this.SVGObj;
      self.x.baseVal.value=x;
      self.y.baseVal.value=y;
      self.width.baseVal.value=w;
      self.height.baseVal.value=h;
      self.style.fill=fill;
      
    this.text = document.createElementNS(NS, 'text');
    this.text.setAttribute('x', x+10);
    this.text.setAttribute('y', y+20);
    this.text.setAttribute('fill', '#000');
    this.text.textContent = '2';
    
    this.g.appendChild(self);
    this.g.appendChild(this.text)
    
    this.g.addEventListener("click",this,false);
  }
}

Object.defineProperty(myRect.prototype, "node", {
get: function node() {
    return this.g; // this.SVGObj;
}
});

myRect.prototype.handleEvent= function(evt){
self = this.g;
  switch (evt.type){
    case "click":
       // alert(this.name); // this.animate();    
       if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
       else self.moving = false;
 
     if(self.moving == true)
       self.move = setInterval(()=>this.animate(),100);
       else{
       clearInterval(self.move); 
       self.parentNode.removeChild(self);
       }        
    break;
    default:
    break;
 }
}  

myRect.prototype.animate = function() {
       self = this.g;
       self.transform="translate(200,200)";
       //    self.x.baseVal.value+=1;
       //    self.y.baseVal.value+=1;
};

    var r= new myRect(50,50,30,30,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
    svg.appendChild(r.node);

更新 我尝试了self.setAttribute('transform','translate(10,10)') 但没有用,我只能使用self.setAttribute('transform','translate(10,10)'); 进行一步一次移动,其中 getItem(0) 获取转换属性中的第一个元素,例如transform="translate(1, 1) scale(2)" 其中getItem(0) 得到translate(1, 1) 矩阵,getItem(1) 得到scale(2) 解释here

但这仍然不是我需要的,一旦我点击g 直到循环结束,我需要持续移动。

【问题讨论】:

    标签: javascript svg translate-animation


    【解决方案1】:
    <html>
    
    <body>
    <div class="svg"></div>
    </body>
    <script>
    var NS="http://www.w3.org/2000/svg";     
    var SVG=function(h,w){
        var svg=document.createElementNS(NS,"svg");
        svg.width=w;
        svg.height=h;
    return svg;
    }
    var svg=SVG(1200,1500);
    var div =document.querySelector(".svg");
    div.appendChild(svg);
    
    class myRect {
      constructor(x,y,h,w,fill,name) {
       this.g= document.createElementNS(NS,"g");
       this.name=name;
       this.SVGObj= document.createElementNS(NS,"rect");
       self = this.SVGObj;
          self.x.baseVal.value=x;
          self.y.baseVal.value=y;
          self.width.baseVal.value=w;
          self.height.baseVal.value=h;
          self.style.fill=fill;
    
        this.text = document.createElementNS(NS, 'text');
        this.text.setAttribute('x', x+10);
        this.text.setAttribute('y', y+20);
        this.text.setAttribute('fill', '#000');
        this.text.textContent = '2';
    
        this.g.appendChild(self);
        this.g.appendChild(this.text)
    
        this.g.addEventListener("click",this,false);
      }
    }
    
    Object.defineProperty(myRect.prototype, "node", {
    get: function node() {
        return this.g; // this.SVGObj;
    }
    });
    
    myRect.prototype.handleEvent= function(evt){
    self = this.g;
      switch (evt.type){
        case "click":
           // alert(this.name); // this.animate();    
           if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
           else self.moving = false;
    
         if(self.moving == true)
           self.move = setInterval(()=>this.animate(evt),100);
           else{
           clearInterval(self.move); 
           self.parentNode.removeChild(self);
           }        
        break;
        default:
        break;
     }
    }  
    
    myRect.prototype.animate = function(evt) {
           self = this.g;
           var recElement=self.childNodes[0];
           recElement.setAttribute("x",10);
           recElement.setAttribute("y",10);
           //self.transform="translate(200,200)";
    
    };
    
        var r= new myRect(50,50,30,30,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
        svg.appendChild(r.node);
    
    
        </script>
    

    【讨论】:

    • 你能试试这个吗,但我假设只有一个 g 标签。
    • 对不起@Ray,这个self.childNodes[0]; 使g 中的第一个元素移动,而不是完整的g 标签,只有rect 元素在移动,而text元素保持不动,即您正在移动g 的子元素
    【解决方案2】:

    感谢Mike Williamson,我能够通过开发海关转换功能解决它:

    myRect.prototype.step = function(x,y) {
      return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
    }
    

    并通过以下方式调用它:

    myRect.prototype.animate = function() {
       self = this.g;
       self.transform.baseVal.appendItem(this.step(1,1));
    };
    

    对于任何感兴趣的人来说,完整的代码是:

    var NS="http://www.w3.org/2000/svg";  
    var SVG=function(el){
       return document.createElementNS(NS,el);
    }
    
    var svg = SVG("svg");
        svg.width='100%';
        svg.height='100%';
    document.body.appendChild(svg);
    
    class myRect {
         constructor(x,y,h,w,fill,name) {
         this.g= SVG("g");
         this.name=name;
         this.SVGObj= SVG('rect'); // document.createElementNS(NS,"rect");
            self = this.SVGObj;
            self.x.baseVal.value=x;
            self.y.baseVal.value=y;
            self.width.baseVal.value=w;
            self.height.baseVal.value=h;
            self.style.fill=fill;
            self.onclick="click(evt)";
    
    this.text = SVG('text');
    this.text.setAttribute('x', x+10);
    this.text.setAttribute('y', y+20);
    this.text.setAttribute('fill', '#000');
    this.text.textContent = name;
    
    this.g.appendChild(self);
    // this.g.appendChild(this.text); // if required to be loaded from start up
    
    this.g.addEventListener("click",this,false);
    //(e)=>alert(e.target.parentNode.parentNode); / this is to check what is clicked
      }
    }
    
    Object.defineProperty(myRect.prototype, "node", {
       get: ()=> return this.g;
    });
    
    myRect.prototype.handleEvent= function(evt){
      self = evt.target.parentNode;  // this returns the `g` element
      switch (evt.type){
          case "click":   
              if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
              else self.moving = false;
    
     if(self.moving == true){
     self.move = setInterval(()=>this.animate(),100);
     self.appendChild(this.text); // show the text node
    
     }
    
      else{
       clearInterval(self.move);
       self.removeChild(self.childNodes[1]); // remove the text node
     //  self.parentNode.removeChild(self);  // This removes the `g` element completly
      }        
    break;
       default:
       break;
     }
    }  
    
     myRect.prototype.step = function(x,y) {
        return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
     }
    
     myRect.prototype.animate = function() {
       self = this.g;
       self.transform.baseVal.appendItem(this.step(1,1));
     };
    
     for (var i = 0; i < 10; i++) {
       var x = Math.random() * 100,
           y = Math.random() * 300;
      var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'click to stop');
       svg.appendChild(r.node);
      }
    

    也可以通过JSFiddle获得

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 2021-08-19
      相关资源
      最近更新 更多