SVG Pan и Zoom не работает

297
19 октября 2018, 05:10

При попытке реализовать Pan и Zoom для двух прямоугольников, не могу заставить это работать.

Я добавил свой код javascript и использовал идентификатор группы для элементов, чтобы попытаться панорамировать и масштабировать, основываясь на моём js, но он еще не работает.

// 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)");  
<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>

Answer 1

getCTM - неподходящая функция для этой цели. Она включает любые преобразования, применяемые к родительскому SVG из-за viewBox и т.д. Вы просто хотите манипулировать атрибутом transform в группе myfield.

Я бы рекомендовал просто манипулировать атрибутом преобразования с помощью предопределенных функций DOM.

Вы получаете доступ к атрибуту DOM transform, используя:

<myfield DOM object>.transform.baseVal

Это возвращает объект SVGTransformList, который в основном представляет собой массив, содержащий два объекта SVGTramnsform. Один объект для части scale(), а другой для части transform().

Когда у вас есть эти объекты, вы можете просто присвоить им новые значения, и SVG будет обновляться.

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>

READ ALSO
Вывод из массива js

Вывод из массива js

В массиве 15 именКак вывести циклом for c седьмого по десятое имя

235
Как выполнить alert() в последнюю очередь?

Как выполнить alert() в последнюю очередь?

Есть вот такая функция, при её выполнении сначала выводится модальное окно, и только потом воспроизводиться аудиоНужно, чтоб сначала воспроизводилось...

203
Как сделать заполнение border кнопки slick слайдера при клике?

Как сделать заполнение border кнопки slick слайдера при клике?

При каждом клике бордер кнопки должен постепенно заполняться те когда будет достигнут последний слайд, у кнопки будет полный бордер вокруг

242
Ошибка в JavaScript+Jquery.js

Ошибка в JavaScript+Jquery.js

Как исправить подобную ошибку?

193