Stop the animation when it takes - scroll

I have this animation to scroll bottom:
$('.link_msg').on('click', function() {
$(this).closest('#tabs').find('.messages').each(function() {
$(this).animate({ scrollTop: $(this).prop('scrollHeight')}, 1500);
});
});
I want stop this animation when I scroll mouse.
I searched and found a solution but when I give that whith "scroll...":
$('.link_msg').on('click', function() {
$(this).closest('#tabs').find('.messages').each(function() {
$(this).on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function(){
$(this).stop();
});
$(this).animate({ scrollTop: $(this).prop('scrollHeight')}, 1500), function(){
$(this).off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove");
});
return false;
});
});
animation don't started. When I remove "scroll" animation work and stop when I click mouse but of course dont stop when I scroll. How fix this?
How else can animate a scroll to return to the bottom and stopped when i scroll mouse?

I use to detect the direction of scrolling. When the animation goes down I do not do anything. If the user is scrolling up, the animation is stopped.
$('.link_msg').on('click', function() {
$(this).closest('#tabs').find('.messages').each(function() {
$(this).animate({ scrollTop: $(this).prop('scrollHeight')}, 2500);
var lastScrollTop = 0;
$(this).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
// downscroll code
} else {
// upscroll code
$(this).stop();
}
lastScrollTop = st;
});
});
});
Hint found at: How can I determine the direction of a jQuery scroll event?

Related

Highcharts Highmaps prevent initial zoom effect

