Quiero implementar la funcionalidad como svg-edit en rectángulo elemento

  1. Rotar el rectángulo
  2. Cambio de tamaño de
  3. Arrastre

La rotación de la SVG rectángulo funciona bien, pero cuando quiero cambiar el tamaño del rectángulo que tiene un problema. Las coordenadas no están funcionando bien; yo uso la transformación de la matriz a girar
targetelement.setAttribute(transform,rotate(45,cx,cy))
pero cuando el elemento ha sido girado las coordenadas se mueven. También estoy usando inverse función inversa de la transformación de la matriz se resuelve el problema, pero no su trabajo con la función de arrastre.

InformationsquelleAutor Abdul Rauf | 2011-01-31

2 Comentarios

  1. 100

    He creado un ejemplo de lo que yo creo que usted está describiendo en mi sitio aquí:

    http://phrogz.net/svg/drag_under_transformation.xhtml

    En general, de convertir el cursor del ratón en el espacio local de un objeto:

    1. La creación de un mousemove controlador de eventos:

      var svg = document.getElementsByTagName('svg')[0];
      document.documentElement.addEventListener('mousemove',function(evt){
        ...
      },false);
    2. En el manejador del evento, convertir las coordenadas del ratón (en píxeles) en el espacio global de su documento SVG:

      var pt = svg.createSVGPoint();
      pt.x = evt.clientX;
      pt.y = evt.clientY;
      var globalPoint = pt.matrixTransform(svg.getScreenCTM().inverse());
    3. Convertir el global en el espacio del objeto que se arrastra:

      var globalToLocal = dragObject.getTransformToElement(svg).inverse();
      var inObjectSpace = globalPoint.matrixTransform( globalToLocal );

    Por Desbordamiento de la Pila de la posteridad, aquí está el código fuente completo de mi SVG+XHTML demo (en caso de que mi sitio está abajo):

    <!DOCTYPE HTML>
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> 
    <meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/>
    <title>Dragging Transformed SVG Elements</title>
    <style type="text/css" media="screen">
      html, body {
        background:#eee; margin:0;
        user-select:none; -moz-user-select:none; -webkit-user-select:none;
      }
      p { margin:0.5em; text-align:center }
      svg {
        position:absolute; top:5%; left:5%; width:90%; height:90%;
        background:#fff; border:1px solid #ccc
      }
      svg rect { stroke:#333 }
      svg .drag { cursor:move }
      svg .sizer { opacity:0.3; fill:#ff0; stroke:#630;}
      #footer {
        position:absolute; bottom:0.5em; margin-bottom:0;
        width:40em; margin-left:-20em; left:50%; color:#666;
        font-style:italic; font-size:85%
      }
      #dragcatch { position:absolute; left:0; right:0; top:0; bottom:0; z-index:-1}
    </style>
    </head><body>
    <p>Showing how to drag points inside a transformation hierarchy.</p>
    <svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full">
      <g transform="scale(1.2,0.8)">
        <rect transform="translate(50,20) rotate(30)"
         class="drag resize" x="50" y="30" width="50" height="30" fill="#69c" />
        <rect class="drag resize" x="5" y="5" width="90" height="50" fill="#c66" />
      </g>
    </svg>
    <p id="footer">
      Copyright © 2011 <a href="mailto:[email protected]">Gavin Kistner</a>. 
      Comments/criticisms welcome.
    </p>
    <script type="text/javascript"><![CDATA[
      var svg   = document.getElementsByTagName('svg')[0];
      var svgNS = svg.getAttribute('xmlns');
      var pt    = svg.createSVGPoint();
    
      function createOn(root,name,prop){
        var el = document.createElementNS(svgNS,name);
        for (var a in prop) if (prop.hasOwnProperty(a)) el.setAttribute(a,prop[a]);
        return root.appendChild(el);
      }
    
      function rectCorner(rect){
        pt.x = rect.x.animVal.value + rect.width.animVal.value;
        pt.y = rect.y.animVal.value + rect.height.animVal.value;
        return pt.matrixTransform(rect.getTransformToElement(svg));
      }
    
      function pointIn(el,x,y){
        pt.x = x; pt.y = y;
        return pt.matrixTransform(el.getTransformToElement(svg).inverse());
      }
    
      function cursorPoint(evt){
        pt.x = evt.clientX; pt.y = evt.clientY;
        return pt.matrixTransform(svg.getScreenCTM().inverse());
      }
    
      //Make all rects resizable before drag, so the drag handles become drag
      for (var a=svg.querySelectorAll('rect.resize'),i=0,len=a.length;i<len;++i){
        (function(rect){
          var dot = createOn(svg,'circle',{'class':'drag sizer',cx:0,cy:0,r:5});
          var moveDotToRect = function(){
            var corner = rectCorner(rect);
            dot.setAttribute('cx',corner.x);
            dot.setAttribute('cy',corner.y);
          }
          moveDotToRect();
          rect.addEventListener('dragged',moveDotToRect,false);
          dot.addEventListener('dragged',function(){
            var rectXY = pointIn(rect,dot.cx.animVal.value,dot.cy.animVal.value);
            var w = Math.max( rectXY.x-rect.x.animVal.value, 1 );
            var h = Math.max( rectXY.y-rect.y.animVal.value, 1 );
            rect.setAttribute('width', w);
            rect.setAttribute('height',h);
          },false);
        })(a[i]);
      }
    
      for (var a=svg.querySelectorAll('.drag'),i=0,len=a.length;i<len;++i){
        (function(el){
          var onmove; //make inner closure available for unregistration
          el.addEventListener('mousedown',function(e){
            el.parentNode.appendChild(el); //move to top
            var x = el.tagName=='circle' ? 'cx' : 'x';
            var y = el.tagName=='circle' ? 'cy' : 'y';
            var mouseStart   = cursorPoint(e);
            var elementStart = { x:el[x].animVal.value, y:el[y].animVal.value };
            onmove = function(e){
              var current = cursorPoint(e);
              pt.x = current.x - mouseStart.x;
              pt.y = current.y - mouseStart.y;
              var m = el.getTransformToElement(svg).inverse();
              m.e = m.f = 0;
              pt = pt.matrixTransform(m);
              el.setAttribute(x,elementStart.x+pt.x);
              el.setAttribute(y,elementStart.y+pt.y);
              var dragEvent = document.createEvent("Event");
              dragEvent.initEvent("dragged", true, true);
              el.dispatchEvent(dragEvent);
            };
            document.body.addEventListener('mousemove',onmove,false);
          },false);
          document.body.addEventListener('mouseup',function(){
            document.body.removeEventListener('mousemove',onmove,false);
          },false);
        })(a[i]);
      }
    ]]></script>
    <div id="dragcatch"></div>
    </body></html>
    • gracias phrogz…. después de la rotación quiero cambiar el tamaño del rectángulo de nuevo como svg-edit….creo que mi rectángulo de coordenadas es cambiado cuando me gire
    • Gracias por el código. Yo estaba teniendo problemas para averiguar cómo obtener la transformación de valor sin usar getAttribute, pero luego vi la getTransformToElement() método en el código. Saludos. 🙂
    • Limpio, simple, funciona. Con tan pobres svg documentación en la web esta respuesta realmente se destaca.
    • Wow, gracias por esto!
    • Muy impresionante, Phrogz. No hay suficientes buenos ejemplos en la construcción gráfica de las herramientas de manipulación usando SVG, que me imagino que es una forma bastante común de casos de uso. @AbdulRauf, puede usted aceptar esta respuesta?
    • Gracias! Tenga en cuenta que Abdul fue visto por última vez en S/S más de 2,5 años, así que parece poco probable que s/él se dará cuenta de su solicitud. 😀
    • ¿Dónde se encuentra la información acerca de getScreenCTM y getCTM? No puedo encontrarlos en el SVG TR o similar, también de la búsqueda de enginges volver muy pocos resultados. Son los estandarizados de las funciones, es decir, ¿podemos confiar en los navegadores de la aplicación de ellos?
    • Ellos son parte de la SVG 1.1 especificaciones, y están bien soportados. Ver: w3.org/TR/SVG11/types.html#__svg__SVGLocatable__getCTM
    • Muchas gracias! He buscado en el lugar equivocado secciones.
    • jsfiddle: jsfiddle.net/84jg7Lpg
    • Gracias por la respuesta, Aquí es muy simple, violín para coordinar la conversión del sistema. jsfiddle.net/milindaaruna/vu2rvz81/1
    • FYI el ejemplo es en la actualidad tirar un error en Chrome: drag_under_transformation.xhtml:56Uncaught TypeError: rect.getTransformToElement no es una función
    • Esto es fantástico. Gracias! Por curiosidad, ¿cuál es la dragcatch div para?

  2. 1

    Para los que usan Chrome por favor, agregue las siguientes líneas después de

    var pt    = svg.createSVGPoint();
    
    SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) {
      return elem.getScreenCTM().inverse().multiply(this.getScreenCTM());
    };

    Más info aquí: https://github.com/cpettitt/dagre-d3/issues/202

    • Esto no contesta a la pregunta original.
    • Sí, pero la respuesta no funciona en el navegador Crome sin él!
    • Las respuestas deben responder a la pregunta, esto es un comentario existente en una respuesta que no está permitido aquí. Una vez que usted tiene 50 rep usted puede agregar un comentario a la respuesta existente.

Dejar respuesta

Please enter your comment!
Please enter your name here