jQuery Mousemove: trigger on change of 5px - events

For a number of technical reasons, I'm implementing my own 'draggable' feature on jQuery, rather than using jQuery UI, and I'm using mousedown and mousemove events to listen for the user trying to drag an element.
It works good so far, I would just like to fire up the mousemove event every 5 px of movement, rather than pixel by pixel. I've tried coding a simple:
$('#element').bind('mousemove', function(e) {
if(e.pageX % 5 == 0) {
// Do something
}
});
However, the movement is not stable every 5 pixels, and sometimes if you move the mouse too fast, it will skip several steps. I think this is because when moving the mouse very fast, jQuery will not trigger the event every pixel.
Do you guys know how to trigger the event every 5 pixels?
Thanks a lot,
Antonio

Your code does not take into account where your drag started. e.pageX will just give you page coordinates, not differences. You need to check for the change in distance moved.
This post is pretty relevant.
Here is the basic code:
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.round(Math.sqrt(Math.pow(startingTop - event.clientY, 2) +
Math.pow(startingLeft - event.clientX, 2))) + 'px';
$('span').text('From your starting point(22x10) you moved: ' + math);
});
EDIT: Now I think I understand what the OP is talking about. I used the above code to come up with this fiddle. It tracks your current position in relation to the Top Left of the screen and it checks to see if your difference is > 5 pixles.
New script:
var oldMath = 0;
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.round(Math.sqrt(Math.pow(startingTop - event.clientY, 2) +Math.pow(startingLeft - event.clientX, 2))) + 'px';
$('#currentPos').text('you are at :' + math);
if(Math.abs(parseInt(math) - oldMath) > 5){
//you have moved 5 pixles, put your stuff in here
$('#logPos').append('5');
//keep track of your position to compare against next time
oldMath = parseInt(math);
}
});​

Related

Tooltip for individual points created using THREE.PointCloud in Autodesk forge

I followed this blog for adding tooltip for each point implemented using Three.PointCloud. I used world2Screen to get the location of individual points and tried using this
elem = document.elementFromPoint(x, y)
but continuously only get canvas as the output (and thus tooltip at a fixed position) instead at the clicked/hovered point.
Anyone who has may be implemented this and knows any work around.
Thanks in advance
According to the blog, the document.elementFromPoint() is used to check if the cursor isn’t over the canvas. If you want to capture the hit point of the mouse clicked one, your own raycaster can help in this case. For example:
var x = ((event.clientX - viewer.canvas.offsetLeft) / viewer.canvas.width) * 2 - 1;
var y = -((event.clientY - viewer.canvas.offsetTop) / viewer.canvas.height) * 2 + 1;
var vector = new THREE.Vector3(x, y, 0.5).unproject(this.camera);
this.raycaster.set(this.camera.position, vector.sub(this.camera.position).normalize());
var nodes = this.raycaster.intersectObject( this.pointCloud );
In the above code snippet, the event object is from the mouse clicking event, see here for detail: https://github.com/wallabyway/markupExt/blob/master/docs/markupExt.js#L48

Multiple overlapping animations on the same element in svg.js

I want to start a animation on an element while a previous animation is still active. However, calling animate() on the element queues the new animation at the end of the current animation.
For example, consider an animation where an element is being moved to a new position. Now, I also want to make it fade out when it reaches a certain position. The following queues the “once” animation at the end of the move, rather than at 80%.
rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
rect.animate(200).opacity(0);
});
How do I make the element start fading out when it reaches 80% of the move? The API seems to be designed for chaining animations rather simultaneous overlapping animations.
What you are trying to do is a bit more complicated. Unforrtunately its not possible to "hack" into the current animation and add a new animation on the fly.
However what you can do is adding a new property which should be animated:
var fx = rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
fx.opacity(0);
});
As you will notice that has its own problems because the oopacity immediately jumps to 80%. So this is not an approach which works for you.
Next try: Use the during method:
var morh = SVG.morph(
var fx = rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
fx.during(function(pos, morphFn, easedPos) {
pos = (pos - 0.8) / 0.2
this.target().opacity(pos)
}
});
We just calculate the opacity ourselves