I built a map with Highmaps that initially zooms in to a lat lon position: see fiddle
Here is my code:
parsed: function() {
var chart = this.chart,
center = chart.fromLatLonToPoint({
lat: 50,
lon: 10
});
setTimeout(function() {
chart.mapZoom(.2, center.x, center.y);
When the map is loaded and when the time slider is started the map zooms in. How can I prevent this animation?
You can disable animation on the chart level and restore it after initial zoom:
chart: {
animation: false,
...
}
chart.update({
chart: {
animation: true
}
});
Live demo: https://jsfiddle.net/BlackLabel/xarg940y/
API Reference: https://api.highcharts.com/highmaps/chart.animation

d3.js v4 programmatic Pan+Zoom. How?

I did a small example of what i am trying to implement, here it is - https://jsfiddle.net/zeleniy/4sgqgcx0/. You can zoom and pan SVG image as usual. But i have no idea how to implement zoom programmatically when user click on "+" and "-" buttons. Especially if he already zoom in/out and pan original image. Could you help me?
On line 13 of the code you will find zoom event handler.
var zoom = d3.zoom()
.on('zoom', function() {
canvas.attr('transform', d3.event.transform);
});
On lines 35 and 39 - zoom event handlers
d3.select('#zoom-in').on('click', function() {
// what here?
});
d3.select('#zoom-out').on('click', function() {
// what here?
});
So when user click on "+" app should zoom in as if mouse were at the center of SVG element. And the same with "-".
Thanks to Fil. Here is an updated version of jsfiddle.
d3.select('#zoom-in').on('click', function() {
// Smooth zooming
zoom.scaleBy(svg.transition().duration(750), 1.3);
});
d3.select('#zoom-out').on('click', function() {
// Ordinal zooming
zoom.scaleBy(svg, 1 / 1.3);
});

fabricjs mouse events fail after setSrc()

When changing a selected canvas image to a larger image using setSrc(), mouse events are not recognized on areas of the new image that lie outside of the xy boundaries of the original smaller image.
Conversely, when changing a selected canvas image to a smaller image, mouse events are recognized on areas outside of the new image up to the xy boundaries of the original larger image.
In either case, once the new image does receive a mouse click, things return to normal where the entire image receives mouse events, no more, no less. Also, the controls appear in the correct locations but are not clickable as stated above.
Is there a way to correct this behavior so only the complete visible image can receive mouse events?
http://jsfiddle.net/kamakalama/0ng18cas/10/
HTML
<body>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<button id="butt">Change Image</button>
<canvas style="border:1px solid silver;" width=500 height=400 id="c"></canvas>
</body>
JavaScript
$(document).ready(function() {
var canvas = new fabric.Canvas('c',{backgroundColor:"#ffffff"});
var bigImg="http://nonsuch30.com/yachtcards/images/cardbox-closed.jpg"
var smallImg="http://nonsuch30.com/yachtcards/images/woodcrafter-thumb.jpg"
fabric.Image.fromURL(smallImg, function (img) {
canvas.add(img);
canvas.renderAll();
img.setTransformMatrix([ 1, 0, 0, 1, 0, 0])
canvas.setActiveObject(img)
})
$("#butt").click(function(){
img = canvas.getActiveObject()
if(img.getSrc()==smallImg){
img.setSrc(bigImg)
}else{
img.setSrc(smallImg)
}
setTimeout(function(){
canvas.renderAll()
canvas.setActiveObject(img)
}, 2000);
});
});
You're correct in using setCoords(), but put that and canvas.renderAll() in the setSrc() callback so you can remove the setTimeout() function call:
if (img.getSrc() == smallImg) {
img.setSrc(bigImg, function() {
canvas.renderAll();
img.setCoords();
});
} else {
img.setSrc(smallImg, function() {
canvas.renderAll();
img.setCoords();
});
}
Calling setCoords() on the new image corrects the problem.

Skrollr: Smooth scrolling

I would like to achieve a smooth scrolling when turning a mouse wheel. Currently, when I do one turn, the scrollbar kinda jumps and the animation is jumpy.
Example of this behaviour:
http://areaaperta.com/nicescroll/
Can this scrolling be achieved using skrollr only? If so, how?
I tried following code
var s = skrollr.init({
render: function(data) {
//Debugging - Log the current scroll position.
console.log(data.curTop);
},
smoothScrolling: true,
smoothScrollingDuration: 500,
easing: {
WTF: Math.random,
inverted: function(p) {
return 1-p;
}
}
});
but it doesn't make a big difference. The animation is little bit smoother (i.e. background slides for a while and then stops), but the scrolling itself is still jumpy.
I would prefer to solve this with skrollr only as I think it is prepared for it instead of adding another plugin.
This is a quote from Petr Tichy (ihatetomatoes.net):
For smooth animations, animate cheap properties.
The best result you'll get, when you keep animating only the cheap CSS
properties.
transform: scale(1.2)
transform: translateX(100px)
transform: rotate(90deg)
opacity: 0.5
These 4 properties will let you change the size, position, rotation
and opacity of your elements.
Combination of these CSS properties will enable you to create pretty
much most of you ideas and will get you the best results.
If you come across lagging and choppy scrolling animations, give the
animated element transform: translateZ(0).
This will promote the element into composite layers and will get rid
of the lag.
Try to include this script
jQuery(function () {
var $window = jQuery(window);
var scrollTime = 0.5;
var scrollDistance = 150;
$window.on("mousewheel DOMMouseScroll", function (event) {
event.preventDefault();
var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
var scrollTop = $window.scrollTop();
var finalScroll = scrollTop - parseInt(delta * scrollDistance);
TweenMax.to($window, scrollTime, {
scrollTo: {
y: finalScroll,
autoKill: true
},
ease: Power1.easeOut,
overwrite: 5
});
});
});
I had this problem also (With Chrome on Mac)
I solved by this plug-in :
https://github.com/simov/simplr-smoothscroll
<!-- After jQuery -->
<script src="jquery.mousewheel.min.js"></script>
<script src="jquery.simplr.smoothscroll.min.js"></script>
<script type="text/javascript">$.srSmoothscroll();</script>

Click Event Not Firing After Drag (sometimes) in d3.js

Observed Behavior
I'm using d3.js, and I'm in a situation where I'd like to update some data based on a drag event, and redraw everything after the dragend event. The draggable items also have some click behavior.
Draggable items can only move along the x-axis. When an item is dragged, and the cursor is directly above the draggable item on dragend/mouseup, the item must be clicked twice after it is re-drawn for the click event to fire. When an item is dragged, but dragend/mouseup does not occur directly above the item, the click event fires as expected (on the first try) after the redraw.
Desired Behavior
I'd like the click event to always fire on the first click after dragging, regardless of where the cursor is.
If I replace the click event on the draggable items with a mouseup event, everything works as expected, but click is the event I'd really like to handle.
A Demonstration
Here is a self-contained example: http://jsfiddle.net/RRCyq/2/
And here is the relevant javascript code:
var data, click_count,did_drag;
// this is the data I'd like to render
data = [
{x : 100, y : 150},
{x : 200, y : 250}
];
// these are some elements I'm using for debugging
click_count = d3.select('#click-count');
did_drag = d3.select('#did-drag');
function draw() {
var drag_behavior,dragged = false;
// clear all circles from the svg element
d3.select('#test').selectAll('circle')
.remove();
drag_behavior = d3.behavior.drag()
.origin(Object)
.on("drag", function(d) {
// indicate that dragging has occurred
dragged = true;
// update the data
d.x = d3.event.x;
// update the display
d3.select(this).attr('cx',d.x);
}).on('dragend',function() {
// data has been updated. redraw.
if(dragged) { draw(); }
});
d3.select('#test').selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx',function(d) { return d.x; })
.attr('cy',function(d) { return d.y; })
.attr('r',20)
.on('click',function() {
did_drag.text(dragged.toString());
if(!dragged) {
// increment the click counter
click_count.text(parseInt(click_count.text()) + 1);
}
}).call(drag_behavior);
}
draw();
A little late to the party, buuuut...
The documentations suggests that you use d3.event.defaultPrevented in your click event to know whether or not the element was just dragged. If you combine that with your drag and dragend events, a much cleaner approach is to call the exact function you want when necessary (see when and how flashRect is called):
http://jsfiddle.net/langdonx/fE5gN/
var container,
rect,
dragBehavior,
wasDragged = false;
container = d3.select('svg')
.append('g');
rect = container.append('rect')
.attr('width', 100)
.attr('height', 100);
dragBehavior = d3.behavior.drag()
.on('dragstart', onDragStart)
.on('drag', onDrag)
.on('dragend', onDragEnd);
container
.call(dragBehavior)
.on('click', onClick);
function flashRect() {
rect.attr('fill', 'red').transition().attr('fill', 'black');
}
function onDragStart() {
console.log('onDragStart');
}
function onDrag() {
console.log('onDrag');
var x = (d3.event.sourceEvent.pageX - 50);
container.attr('transform', 'translate(' + x + ')');
wasDragged = true;
}
function onDragEnd() {
if (wasDragged === true) {
console.log('onDragEnd');
// always do this on drag end
flashRect();
}
wasDragged = false;
}
function onClick(d) {
if (d3.event.defaultPrevented === false) {
console.log('onClick');
// only do this on click if we didn't just finish dragging
flashRect();
}
}
I didn't like the global variable, so I made a revision to use data: http://jsfiddle.net/langdonx/fE5gN/1/
After observing that the click required before my svg circles would start responding to click events again could happen anywhere in the document, I settled on a hack whereby I simulate a click event on the document (thanks to https://stackoverflow.com/a/2706236/1015178) after the drag ends. It's ugly, but it works.
Here's the function to simulate an event (again, thanks to https://stackoverflow.com/a/2706236/1015178)
function eventFire(el, etype){
if (el.fireEvent) {
(el.fireEvent('on' + etype));
} else {
var evObj = document.createEvent('Events');
evObj.initEvent(etype, true, false);
el.dispatchEvent(evObj);
}
}
And here's the updated drag behavior:
drag_behavior = d3.behavior.drag()
.origin(Object)
.on("drag", function(d) {
// indicate that dragging has occurred
dragged = true;
// update the data
d.x = d3.event.x;
// update the display
d3.select(this).attr('cx',d.x);
}).on('dragend',function() {
// data has been updated. redraw.
if(dragged) { draw(); }
// simulate a click anywhere, so the svg circles
// will start responding to click events again
eventFire(document,'click');
});
Here's the full working example of my hackish "fix":
http://jsfiddle.net/RRCyq/3/

Resources