Getting swipe feature in replacement for next and previous button - javascript

How can I get a swipe feature instead of having to use buttons on computer/phone.
Here is an example of a next a previous button that should be changed to swiping right or left.
I also would like dots to indicate which track is visible.

I was able to add an onMouseDown event handler that captures the position of the mouse when it is over the <h4> tag and then when the mouse moves (onMouseMove) it determines if the new x coordinates of the mouse are greater than or less than the original x coord. If it's greater, execute the onClickNext() function, proceeding to the next track. If it's less, then it executes onClickPrev(). After the swipe is completed it resets oldX to null thus ending the swiping event check.
onMouseDown() {
this.setState({
oldX: event.clientX
});
}
onMouseMove(){
var newX = event.clientX;
if (this.state.oldX) {
if (newX > this.state.oldX) {
this.onClickNext();
this.setState({ oldX: null });
} else if (newX < this.state.oldX) {
this.onClickPrev();
this.setState({ oldX: null });
}
}
};
Here is the codesandbox with the code.

Related

How to make jquery setinterval movement in mobile smoother?

Sorry for bad english.
Here's link to site.
My task is to create site with no scroll. When user clicks to right part of screen car starts to move forward. When it reaches middle of screen - car stops and fixed content-block starts to move in opossite direction. if user moves cursor to left side of screen (while holding mouse button clicked) car should move backward.
Desktop version works as expected. But mobile version is slow. (it's not exactly slow, it's not as smooth as desktop i guess)
What can i do fix this problem?
On touchstart event i get event.pageX value to check what part of screen user touched. (so i would know what direction car should move) and store this value in variable "mousePos". Then i call setInterval with movement function
On touchend event i clear interval to stop car from moving.
On touchmove i will rewrite "mousePos" var with new event.pageX value. For example: user clicked, car starts to move, if user moved cursor to left i will use this var to check direction and turn car back.
In mouseMove function i will check car position and decide what action should be done - either move car or move background and i'll check if it reached start of end points
events:
$(document).on('mousedown touchstart', '.mouse-click', function(event){
clicking = true;
mousePos = event.pageX;
if ( event.target.className == 'helper' ) {
showModal();
} else {
moveStuff = setInterval(mouseMove, 1);
}
});
$(document).on('mouseup touchend', function(){
clicking = false;
carLights.removeClass('blink');
clearInterval(moveStuff);
})
$(document).on('mousemove touchmove', '.mouse-click', function(event){
if(clicking == false) {
return;
} else {
mousePos = event.pageX;
}
});
function:
function mouseMove() {
let offset = parseInt( mainContent.css('left') );
let offsetCar = parseInt( car.css('left') );
if ( mousePos > middleScreen ) {
carLights.removeClass('blink');
if ( offset < - ( contentWidth ) ) {
return;
} else {
rotateWheelsForward();
if ( offsetCar < middleScreen ) {
car.css('left', (offsetCar + mouseSpeed) + 'px');
} else {
mainContent.css('left', (offset - mouseSpeed) + 'px');
}
}
} else if ( mousePos < middleScreen ) {
carLights.addClass('blink');
if ( offset > 0 ) {
carLights.removeClass('blink');
return;
} else {
rotateWheelsBackward();
if ( offsetCar > minCarLeft ) {
car.css('left', (offsetCar - mouseSpeed) + 'px');
} else {
mainContent.css('left', (offset + mouseSpeed) + 'px');
}
}
}
}
So how can i make movement smoother in mobile? (i use iphone 5s safari, but tested in iphone 6, still works bad)
What changes should i implement to this code?
I suggest to use transform rather than position eg: left, top cause thats really affect layer reflow-repaint. Use requestAnimationFrame (wisely) to perform smooth event animation like scroll, mouseup, or any other event.
Then use will-change: transform; to element which will "transformed" on the future. This will creates new layer and prepare for the element changes later.
In my case, relative position impact reflow or green flash on the rendering tool chrome. So I prefer use fixed/absolute position to prevent this.
Here's some great article for you to get Leaner, Meaner, Faster Animations with requestAnimationFrame and how to achieving 60 fps animations with css
Hope this help ;)

How can I add some buffer to a mousemove event so it doesn't disrupt mouseup events

