SVG animate only with "to" attribute - javascript

I want to animate an SVG path to 2 different states. For this, I've created a triangle path, with 2 example animations, which I trigger through Javascript.
These animations only have the "to" attribute because the intention is to animate the path from whatever state is in to any other desired state (the final animation will have 10+ states).
You can see a working example here: http://codepen.io/anon/pen/dxvlt
The problem is that, at least in Chrome, if you click Animation1, then Animation2, then back to Animation1 it works fine. However, right after that, animations stop working, or only one of them works. I believe the animation is triggered, but it's not being drawn. This problem does not happen in Firefox, and I've read that Webkit and Blink have numerous SVG bugs.
Do you know a workaround to make it draw correctly on Chrome as well?

Related

Adobe Animate CC Canvas mouse actions on the stage are laggy and intermittent

In Adobe Animate CC HTML5 Canvas (createJS), I'm trying to do something very simple, to trigger an animated rollover when the entire stage of an ad is moused over, and to trigger an animated rollout when the mouse leaves the stage. It should be very simple, but it's not. Using mouseenter and mouseleave on the stage is laggy and only works intermittently. It's the same with mouseover and mouseout.
Here's the code that's laggy and intermittent:
stage.addEventListener("mouseenter", fl_MouseOverHandler.bind(this));
stage.addEventListener("mouseleave", fl_MouseOutHandler.bind(this));
function fl_MouseOverHandler(){
this.btnOverAnim.gotoAndPlay("on");
}
function fl_MouseOutHandler(){
this.btnOverAnim.gotoAndPlay("off");
}
I also tried mouseover and mouseout on a button the entire size of the stage and I got the same issue. (Also doing it this way doesn't work at all from inside a frame, and the ad is served inside a frame). I put the var frequency way up to 90 to see if that would help with the lagging, it didn't.
This was the simple mouseover / mouseout code I tried:
var frequency = 90;
stage.enableMouseOver(frequency);
this.bgCta.addEventListener("mouseover", fl_MouseOverHandler.bind(this));
this.bgCta.addEventListener("mouseout", fl_MouseOutHandler.bind(this));
On the createJS website it says "You can monitor whether the pointer is over the canvas by using stage.mouseInBounds AND the mouseleave / mouseenter events." So I'm wondering if using stage.mouseInBounds will help (but I can't find an example anywhere of how to use it). But I actually don't think it'll help because I think this whole problem is about createJS not reading where the mouse is fast enough.
Does anyone know how to fix this lagginess and intermittent firing? A work around? Why does createJS not just monitor the mouse events constantly like pure js?
Also mouseenter and mouseleave on the stage in createJS do not work on tablets or mobile and that's a problem, so it would be better to do this with mouseover and mouseout on a button the entire size of the stage. I did try using mouseover and mouseout and having 3 pixels space around the button between the edge of the button and the edge of the ad banner, this helped, but it was still firing intermittently.
Your thoughts and ideas please.
Mouseover checks are expensive. A canvas is essentially just a bitmap, so EaselJS can't use mouse events from the browser (you just get one for the entire canvas). Instead, mouseover in EaselJS requires every element to be drawn to a 1x1 pixel canvas, and then checked for fill. This gives pixel-perfect detection, but is costly if you are either checking a lot of content, or checking too often.
Reduce your frequency:
It looks like you have set the frequency to 90. This is really high (11 ms between checks, which is basically trying to achieve 90 fps). The default is 10, which is slower than a good framerate, but fast enough to feel responsive. You can probably bring it down to 20 or so to give you a peppy check without it being unnecessarily high.
Modify interactivity: Another thing you can do is filter out exactly what gets checked. By default, all display objects get checked -- but you can reduce this by turning off mouseEnabled on anything you don't care about (omitting them from the check), and turning off mouseChildren on containers that you want to treat as a single object (so something like a complex button is drawn once, instead of all its contents being drawn individually).
// Example
myBackground.mouseEnabled = false;
myButton.mouseChildren = false;
Hope that helps!
Friends, I know this was asked 4 years ago, but the lagginess in Adobe Animate CC V.21 is no different (horrible) regarding mouseenter, mouseleave, mouseover and mouseout. After 10 times of rolling over/out the page becomes unresponsive. I was able to alleviate this using stage.mouseInBounds on a setInterval. The original poster could not find an example, so here is what I did:
// Place this in a keyframe on the timeline where the named cta exists.
setInterval(function(scope){
if(stage.mouseInBounds){
createjs.Tween.get(scope.cta).to({scaleX:1.1, scaleY:1.1}, 150);
}
else{
createjs.Tween.get(scope.cta).to({scaleX:1, scaleY:1}, 150);
}
}, 150, this );
Make sure to pass this into the end of the setInterval function as an argument for the callback function as to not lose scope. I am guessing this can be reworked to use gotoAndPlay() on the timeline, in this instance the built-in tweener for CreateJS sufficed for what I needed.

D3 js unexpected behavior on rapid mouse clicks

I have a multiline chart using D3, and the lines have nodes to mark the points. I also have legends below x-axis to display or hide each line when a user clicks on them. Similar to this example
The chart and legend selection works totally fine when I click normally on legends. But when I click rapidly on legends, one of the lines' nodes disappear. When I inspected the page, I found they got relocated to the top of the browser window(and not visible because there's no svg element there)
I don't even know what the problem is and where should I start debugging as it works fine with normal speed mouse clicks on legends.
I know it is very difficult for anyone to help without looking at the source code or a working fiddle, but I just wanted to know (before I try to reproduce the problem on fiddle) has anyone experienced something like this before? does mouse clicking speed affect how elements get rendered in D3? or this is not a D3 problem at all and some javascript/dom thing I am overlooking?
Some "strange" behaviour can occur depending on how your transitions are set up. For example, if there are many transitions attached to the same element, one might be interrupted when another one starts, and that may result on some element not being redrawn on screen.
For more about this see D3 documentation: Working with transitions, specifically this section which explains that "for a given element, transitions are exclusive: only one transition can be running on the element at the same time. Starting a new transition on the element stops any transition that is already running."

