Parent css transform affecting d3.mouse points - javascript

I'm using a third library that is adding 'transform: translate3d(200,0,0);' to a parent element. So the elements within the svg tend to move to the right. For drag&drop events, setting the origin is enough, but I'm having troubles to get corrected the d3.mouse(this).
I have created a jsfiddle of this example: http://bl.ocks.org/hlucasfranca/f133da4493553963e710
jsFiddle: https://jsfiddle.net/rahpuser/5jp6123u/
So, when clicking without applying the transform to the parent, everything is ok, but when the parent has the transform, d3.mouse returns a wrong number
var coords = d3.mouse(this);
coords[0] === 100; //true without transform..
coords[0] === 300; // true when the transform to the parent is applied.
// the values are not precise but you can verify the behavior in the jsfiddle
Why d3.mouse(this) is not able to get the correct value ?
my understanding is that d3.mouse should get the coords based on the container this ( svg ).
What should I do to fix the behavior keeping the parent with the new transform?
Thanks.
UPDATE:
Not working in Firefox 46 for ubuntu
Working well in chrome and opera

As you've discovered, this is a known FireFox bug. Even if you did fix FireFox, it's going to take some time to propagate, and it'll never be backwards-fixed. So you still need a workaround.
One thing you can do — as long as the SVG's top-left is always at the 0,0 coordinate of its containing div (as is the case with your jsFiddle) — is replace the call to d3.mouse(this) with:
d3.mouse(this.parentNode)
That'll get the mouse coordinate from the parent of the SVG, which is a normal div, so apparently it's not affected by this bug and will get you the value you want on all platforms.
This does not address the root problem (for example getClientBoundingRect would still return the wrong values), but it works around your specific problem.

Related

d3.mouse pixel offset in Firefox

I visualize some data on a timeline. On mousemove I’d like to show a line and the current hovered time. It works as expected in Chrome and Safari but in Firefox (tested in 44 & 45) there is an offset: The returned pixel value is always lacking half the width of the whole SVG.
E.g., when hovering the left side of the visualization, I expect the value of d3.mouse to equal 0, but it is -300.
See this test case on Codepen: http://codepen.io/ro-ka/pen/bpqazK?editors=0010 The function in question is at the bottom.
Any ideas what’s wrong with it?
It's because the transform: translate() CSS function, if you disable this it works perfectly. Maybe there are another CSS property to solve this 2D transform.
Ideas:
You can wrap the <svg> element into a DIV that contains these perfect-center styles and remove them from svg object.
Center with a fixed meassurement without translate.
Good luck!

Masked element in Snap SVG doesn't come into view when translated

I have a group of elements that are masked by a rect in SnapSVG and I want to translate the elements, bringing new ones into view (and hiding ones that are currently in view). The code is really simple - here's a codepen: http://codepen.io/austinclemens/pen/ZbpVmX
As you can see from the pen, box1, which starts outside the mask element (clip) should cross through it when animated, but it never appears. Moreover, box2, which should move out of the clipping area, remains visible.
This example seems to do a similar thing and has no problems: http://svg.dabbles.info/snaptut-masks2
Here's the code from codepen:
var t = Snap('#target')
var clip=t.rect(200,200,200,200).attr({fill:'#fff'})
var box1=t.rect(300,100,50,50).attr({fill:'#000'})
var box2=t.rect(300,300,50,50).attr({fill:'#000'})
var boxgroup=t.group(box1,box2)
boxgroup.attr({mask:clip})
boxgroup.animate({transform:'t100,300'},2000)
I notice that the svg.dabbles examples translates the clip region by 0,0 at one point, but adding something like that doesn't seem to get me anywhere.
Ok, I figured this out thanks in part to this really great article about SVG transforms: http://sarasoueidan.com/blog/svg-transformations/
The upshot is that when I translate the box group, it takes the mask with it. This is a little confusing to me still - I guess the mask attribute is causing this somehow? Anyways, the solution is to apply an opposite translation to the mask to keep it in place. Check the pen to see it in action but basically I just had to add:
clip.animate({transform:'t-100,-300'},2000)
The tricky part of this is that you now need to synchronize the movement of the mask and the movement of the box group.
edit - I now demonstrate how synchronization can be achieved using snap's set.animate method on the codepen.

SVG - Endless rotation takes wrong center point

