10

Co próbuję zrobić jest prosta: przeskaluj niektóre kropki SVG z scale(0) do scale(1), gdy element rodzeństwa jest ujęty za pomocą jamy waniliowej. Są to czerwone w the demoSkala SVG bez ruchomej lokalizacji

Oto podstawowa konfiguracja SVG

<?xml version="1.0" encoding="utf-8" ?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
     x="0px" y="0px" viewBox="0 0 720 576" style="enable-background:new 0 0 720 576;" xml:space="preserve"> 
    <style type="text/css"> 
     .st3 { 
      fill:red; 
     } 
     * { 
      -webkit-transition:.3s; 
      transition:.3s; 
     } 
    </style> 
    <g id="Layer_4"> 
     <!-- Shield --> 
     <path class="st8" d="M601,304.7c-32.4-15.4-68.6-24-106.8-24c-40.4,0-78.5,9.6-112.3,26.6c4.9,79.7,41.9,146.7,109.5,187.6 
      C559.8,454.1,597,385.6,601,304.7z" /> 
     <path class="st9" d="M420.1,328.7c2.1-4.7,32.5-23.9,72.5-23.9c39.9,0,73.1,20,75.5,24.3c2.4,4.3,5.7,40-12.7,74.6 
       c-19.7,36.9-53.5,50.1-61.8,50.4c-6.4,0.2-41.8-14.3-62.5-51.6C411.5,367.4,418,333.4,420.1,328.7z" /> 
     <circle class="st10" cx="494.9" cy="373.3" r="35.5" /> 
    </g> 
    <g id="Layer_8"> 
     <!-- Dots on shield --> 
     <circle class="st3" cx="578.8" cy="316.2" r="4.6" /> 
     <circle class="st3" cx="543.4" cy="346.2" r="4.6" /> 
     <circle class="st3" cx="505" cy="375.5" r="4.6" /> 
    </g> 
</svg> 

Kwestia jest to, że waga SVG oparte na lokalizacji pochodzenia, a nie bieżącej lokalizacji, więc podczas transformacji nanosi się porusza element oprócz skalowania go. Próbuję naprawić tę sytuację, tłumacząc ją przez przesunięcie, skalowanie, a następnie tłumaczenie, ale to tylko pomogło i nie całkowicie rozwiązało problem.

var shield = document.getElementById("Layer_4"), 
    dots = document.querySelectorAll("#Layer_8 .st3"); 

toggleTransform(false); 

shield.onmouseover = function() { toggleTransform(true); } 
shield.onmouseout = function() { toggleTransform(false); } 

function toggleTransform(bool) { 
    if (!bool) { 
     for (var i = 0; i < dots.length; i++) { 
      var box = dots[i].getBBox(), 
       cx = box.x + box.width/10, 
       cy = box.y + box.height/10; 
      //dots[i].setAttribute("transform", "translate(" + cx + " " + cy + ") scale(0) translate(" + cx + " " + cy + ")"); 
      dots[i].style.WebkitTransform = "translate(" + cx + "px, " + cy + "px) scale(0) translate(" + -cx + "px, " + -cy + "px)"; 
     } 
    } else { 
     for (var i = 0; i < dots.length; i++) { 
      var box = dots[i].getBBox(), 
       cx = box.x + box.width/2, 
       cy = box.y + box.height/2; 
      //dots[i].setAttribute("transform", "translate(0 0) scale(1) translate(0 0)"); 
      dots[i].style.WebkitTransform = "translate(0, 0) scale(1) translate(0, 0)"; 
     } 
    } 
} 

Próbowałem przy użyciu zarówno setAttribute i CSS na transformacji (nie mogłem dostać setAttribute przejście, przypuszczalnie dlatego, że nie jest animatable przez CSS), ale nie mógł się go z innym. Testowałem tylko w Chrome

Ktoś ma pomysł, w jaki sposób mogę przeskalować, a nie poruszać się, czerwone kropki?

Here's the demo ponownie jeśli brakowało mu

