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!
Related
I have some colored lines in a canvas which I scan using a mousemove event, which returns the line's hex color code.
Is there anyway I could make this canvas invisible to the eye, but when the pointer goes over the canvas, still returns the correct color code?
I've tried setting the context's globalAlpha to transparent or near transparent (0, 0.1...) with mixed results in the following fiddle:
In Firefox, the collected hex returns an altered color due to transparency,
In Chrome, it returns the correct color regardless of transparency (this is actually the behavior I want).
And oddly, in my original code, even in Chrome, canvas lines with globalAlpha=0 no longer return their original color.
Can someone kindly explain what the expected behavior for globalAlpha is? More importantly, is there another way to make a canvas invisible to the eye but which still allows collecting the colors with a mouse event? Any help appreciated!
Set CSS property opacity to 0.
When you apply the property to your canvas like
#examplecanvas {
opacity: 0;
}
It will vanish from the screen but still detect color when you mouse over it (or click it).
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.
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.
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
I'm trying to draw a grid on a <canvas> element with the ultimate goal of making a Go board.
For some reason the grid is looking stretched, with the lines being thicker than 1 pixel and the spacing being completely wrong. It doesn't even start in the (10,10) position..
It would be great if someone could take a look at tell me what I'm doing wrong.
http://jsfiddle.net/h2yJn/
I've found the problem. I was setting the dimensions of the <canvas> using CSS, when you actually have to set the width and height attributes. This was causing it to be stretched/skewed.
var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');
http://jsfiddle.net/h2yJn/66/
Please try it outside jsfiddle, maybe jsfiddle is applying some linear transformation.
Also please make sure that you add 0.5 everywhere to both x and y coordinates. Alternatively, you can apply translate(0.5, 0.5) to shift all coordinates by half a pixel.