I'm currently building a menu that is also draggable and I'm using the following on each individual tab:
(mousedown)="dragging = false"
(mousemove)="checkMouseMove($event)"
(mouseup)="changeRoute('forms')"
Change Route looks like this:
changeRoute(routeName: string) {
// manual reset for dragging.
if (this.dragging) {
return;
}
Past this is just my routing and switch statement's that correctly will change route and apply styling etc.
Previously inside the mousemove event I just had dragging = true but the problem with this is that even the slightest movement will mean that a click does not occur when it's likely to be intended to.
My first instinct was that I need to add a buffer to the amount of space it will need to move to be called a drag but given the output events I'm not sure how to achieve this.
checkMouseMove(event) {
console.log(event);
}
This event provides me with the following output:
How can I use these events in conjunction with my checkMouseMove / Component to only change dragging after a reasonable amount of movement?
You can save the last mouse position and calculate the distance the cursor moved.
Based on this distance you can filter small and unwanted drags.
var lastEvent;
function checkMouseMove (event){
var dx = 0;
var dy = 0;
if (lastEvent) {
dx = event.clientX - lastEvent.clientX;
dy = event.clientY - lastEvent.clientY;
}
var d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
if (d > 5) { /* handle mouse move here */ }
lastEvent = event;
}
You can also use any other non euclidean heuristics like Manhattan or Chebyshev.

Preventing the default action only for a left swipe/right swipe event

I am using event.preventDefault but after some checks, I want the event to continue.
For eg, For the
touchmove
event I am using event.preventDefault() as I don't want the browser to scroll horizontally, but after determining the direction of swipe, if the direction turns out to be up/down, whatever event i have prevented, i want to nullify the effect. Is that possible?
My scenario
This is my html
<div id="teazer" class="globalTeaser" ontouchcancel="touchCancel(event);" ontouchmove="touchMove(event);" ontouchend="touchEnd(event,'gTeaser');" ontouchstart="touchStart(event,'teazer');">
This is my js after removing the irrelevant part
function touchMove(event) {
if(fingerCount==1){
event.preventDefault();
if ( event.touches.length == 1 ) {
curX = event.touches[0].pageX;
curY = event.touches[0].pageY;
}
else {
touchCancel(event);
}
}else {
touchCancel(event);
alert("hi");
}
}
function touchEnd(event,eventType) {
//I get the swipe direction here,after some calculations
//I get the directions fine,now
//if the swipe direction is up/down whatever event i have prevented in touch move I need to nullify
}
Please note, if anyone is gonna suggest window.scrollBy, for some reason its not working for me. Any other solutions I am happy to try.
I don't know how your code behaves exactly, but this is the general principle:
// Keep a reference for last point both events can access
var start;
$( 'body' ).on( {
// On start, assign the event data to start
touchstart : function touchStart( touchstartEvent ){
start = touchstartEvent.touches[ 0 ];
},
touchmove : function touchMove( touchmoveEvent ){
// The difference between both events positions
var delta = {};
// The end event's position
var end = touchmoveEvent.touches[ 0 ];
// Calculate the offset compared to start for this move event
delata.pageX = start.pageX - end.pageX;
delata.pageY = start.pageY - end.pageY;
// If pageX is less than or greater than 0, it means there has been horizontal movement,
// and this if condition will pass
if( delta.pageX ){
touchmoveEvent.preventDefault();
}
}
} );
This isn't perfect, because in practice it's very difficult to create a perfect downward or upward swipe — my finger might move a couple of pixels left or right even if the main movement is downwards. But then you have the problem of preventing horizontal motion but not vertical! In any case, the general principal for testing different properties of a touch event and only preventing default in certain conditions is illustrated.
My touchMove() function has been rewritten as follows
function touchMove(event) {
if (event.touches.length == 1) {
curX = event.touches[0].pageX;
curY = event.touches[0].pageY;
if (Math.abs((curX - startX)) > 10) {
//default acion is prevented only if the
//finger count is one and change in
//x coordinatesis greater than 10 px
event.preventDefault();
}
}
else {
touchCancel(event);
}
}
This code will make sure of two things
1)Pinch to zoom is not affected
2)default action for vertical swipe is not affected

canvas button onmouseover change color