I made a codepen with snap svg: Codepen
I try to rotate a svg-gear in an endless-loop around his own centerpoint.
This works on Internet Explorer, but fails on Mozilla-Firefox and Google-Chrome.
The center point in Chrome and Firefox seems wrong and so the gear move out of his position.
For the rotation i used following code:
function infRotate(el, time, cw) {
var box = el.getBBox();
el.transform('r0,' + box.cx + ',' + box.cy);
if (cw)
el.animate({transform: 'r360,' + box.cx + ', ' + box.cy}, time, mina.linear, infRotate.bind(null, el, time, cw));
else
el.animate({transform: 'r-360,' + box.cx + ', ' + box.cy}, time, mina.linear, infRotate.bind(null, el, time, cw));
}
What i have to do for Firefox and Chrome to find right center point?
Thanks for your help.
Found solution based on #lan's comment.
The gear was in a group, which contains a X/Y - transformation.
So I try to remove each group and layer in the svg file. To see clearly the nesting of objects, I work with the XML-Editor in Inkscape.
Each object must be moved to his original position by using relativ-transformation. Using relativ movements prevent inkscape to print out translations attributes to groups.
Steps to move object relativ in Inkscape:
Go to Edit -> Select All in All Layers
Go to Object -> Transform
In Transform panel:
Uncheck Relative move and check Apply to each object separately
Move object to target position
After clean up the svg file, firefox and chrome calculate the right values too and the gear is now rotation well (see updated code on codpen)
Maybe it exist a better solution to tell Inkscape not working with transformation-attributes, but i didn't found it yet.
So if you work with animated SVG, be sure that the file is has no unnecessary groups and layers and keep attentions on transformation.
Joel except of taking center by using box.cx and box.cy. take center by dividing width and height of container by 2 and then set with it.

Zooming in/out with animate on hover with snap.svg

I'm building an SVG and animating it in snap.svg because of a lack of IE support for animations (thanks IE). What I have in it's most basic form is a pentagon I'd like to rotate on hover, on mouse out it then resets itself. Code is located in the fiddle below (obviously this is a cut down version of the real thing but it shows the bug clearly still)
The JS is as follows:
// Set up snap on the svg element
var svgElement = Snap("#svg");
// Create the hover on and off events
var hoverover = function() {
svgElement.select('#pentagram-one').stop().animate({transform: 's1r72,500,515'}, 1000);
};
var hoverout = function() {
svgElement.select('#pentagram-one').stop().transform('s1R0,500,515');
};
// Set up the functions for hover in and out
svgElement.select('#pentagram-one').hover(hoverover, hoverout);
Fiddle demo of this behaviour here: http://jsfiddle.net/kfs8o9mw/
The pentagon rotates as expected on the first hover in then out. However when doing it a second time the pentagon zooms in and out a bit which is completely unexpected (it's ends up at the right size but during the animation isn't). And I've been able to replicate this in IE(10), Chrome and Firefox.
Is this a bug in snap.svg or is there something wrong in the code?
Thanks in advance
You simply can remove the s1 you have defined for the scale as show in the following:
Also note that you're using a capital R in the transform event for hoverout, when it should be a lowercase r
http://jsfiddle.net/3phpbef7/2/
I would also define you pentagram element as a variable as you're using it multiple times. I've also included this in the Fiddle above.
Hope this helps

css3 matrix3d value applied using jQuery not taking

I'm experimenting with rotating/animating an environment using CSS3 and javascript. So I have a cube object with faces, which lives inside a "rotator" object, which is the object that gets interacted with in the UI. I want to make it so that when you click a face, it appends it to a div outside of the rotator div, but applies the transformation matrices to the object from its parents, so that it appears with the same orientation on the outside of the "rotator" as it did inside, but can be animated and become independent of the rest of the objects in the "rotator" div.
Here is the function for the click event that should do this:
This depends on several custom functions, please see the fiddle for full code and reference to functions.
jQuery('#top').on('click',function(){
if(jQuery(this).parent().is('#cube')){ // only do this if it isn't already detached
M = jQuery(this).getTransMatrix(); // get the local transform of this
M = M.multiply(jQuery('#rotator').getTransMatrix()); // multiply it by the rotator's transform to get the final transform
jQuery(this).appendTo('#container'); // move this to the container div outside of the rotator
jQuery(this).css(CSS3.prefix+'transition','none'); // make sure that style changes, etc happen instantly
// wtf here
console.log(M.cssTransformString()); // just to check, we see the transform string before it is assigned. It's what it should be in my tests
jQuery(this).css(CSS3.prefix+'transform',M.cssTransformString()); // we apply the string. The wrong transformation results. If I double-check it from the console, it is NOT the string from the previous line
}
});
If you check out the fiddle, you will be able to drag around to rotate the cube. Clicking on the face will have some effect. The top face with the star is the one in question. When clicked, simply does not apply the transformation. Even if I log to console the transform string it's about to apply, the next operation does NOT result in that string being applied. It simply does not stick. HOWEVER, if I click and drag slightly, then release with the cursor still on the face, THEN the transform sticks. I have tried tracing virtually everything and I cannot figure out why the transform is only sticking if you click normally (without holding/moving at all)
Fiddle here:
http://jsfiddle.net/spaceboycoop/PWkB9/

Categories

Resources