10

Was ich versuche zu tun ist einfach: Skalieren Sie einige SVG-Punkte von scale(0) bis scale(1), wenn ein Geschwisterelement mit Vanille js schwebt. Sie sind die roten in the demoSVG Scale ohne beweglichen Ort

Hier ist der Grund SVG Setup

<?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> 

Das Problem ist, dass SVG Skalen auf der Grundlage der Herkunft Standort, nicht die aktuelle Position, wenn damit eine Transformation angewendet wird, bewegt er sich das Element zusätzlich zu skalieren. Ich versuche, diese Situation zu beheben, indem ich den Offset, die Skalierung und dann die Übersetzung zurückübersetze, aber das schien nur zu helfen und das Problem nicht vollständig zu beheben.

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

Ich habe versucht, sowohl setAttribute mit und CSS-Transformation von (I nicht setAttribute bekommen konnte vermutlich übergehen, da sie von der CSS nicht animierbar sind), aber kann es nicht mit entweder bekommen. Ich habe nur in Chrome getestet

Jeder eine Idee, wie ich skalieren kann, während sich nicht bewegt, rote Punkte?

Here's the demo wieder, wenn Sie es

bearbeiten

verpasst

habe ich eine Funktion basierend auf RashFlash Antwort es ganz einfach zu machen, zu bedienen und berücksichtigt auch Versetzungen und andere Transformations Ursprüngen

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

Es ist nicht wirklich klar, was Sie wollen passieren. Möchtest du, dass jeder der roten Punkte beim Mouseover größer wird? –

+0

@BigBadaboom Ja, ich möchte die roten Punkte auf der Maus skalieren, ohne dass sie von irgendwoher kommen - werde einfach größer –

Antwort

7

Wenn ich nicht falsch liege, möchten Sie die Punkte entlang ihrer Mitte skalieren, Punkte bleiben ihre aktuelle Position und werden nur größer.

wenn dies Sie wollen, dann folgenden Code wird Ihnen helfen,

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+')'); 

Also, was ich tat, ich zuerst den Punkt übersetzen und als es skalieren. Ich benutze folgende Formel, wie in Transforming Coordinate system

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

Danke für deine Hilfe! Wenn Sie diese Mathematik verwenden und stattdessen eine CSS-Transformation verwenden, behalten Sie den Übergang bei. [** Arbeitsdemo **] (http://jsbin.com/vefahide/2/edit) (nur Webkit) –

11

beschrieben wurden, können Sie tatsächlich diesen Effekt ohne JS erreichen.

.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