d3 - Axis Label Transition

In Mike Bostock's cubism demo (http://bost.ocks.org/mike/cubism/intro/demo-stocks.html), there is a cursor which displays the values of all horizon charts on display. Furthermore, the cursor text shows the time axis point in time. As the cursor text obscures an axis label, the label fades.
I am working on a similar display with d3.js (but not cubism). I have all working except that fade portion. I have searched through the CSS in the developer's window, searched the source code (as best I could), but I don't understand what manner of magic is being used to accomplish this feat. I've even looked through SO "axis label transition" questions, but I have failed to connect the dots on xaxis label transitions.
How does that fade in/out when obscured by text happen?
UPDATE:
I think I located the event script area where this happens - its just a little over my head at the moment - can anyone help me decipher what this event listener is doing? Specifically, in the second g.selectAll in the else clause below - what data (d) is being used here? What is causing this event to fire?
This is the coolest part of the display (outside of the horizon charts), I would love to figure this out ...
context.on("focus.axis-" + id, function(i) {
if (tick) {
if (i == null) {
tick.style("display", "none");
g.selectAll("text").style("fill-opacity", null);
} else {
tick.style("display", null).attr("x", i).text(format(scale.invert(i)));
var dx = tick.node().getComputedTextLength() + 6;
g.selectAll("text").style("fill-opacity", function(d) { return Math.abs(scale(d) - i) < dx ? 0 : 1; });
}
}
});
I used this as reference to accomplish the same effect.
I'm not sure what the context variable is or how the id's are set or what the tick flag references but what I did was simply update the opacity of the ticks according to their proximity to the mouse. With this, the vertical tick fades as well as the label text.
svg.selectAll('.x.axis .tick').style('opacity', function (d) {
return Math.min(1, (Math.round(Math.abs(d3.mouse(svg.node())[0] - x(d))) - 10) / 15.0);
});
This way, the opacity is set to 0 if it's within 10 pixels, and fades from 1-0 between 10 and 25. Above 25, the opacity would be set to an increasingly large number, so I clamp it to 1.0 using the Math.min function.
My labels are slightly rotated, so I also added an offset not shown inside the formula above (a +3 after [0]) just to make it look a bit nicer. A year late to answer your only question, but hey it's a nice effect.
same answer as Kevin Branigan's post, but using the d3 scale to calculate the opacity value.
var tickFadeScale = d3.scale.linear().domain([10,15]).range([0,1]).clamp(true);
svg.selectAll('.x.axis .tick').style('opacity', function (d) {
return tickFadeScale(Math.abs(d3.mouse(svg.node())[0] - x(d)));
}

D3 transition end events not firing correctly?

This should be straightforward: I just want to start a D3 transition running when the user clicks on a button.
However, the D3 end event does not seem to be firing correctly on my transitions: I've asked for a transition to rotate(120), but the end event seems to be firing when the rotate attribute is only 45.
This is my code:
var angle = 0;
// handle click event
d3.selectAll('.mycolour').on('click', function() {
d3.select("#loadingicon").remove();
// redraw the icon (excluded here for brevity)...
// setting the transform attribute to 0 explicitly..
group2.attr("transform", "rotate(0,0,0)");
// and start it turning:
angle = 0;
function rotateLoadingIcon() {
angle = angle%360;
angle += 120;
console.log('rotateLoadingIcon', angle, group2.attr("transform"));
d3.select(".icon").transition().ease("linear")
.duration(4000)
.attr("transform", "rotate(" + angle + ",0,0)")
.each("end", function() {
angle += 120;
console.log('innerRotateLoadingIcon', angle, group2.attr("transform"));
group2.transition().ease("linear")
.duration(4000)
.attr("transform", "rotate(" + angle + ",0,0)")
.each("end", function() {
rotateLoadingIcon();
});
});
}
console.log('about to start icon loading');
rotateLoadingIcon();
});
It works the first time the icon is drawn:
rotateLoadingIcon 120 rotate(0,0,0)
innerRotateLoadingIcon 240 rotate(119.99999999999999)
But after second or subsequent clicks, I've seen it produce console output like this:
about to start icon loading
rotateLoadingIcon 120 rotate(0,0,0)
innerRotateLoadingIcon 240 rotate(45.14999999999999)
In practice what this means is that the direction of rotation changes :(
Why has innerRotateLoadingIcon started, when the rotate attribute is only set to 45.1...? Surely given the code, it shouldn't start until rotate reaches 120 - as in the first time the code is run.
I'm wondering if the way I have set up the JavaScript means that two different versions of rotateLoadingIcon could be running at the same time. Is this possible, and can I fix it if so?
Update: Here's a JSFiddle that demonstrates the problem, though I'm now trying setInterval rather than end - click twice and you'll see the rotation change direction, I can't figure out why: http://jsfiddle.net/QtBvJ/
In the version in your jsfiddle, you only need to clear the timeout properly to make it work. The function setTimeout returns a reference that you need to pass to window.clearTimeout, i.e.
var t = null;
...
window.clearTimeout(t);
...
t = setTimeout(...);
Working fiddle here.

How do I rotate a div with Raphael.js?

I am brand new to Raphael and am really stuck, I would like to rotate a div and its contents, using a button, with Raphael.
Ideally, I would like to have a smooth animation that goes from 0 degrees to -90 degrees when the button is clicked, then when the button is clicked again, the animation would reverse. I think I will change the id or class on mouse click so that I can use the same button for both animations. Would that be wise?
I really would like some help please, my Sandbox is at http://jsbin.com/isijo/ and you can edit it at http://jsbin.com/isijo/edit
Many thanks in advance for any help.
Hello and welcome to Raphael!
I have been looking at Raphael for more than a few months and although the documentation is not very comprehensive the software is brilliant.
I have been mixing Divs with Raphael objects in many ways and have got a "feel" for what works and what does not work.
I am recommending that you do not try rotating divs but (instead) Raphael objects.
First of all you could make a shiney set of Raphael buttons using this "tweakable" code below..
var bcontrols = new Array();
var yheight = 300;
for (var i = 0; i < 3; i++) {
bcontrols[i] = paper.circle(15 + (35 * i), yheight, 15).attr({
fill: "r(.5,.9)#39c-#036",
stroke: "none"
});
bcontrols[i].shine = paper.ellipse(15 + (35 * i), yheight, 14, 14).attr({
fill: "r(.5,.1)#ccc-#ccc",
stroke: "none",
opacity: 0
});
bcontrols[i].index = i;
bcontrols[i].shine.index = i;
bcontrols[i].shine.mouseover(function (e) {
this.insertBefore(bcontrols[this.index]);
});
bcontrols[i].mouseout(function () {
this.insertBefore(bcontrols[this.index].shine);
});
/* Called from Raphael buttons */
bcontrols[i].click(function () {
alert("Hello you just clicked " + this.index);
});
}
Next you need to know more about rotating Sets:
var s = paper.set();
s.push(paper.rect(10, 10, 30, 30, 10).attr({fill:'red'}));
s.push(paper.rect(50, 10, 30, 30, 5).attr({fill:'blue'}));
s.push(paper.rect(90, 10, 30, 30).attr({fill:'orange'}));
s.animate({rotation: "360 65 25"}, 2000);
This shows the degree of rotation and the centre of rotation of the "set" on the last line.
My additional Raphael resources website which aims to supplement documentation (Amongst other things):
http://www.irunmywebsite.com/raphael/raphaelsource.html
Heres where you can run the above 2 code examples without alteration:
http://raphaeljs.com/playground.html
I'm hoping this helped...
To my knowledge, there is no way to convert a div into a Raphael object. Since the Raphael rotate command is only defined for Raphael objects, your best bet is to create the major elements of your div (images, text, buttons and all) in Raphael instead of HTML, put them together in a single set, and, as the set is a Raphael object, rotate the set.
Consult Rotate a div in CSS and in IE filters. This is not the same as SVG, so if you need more layout magic, Raphael shapes are likely the way to go. You should be able to used JQuery in concert with Raphael to manipulate both in your window, but I am brand new to Raphael and have never done so.

Resources