I have a #wrapper div wrap a #pane div, the #wrapper, overflow-x:scroll.
What I want to do is while I touch the #wrapper,the #pane should follow my finger moving.
my code is
$('#wrapper').on('touchmove',function(event){
var touch = event.originalEvent.targetTouches[0];
var move_x = touch.pageX;
$('#wrapper').scrollLeft(move_x);
})
The result is : Yes the #pane is following my finger just in reverse direction, but when my finger leave and touch again, the #pane scroll location jump to my finger x position instantly, that's not what I want. The #pane shouldn't move when I touch it until I drag around it.
If you dont want it to jump to your finger location, you will have to store the current position, and move it based on the difference between the original location that you touch, and the end location that you stop touching.
Related
I've got a custom scrollbar solution (view on CodePen).
The obvious idea is dragging the custom scrollbar should scroll the page.
Try it and see what happens... it's bizarrely janky, and the scrollbar and page scrolling will suddenly snap between points.
The scrolling process is currently in a mousemove handler:
update the scrollbar position visually
window.scrollTo(...) the new position, calculated as viewport top relative to the new scrollbar position
If I comment out the window.scrollTo(...) line, the scrollbar itself then moves perfectly smoothly and sticks with the cursor.
Pertinent code
mousemove(e) {
if (!this.active) return;
this.update(this.getScrollDeltaPositional(e.pageY));
window.scrollTo({top: this.getWindowScrollTop()});
}
update(position, show=true, timer=true, time=0) {
let track = this.getTrackHeight();
this.trackPosition = Math.min(Math.max(position, 0), track);
this.track.style.transform = `translateY(${this.trackPosition}px)`;
}
getWindowScrollTop() {
let scroll = this.getDocumentScroll();
let position = (this.trackPosition / this.root.clientHeight);
return Math.round(scroll * position);
}
(Recommended you view the full source on CodePen)
I presume the scrolling each mousemove is blocking the mousemove events, resulting in the sudden snaps being observed.
How to achieve a smooth scrolling effect on window using a custom scrollbar?
I finally found the answer
After far too many hours of trying everything conceivable to remedy this, I stumbled upon this identical problem: https://css-tricks.com/forums/topic/scrolltop-inexplicably-going-haywire/.
As that user eventually discovered, MouseEvent.pageY (which is what I was using to get scroll position) is
relative to the top edge of the viewport, including scroll offsets.
Therefore, the scroll movement effectively amplifies the mousemove events, causing the scrolling to accelerate exponentially as seen in the demo.
So after half a day of hacking about with this, the fix is a simple Ctrl+H... use MouseEvent.clientY instead.
I'm trying to gradually show a div as the swipe down event happens on the body.
I'm currently using the jQuery version of hammer.js to listen for the swipe down, but how do I get the distance of the swipe and change the height of the div as the swipe is happening to that value?
It is not much, but here is what I have so far:
var distance;
$('body').on('swipedown', function(){
// set distance to swipe distance
$('header, #header, [role="banner"]').css('height', distance);
});
But, won't the above only set the distance at the end of the swipe down? How can I set the distance while the swipe down is happening?
I would greatly appreciate any and all help!
By hammer.js swipedown event triggered, your function will get a gesture object in the event object.
you can get that like this
Hammer(document.body).on('swipedown', function(e){
gesture = e.gesture
// gesture.distance or gesture.deltaY is swipe distance
// and you can console.log(gesture) to find more!
});
I'm currently building a somewhat basic video timeline. On this timeline are various media assets of variable duration and the width of the DIVs representing the assets reflect the duration, with 1 second being measured as 35px. So, for example, a 5 second asset would take up 175px in width on the timeline.
Because the timeline needs to be longer than the width of my usable space on the page, it needs to scroll horizontally. Instead of using an ugly standard scrollbar, I'm using a jQuery plugin scrollbar, which requires that the full-width DIV of the timeline sits inside another DIV that is the width of the usable area of the page and acts as a frame, with the inner DIV being absolutely positioned. When you move the scrollbar left or right it changes the "left" value of the inner DIV.
Having given that context, I now come to my problem. The assets on the timeline need be horizontally resizable to adjust their duration. I have that working using jQuery UI, but I need to make it so that when I drag the right edge of an asset near to the right edge of the outer DIV framing the timeline, the inner DIV of the timeline moves (basically scrolls) left and the width of the asset increases by 1 second (35px).
Even this last bit I have working to a certain degree, but not well enough. What I need is that when I drag far enough to the right, so that I'm within 35-70 pixels of the right edge of the framing DIV, the inner DIV timeline will move to the left, the width of the asset will increase, and this will keep happening until I move my mouse back towards the left.
The best example I can think of is like when you're selecting text in your browser and you drag past the bottom of the screen, the screen starts scrolling down and it keeps doing that till you move your mouse up.
Currently I'm trying to to this by drawing on the "resize" event of the jQuery UI resizable element, but the problem is that I can't get that continuous effect I was just talking about, I have to keep dragging my mouse further to the right rather than just keeping it still. And when I reach the right edge of the window I have to release the mouse button, move back over to the resizing handle and start dragging again.
Here's the function I was trying to write (FYI, a .mediaInstance is an asset on the timeline):
//Scroll Timeline when resized handle comes close to right edge
function timelineScroll() {
//console.log('running');
var mediaElement = $('#mediaTrack .mediaInstance.resizing');
var track = $('#horiz_container_inner');
//Determine location of right edge of the timeline viewport
var timeline = $('#horiz_container_outer');
var timelineOffset = timeline.offset();
var timelineLeft = timelineOffset.left;
var timelineRight = timelineLeft + $('#horiz_container_outer').width();
//Find right edge of current .mediaInstance
var instanceOffset = mediaElement.offset();
var instanceLeft = instanceOffset.left;
var instanceRight = instanceLeft + mediaElement.width();
if ( (timelineRight-instanceRight) < 35 ) {
var timelineCurrentLeft = Number(track.css('left').replace('px',''));
var timelineNewLeft = timelineCurrentLeft - 70;
track.css('left',timelineNewLeft);
mediaCurrentWidth = mediaElement.width();
mediaElement.width(mediaCurrentWidth+35);
if (currentMousePos.x > timelineRight) {
while (currentMousePos.x > timelineRight) {
var timelineCurrentLeft = Number(track.css('left').replace('px',''));
var timelineNewLeft = timelineCurrentLeft - 35;
track.css('left',timelineNewLeft);
mediaCurrentWidth = mediaElement.width();
mediaElement.width(mediaCurrentWidth+35);
}
}
}
}
You'll notice I even tried a loop at the end there based on the mouse position being farther right than the right edge of the framing DIV, but I didn't think it would work, and it didn't ... just seemed to put me in an infinite loop.
In any case, I'd really appreciate any help anyone can offer on this. I'm working on a project with a really short turnaround time and I've never really done any of this particular stuff before.
It turns out I solved my own problem. I just needed to use a setTimeout within the 'resize' function checking if the mouse was beyond the right edge of the framing DIV every 250 milliseconds and, if so, move the inner DIV left and increase the width of the asset. Here's what I used...
EDIT: It turns out my solution didn't work as I'd hoped, so I could use some help after all.
Here's the HTML:
<div id="horiz_container_outer">
<div id="horiz_container_inner" style="position: absolute; left: 0px; top: 0px; visibility: visible;">
<div id="horiz_container" style="width: 10500px;">
<div id="transitionTrack"></div>
<div id="mediaTrack" class="ui-sortable ui-droppable">
<div class="transitionBoxContainer first ui-droppable"></div>
<div class="mediaInstance" assetid="001" assettype="video" thumb="video1_thumb.jpg" style="display: block; width: 419px;" type="asset" duration="12">
<div class="mediaThumbnail" style="background-image: url(./images/assets/thumbnails/video1_thumb.jpg);"></div>
<div class="mediaInfo">
<div class="mediaFilename">video1.avi</div>
<div class="mediaDuration">12s</div>
<div class="mediaHandle"></div>
</div>
<div class="transitionBoxContainer ui-droppable"></div>
<div class="deleteButton"></div>
</div>
</div><!-- End of #mediaTrack -->
</div><!-- End of #horiz_container -->
</div><!-- End of #horiz_container_inner -->
</div><!-- End of #horiz_container_outer -->
And here's my code to make the mediaInstance on the timeline resizable, snapping to 35px increments:
//Watch timeline assets for click on resize handle
$("#mediaTrack").on('mousedown','.mediaInstance .mediaHandle', function(e) {
e.stopPropagation();
e.preventDefault();
//Find offset location of right edge of the timeline viewport
var timelineViewport = $('#horiz_container_outer');
var timelineViewportLeft = timelineViewport.offset().left;
var timelineViewportRight = timelineViewportLeft + timelineViewport.width();
//Assign track object to variable
var track = $('#horiz_container_inner');
var thisInstance = $(this).parents('.mediaInstance');
//Store the mouse position before we start moving
var startMousePos = e.pageX;
$(document).mousemove(function(e){
var currentInstanceWidth = thisInstance.width();
//Find right edge offset of current .mediaInstance
var instanceLeft = thisInstance.offset().left;
var instanceRight = instanceLeft + currentInstanceWidth;
if ( (e.pageX < (startMousePos-35)) || (e.pageX > (startMousePos+35)) ) {
if ( e.pageX < (startMousePos-35) ) {
thisInstance.width(currentInstanceWidth-35);
} else {
thisInstance.width(currentInstanceWidth+35);
}
startMousePos = e.pageX;
recalcDuration(thisInstance);
calcTotalDuration();
}
});
});
$(document).mouseup(function(e){
$(document).unbind('mousemove');
});
That works great for the actual resizing, but the problem I'm having is that when I move the mouse past the right edge of #horiz_container_outer, which acts as a frame for the timeline, I want the #horiz_container_inner DIV to start moving its left position to the left by increments of 35px while also continuing to resize the .mediaInstance div to make it 35px wider ... and I want both those things to happen every 0.25 seconds ... HOWEVER, I don't want the "scrolling" of #horiz_container_inner to continuously fire with the mousemoves. Once the mouse passes the right edge of #horiz_container_outer, I want some function to take over and start scrolling and resizing the .mediaInstance DIV at a set interval until the mouse once again moves left, past the right edge of #horiz_container_outer, at which point the original resizing shown above takes over again.
The problem is that I have no idea how to achieve this. I tried using a flag variable and conditional to tell me when my mouse is "in the zone", with inTheZone = false to begin with, running a conditional to run my initial code only when inTheZone == false, then setting it to true once the mouse enters the right area and having a setTimeout takeover to loop the scrolling and resizing. This worked to a certain degree, but the mouse position suddenly became unavailable so I couldn't tell when I moved outside the zone and the div just kept scrolling indefinitely.
Any ideas?
I am using Zepto (with the Touch Module)
I have a div with a 'swipe' listener on it.
I want the div to follow the finger of the user when swiping it, just as you swipe away your notifications on your Android or iPhone.
Is there a way of getting the swipe/finger position on the swipe event? so I can put the div to position: relative with a left: [finger left position]
I found a solution for it, you have to bind it to the touchmove event, not the swipe one:
$(".element").on('touchmove', function( e ){
var x = e.touches[0].pageX;
$(this).css('left', x);
});
And of course add an ontouchend event in order to replace the element where it was in the beginning (in case the user released the swiped element)
It's also even better to use -webkit-translate: (70px 0px) for faster performance (replace 70px with x)
I'm displaying some HTML content in my iPhone app using a UIWebView. I have an image link, and I want it to change when the user touches it - at the moment the user puts a finger on the screen, rather than waiting until they lift their finger back off.
What CSS or JavaScript concept could accomplish this? I've looked at the hover and active states in CSS, but they don't seem to be what I'm after: hover relates to touch-up rather than touch-down, while active seems to have no effect at all.
You could try this.
I think it should be what you are looking for!
http://articles.sitepoint.com/article/iphone-development-12-tips/2
8: Touch Events
Of course, you use your iPhone with a
finger instead of a mouse; rather than
clicking, you tap. What’s more, you
can use several fingers to touch and
tap. On the iPhone, mouse events are
replaced by touch events. They are:
touchstart
touchend
touchmove
touchcancel (when the system cancels the touch)
When you subscribe to any of those
events, your event listener will
receive an event object. The event
object has some important properties,
such as:
touches — a collection of touch objects, one for each finger that
touches the screen. The touch objects
have, for example, pageX and pageY
properties containing the coordinates
of the touch within the page.
targetTouches — works like touches, but only registers touches on
a target element as opposed to the
whole page.
The next example is a simple
implementation of drag and drop. Let’s
put a box on a blank page and drag it
around. All you need to do is
subscribe to the touchmove event and
update the position of the box as the
finger moves around, like so:
window.addEventListener('load', function() {
var b = document.getElementById('box'),
xbox = b.offsetWidth / 2, // half the box width
ybox = b.offsetHeight / 2, // half the box height
bstyle = b.style; // cached access to the style object
b.addEventListener('touchmove', function(event) {
event.preventDefault(); // the default behaviour is scrolling
bstyle.left = event.targetTouches[0].pageX - xbox + 'px';
bstyle.top = event.targetTouches[0].pageY - ybox + 'px';
}, false);
}, false);
The touchmove event listener first cancels the default behavior of the finger move—otherwise Safari will scroll the page. The collection event.targetTouches contains a list of data for each finger currently on the target div element.
We only care about one finger, so we use event.targetTouches[0]. Then pageX gives us the X coordinate of the finger. From this value we subtract half the width of the div so that the finger stays in the center of the box.
Hope it helps!
Try the Javascript "onMouseDown", hopefully the mobile Safari will fire the event.
Link