Edit

Zrobiłem funkcję w oparciu o odpowiedzi RashFlash do sprawiają, że dość proste w użyciu, a także bierze pod offsetu konta i różne przekształcenia początki

function scaleMe(elem, scaleX, scaleY, newOffsetX, newOffsetY, originX, originY) { 
    newOffsetX = null ? 0 : newOffsetX; 
    newOffsetY = null ? 0 : newOffsetY; 
    originX = null ? "center" : originX; 
    originY = null ? "center" : originY; 

    var bbox = elem.getBBox(), 
     cx = bbox.x + (bbox.width/2), 
     cy = bbox.y + (bbox.height/2),   
     tx = -cx * (scaleX - 1) + newOffsetX, 
     ty = -cy * (scaleY - 1) + newOffsetY;   

    if(originX === "left" || originX === "right") { 
     tx = newOffsetX; 
    } 
    if(originY === "top" || originY === "bottom") { 
     ty = newOffsetY; 
    } 

    var scalestr = scaleX + ',' + scaleY, 
     translatestr = tx + 'px,' + ty + 'px'; 

    elem.style.WebkitTransformOrigin = originX + " " + originY; 
    elem.style.MozTransformOrigin = originX + " " + originY; 
    elem.style.msTransformOrigin = originX + " " + originY; 
    elem.style.transformOrigin = originX + " " + originY; 

    elem.style.WebkitTransform = "translate(" + translatestr + ") scale(" + scalestr + ")"; 
    elem.style.MozTransform = "translate(" + translatestr + ") scale(" + scalestr + ")"; 
    elem.style.msTransform = "translate(" + translatestr + ") scale(" + scalestr + ")"; 
    elem.style.transform = "translate(" + translatestr + ") scale(" + scalestr + ")"; 
} 
+0

To naprawdę nie jest jasne, co chcesz się zdarzyć. Czy chcesz, aby każda z czerwonych kropek powiększyła się po najechaniu kursorem myszy? –

+0

@BigBadaboom Tak, chcę przeskalować czerwone kropki na myszy bez przenoszenia ich z dowolnego miejsca - po prostu się powiększ –

Odpowiedz

7

Jeśli się nie mylę, chcesz przeskalować kropki wzdłuż ich środka, kropki pozostają w aktualnej pozycji i po prostu stają się większe.

jeśli tego chcesz, to poniższy kod pomoże

var bbox=elementNode.getBBox(); 
var cx=bbox.x+(bbox.width/2), 
    cy=bbox.y+(bbox.height/2); // finding center of element 
var scalex=1.5, scaley=1.5; // your desired scale 
var saclestr=scalex+','+scaley; 
var tx=-cx*(scalex-1); 
var ty=-cy*(scaley-1);       
var translatestr=tx+','+ty; 

elementNode.setAttribute('transform','translate('+translatestr+') scale('+saclestr+')'); 

Więc co zrobiłem, najpierw przetłumaczyć kropkę i niż skalować. ja używać poniższego wzoru, jak to opisano w Transforming Coordinate system

translate(-centerX*(factor-1), -centerY*(factor-1)) 
scale(factor) 
+1

Dzięki za pomoc! Użycie tej matematyki i użycie transformacji CSS zachowało przejście. [** Demo robocze **] (http://jsbin.com/vefahide/2/edit) (tylko webkit) –

11

można rzeczywiście osiągnąć ten efekt bez JS.

.st3 { 
    fill: red; 
    -webkit-transform: scale(1); 
    -webkit-transform-origin: 50% 50%; 
    -webkit-transition:.3s; 
    transform: scale(1); 
    transform-origin: 50% 50%; 
    transition:.3s; 
} 

#Layer_4:hover + g .st3 { 
    -webkit-transform: scale(2); 
    -webkit-transform-origin: 50% 50%; 
    -webkit-transition:.3s; 
    transform: scale(2); 
    transform-origin: 50% 50%; 
    transition:.3s; 
} 

Demo here