Animated SVG path doesn't show up in Firefox when hidden initially

I'm trying to debug why this piece of animating SVG isn't working in Firefox.
Test case & code here: http://jsbin.com/AYICOwE/18/edit
I'm changing the stroke-dasharray attribute on a <path>-element inside of an inline <svg> graphic, to progressively draw a dashed line. Since I don't want the path to show before I animate it, I set the stroke-attribute to none initially (have also tried to set it to a transparent color), and then re-set it when the animation runs.
The progressive drawing of the dashes works everywhere when the line initially has a visible stroke, but as soon as it doesn't, Firefox doesn't show anything at all. When the line is initially shown, I can still animate it, hide it (by setting stroke to none) and show it again etc.
Toggling CSS properties in the inspector (causing the element to repaint) afterwards snaps it into view.
Browser bug, or something I'm doing wrong/stupidly? Workaround ideas?

Prevent image from 'obscuring' onmouseover event below?

For a 'shooting gallery'-like game, there are images with an onMouseOver event that will show a crosshair (which follows the mouse) and an onMouseOut event that will hide it.
However, the instant the crosshair becomes visible, it covers the below image, activating its onMouseOut event which hides the crosshair.
This creates a 'flicker' effect which is very, very ugly.
Is there a way to prevent the crosshair image from obscuring the target below?
One easy solution is to create an onMouseOver for the crosshair that shows it (I know this is redundant, but it works for menus and the like).
Another solution would be to set a timeout in the onMouseOut to hide the crosshair. It will reduce the flickering and the crosshair will be visible out of the target for a short time.
Edit:
And another would be to perform a collision detection between the mouse and the elements, changing the mouseOver to a mouseMove in the target's parent element:
http://jsfiddle.net/sHecT/1/
The code is quite long, but its logic is what I've said above.
Just a note: The getElementsByClassName doesn't work in older browsers, but you can use an array of targets, as you create them, add them to an aray (probably you already has one) and use it in place of this call;
This one illustrates an easing function to position the crosshair smothly and the cursor is hidden when over the target
http://jsfiddle.net/sHecT/2/
Instead of using an image for your background, and an image for your cross-hairs, what if you used a div with a background image for your background instead, and then made the cross-hairs image a child of that div?
I haven't tested this, but since the cross-hair image would now be part of the content of the background div, I would imagine that it would no longer trigger a mouseout.
I believe The pointer-events property is exactly what you're looking for. It basically prevents an element from being the target of any sort of mouse-event so the elements underneath it can handle them instead. Parent elements can still react to the event.
HOWEVER it is only supported in the later versions of Firefox, Safari, and Chrome, and it probably won't be in the CSS specification until CSS4. It an awesome solution for supported browsers, but if you want to fix the issue in any version of IE or Opera you'll also need an alternate solution. I felt like it deserved a mention here though. :D

Raphael and IE. Mouseout workaround

I've run into an issue using Raphael for SVG effects on an IE browser. When I mouseover an object, the animation occurs as expected. On mouseout, however, the mouseout action is never called, so the object(s) are stuck in their mouseover state.
I've seen others complain about this issue in the past, but the only solution I saw was to force the mouseover event on every object to return everything != current object to their normal state. I'd rather not do a general "reset everything" because I have quite a few objects, so I'm wondering if anyone has an alternative they can suggest. I was thinking about storing the last object with the last triggered mouseover in a variable and only resetting that on every mouseover, which could work....
Since Raphael 2.0.2, there's been an issue in Raphael and Internet Explorer (all versions) where various manipulations of a path such as resetting a transform, .toFront(), or .toBack() called from hover() while hovering can cause hover ins to loop endlessly and/or hover outs to be missed.
While hover mostly works fine in IE for mouseout, there are a few things I've found that that can trip it up, causing it to a) ignore mouseouts as you describe and b) trigger the mouseover event recursively such that if you put a console.log in there, IE developer tools' console breaks and turns grey... which sometimes seems to also stop it recognising mouseouts.
Here are the things I've encountered which cause this:
Resetting a transform, which would cause the element to move from under the mouse, then reapplying it putting the element back under the cursor. non-IE carries on like nothing happened and works fine, IE freaks out as described above.
.toFront() and .toBack() - non-IE recognises the moved element as being the same element in the same X Y position, IE freaks out as described above.
There are some observations and demonstrations in this jsfiddle (read & uncomment the various comments).
A good workaround here, is to have some kind of flag like for example 'path.data( 'hoverIn', true );on mouse in and 'path.data( 'hoverIn', false ); on mouse out, then wrap any .toFront() or offending transforms in a check that !path.data( 'hoverIn' ) so that it can only happen once until the mouse out happens. Or, store a reference to the most recently hovered path somewhere after the toFront() or whatever, then don't toFront() or whatever if this path is also the most recently hovered one.
I had the same problem (map with regions that changed background on hover) and the deal-braker in IE9/Opera for me was the toFront() method. I removed that and it works fine.
I gone around this limitation by putting code inside anonymous function and then calling it via setTimeout inside event handler.
If you add a rect as a background underneath (and containing) the object you are trying to mouseout of, you can effectively get a mouseout effect by adding another hover event handler to the background rect.

Categories

Resources