I have a drawButtons function that takes an argument of "nonhover", "hover1" or "hover2" and draws up a new button set to the canvas, and depending on the argument it takes, will draw the buttons different colors. It does work when i call it from setUpGame() but not when I call it from draw(). I want to call it from draw() because draw() is called 80 times a second in setInterval(). That way it can keep checking if the mouse is hovering over the button and draw the appropriate button set.
setUpGame() is called outside of any object or function. draw() is called by setInterval() which is outside of any function or object. setInterval calls draw 80 times a second.
getMouseOver() another function that is the one that should actually be called by draw(), because it says "if mouse is over button one: drawButtons("hover1") and so on. It just doesn't draw the buttons when I call it.
There are no errors in the browser Javascript console. I am using Chrome which works best with my game.
From this we can deduce that there is no problem with drawButtons() as it worked when called from setUpGame().
There is possibly a problem with draw() as drawButtons() doesn't work when I call it from there (but to perplex us more, displayNumbers does display the numbers when I call it from there) and it worked fine when playing the game (here we are not playing the game, we are on a start screen).
There is probably a problem with getMouseOver() because that doesn't work anywhere.
I will show you getMouseOver() for now. My program is getting big and it is overwhelming to show too much right from the start. I intend for this function to be called 80 times a second.
getMouseOver: function() {
window.onload = (function(){
window.onmouseover = function(e) {
// IE doesn't always have e here
e = e || window.event;
// get event location
// change the code so that it gives the relative location
var location = {
x: e.pageX - offset.x,
y: e.pageY - offset.y
};
if (location.x > 103.5 && location.x < 265.5) {
if (location.y > 240 && location.y < 291) {
nonGameContent.drawButtons("hover1");
}
}
if (location.x > 103.5 && location.x < 265.5) {
if (location.y > 160 && location.y < 212) {
nonGameContent.drawButtons("hover2");
}
}
else{
nonGameContent.drawButtons("nonHover");
}
}
})},
In this fiddle you have click() and onmousemove() that are working.
I didn't understand well if you want to display button at the beginning or just when the mouse hovers somewhere on the future place of the button but it's a beginning :
http://jsfiddle.net/Akinaru/3a7g2/57/
Main modification :
canvas.onmousedown = nonGameContent.getMouseClick;
canvas.onmousemove = nonGameContent.getMouseOver;
to change the canvas rectangle color when you mouse over it use onmousemove to find if you are over it, then redraw the canvas with a different color rectangle
getMouseClick: function() {
window.onmousemove = function(e) {

Best way of making draggable element jump to cursor (and start drag) when mousedown on parent

I've got a home-made slider made from jQuery UI's draggable() function:
$("#petrolGauge .fuelBar .slider").draggable({
containment: "parent",
axis: "x",
drag:function(){
updValues();
},
start:function(){
$(this).css("background-color","#666");
},
stop:function(){
//checkForm();
$(this).css("background-color","#AAA");
}
});
This is for the following markup:
<div id="petrolGauge">
<input id="endPet" name="endPet" type="hidden" value="0">
How much fuel was left in the tank when you were finished? (Use the slider) <b>(~<span class="petLeft">0</span>%)</b>
<span class="mandatory">*</span><br />
<div class="fuelBar">
<div title="Drag" class="slider"></div>
</div>
This works a treat, when I click on the slider. But I'd like it so that when I click the fuel bar (the slider's parent) the slider not only starts dragging but also jumps to the cursor. I've achieved it by doing this:
$("#petrolGauge .fuelBar").on("mousedown",function(e){
slider = $("#petrolGauge .fuelBar .slider");
left = e.pageX-($(this).offset().left)-(slider.width()/2);
updValues();
slider.css("left",left).trigger(e);
});
Two problems with this:
Firstly, when clicking on the parent I get a couple of second's delay before the slider starts to drag? I've tried and tested this in Chrome and IE and both do it. Secondly if the cursor is less than half of the slider's width away from the edge of the parent, the slider will move to the outside of the parent. Wouldn't be hard to fix this with a couple of checking, but was wondering if there was another way? I'm suprised that draggable() doesn't have any parameters for this to be honest. I didn't want to use slider() if I could help it but if it's the only way, then it's the only way.
Here's a fiddle to work with.
The reason you get the delay is because you use .trigger() inside the .on() event which creates a big loop. As a result the loop slows down the moving process.
$("#petrolGauge .fuelBar").click(function (e) { // use click instead of mousedown
slider = $("#petrolGauge .fuelBar .slider");
left = e.pageX - ($(this).offset().left) - (slider.width() / 2);
if(left > 570) { left = 570; } else if(left < 0) { left = 0; }
// it looks like a draggable bug due to the manual position change, so use a small check
slider.css("left", left); // change the position first
updValues(); // then calculate and update the div
// no need to trigger the event a second time because it will loop until jQuery exceeds it's trigger limit.
});
Here's an updated FIDDLE
Updated answer
To make .slider move accordingly to the mouse movement when not directly dragged, bind a mousemove event to the mousedown and unbind it when mouseup. Then in .mousemove() you change the position of .slider.
var move = function (e) {
left = e.pageX - ($('#petrolGauge .fuelBar').offset().left) - (slider.width() / 2);
if (left > 570) {
left = 570;
} else if (left < 0) {
left = 0;
}
slider.css("left", left);
updValues();
};
var slider = $("#petrolGauge .fuelBar .slider");
$("#petrolGauge .fuelBar").mousedown(function (e) {
e.preventDefault();
left = e.pageX - ($(this).offset().left) - (slider.width() / 2);
if (left > 570) {
left = 570;
} else if (left < 0) {
left = 0;
}
slider.css("left", left)
$(this).bind('mousemove', move);
updValues();
}).mouseup(function () {
$(this).unbind('mousemove');
});

Categories