How to use Hammer.js for swiping? - javascript

So i've got hammer.js swipe to work on my div. the swipe region looks like this
https://imgur.com/ncW4nDB
so basically, i want the orange area to be able to swipe left/right and when it reaches the end (on both sides), it halts swiping.
the script and etc :
var containerDiv = document.getElementById('list-container');
var listDiv = document.getElementById('train-line-list');
// Create a manager to manager the element
var manager = new Hammer.Manager(listDiv);
// Create a recognizer
var Swipe = new Hammer.Swipe();
// Add the recognizer to the manager
manager.add(Swipe);
// Declare global variables to swiped correct distance
var deltaX = 0;
var deltaY = 0;
// Subscribe to a desired event
manager.on('swipe', function(e) {
deltaX = deltaX + e.deltaX;
var direction = e.offsetDirection;
var translate3d = 'translate3d(' + deltaX + 'px, 0, 0)';
if (direction === 4 || direction === 2) {
e.target.innerText = deltaX;
e.target.style.transform = translate3d;
}
});
<div id="list-container">
<div id="train-line-list">
<img id="" src="">
<img id="" src="">
</div>
#list-container{
z-index: 10;
position:fixed;
top:60%;
left:0;
width:100%;
height:40%;
}
#train-line-list{
width: 95%;
height: 95%;
top: 2%;
margin: 0 auto;
position: relative;
}
like i said, the swiping sort of works but the images disappear. why does this happen and how can i fix it? Also, the swiping is not very "reactive" in a way, like its slow. not natural. is there an alternative? or a better way to implement? Also, just realized, the images can be swiped as well ?? how do i "lock" the images. i just want the container of the images to be swiped.

Here is a working example
<html>
<head>
<style>
#box {
background-color: red;
height: 100px;
width: 100px;
margin-right: 10px;
}
#collection {
display: flex;
flex-direction: horizontal;
}
#container {
display: flex;
background-color: aqua;
padding: 50px 0px 50px 0px;
overflow: scroll;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>
</head>
<body>
<div id="container">
<div id="collection">
<div id="box"></div>
<div id="box"></div>
<div id="box"></div>
<div id="box"></div>
<div id="box"></div>
<div id="box"></div>
</div>
</div>
<script>
var container = document.getElementById("container");
var content = document.getElementById("collection");
var hammer = new Hammer(container);
var initialX = 0;
var deltaX = 0;
var offset = initialX + deltaX;
hammer.on("panleft panright", function(ev) {
deltaX = ev.deltaX;
offset = initialX + deltaX;
container.scroll(-offset, 0);
});
Hammer.on(container, "mouseup", function(e) {
initialX = offset;
});
</script>
</body>
</html>
You could replace the squares with your images.

Related

How to let the coodinates of the cursor follow the cursor when hovering over a rectangle?

The following code always shows the coordinates of the cursor below the cursor:
function showCoords(e) {
var x = event.clientX;
var y = event.clientY;
var coor = "(" + x + ", " + y + ")";
document.getElementById("box").innerHTML = coor;
var bx = document.getElementById("box");
bx.style.left = e.pageX - 50;
bx.style.top = e.pageY + 20;
}
function clearCoords() {
document.getElementById("box").innerHTML = "";
}
div.relative {
position: relative;
width: 400px;
height: 300px;
border: 1px solid black;
}
div.abs {
position: absolute;
top: 100px;
right: 50px;
width: 200px;
height: 100px;
background-color: yellow;
}
<body onmousemove="showCoords(event)">
<div class="relative">
<div class="abs" onmousemove="showCoords(event)" onmouseout="clearCoords()"></div>
</div>
<div id="box" style="width:100px; height:30px; position:absolute"></div>
</body>
I only want the coordinates to be visible when the mouse pointer is hovering over the yellow rectangle.
If I change <body onmousemove="showCoords(event)"> to <body>, the coordinates are never visible.
How do I get the coordinates be visible only when hovering over the yellow rectangle?
Move the onmousemove listener from the body to the element you want to listen on - div.abs in this case.
I'd recommend not using the onmousemove attribute, in favour of using an entirely javascript solution - just to keep javascript-y things together. Something like (untested)
var listenOn = document.querySelector(".abs");
listenOn.addEventListener("mousemove", ShowCoords);

Only the last draggable <div> element / JS function stops when released and not the previous?

I am having problems with the following code (heavily cut down version). essentially I am trying to make the two different windows draggable (via the title bar only). It works perfectly when there is only one window, however, once I add another - they're both draggable, but one (first called in the code) won't let go.
makeDragable('#handle_1', '#moveable_1')
makeDragable('#handle_2', '#moveable_2')
So '#handle_1', '#moveable_1' would not be dropped after releasing the mouse.
This is my first time using JS - and html/css properly so I am sorry if this is a fundamental error. The JS is not my code. I am assuming the problem lies here:
/* End dragging */
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
But just can't work it out. I'd prefer to use this code as it allows me to only allow the main bar to be draggable rather than the entire window. I apologise if my post is convoluted, any critique would be highly appreciated as this is my first Stack post.
Thanks in advance!
body {
background-image: url('https://www.betaarchive.com/imageupload/1304990899.or.90622.png');
font-family: "Pixelated MS Sans Serif",Arial;
font-size: 11px;
}
.grid-container {
display: grid;
gap: 10px;
font-size: 13px;
margin: 15px 35px 35px 35px;
}
.grid-container > div {
text-align: center;
margin: 10px 0px 10px 0px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/xp.css"/>
<link rel="stylesheet" href="styles_login.css"/>
<title>Login Screen</title>
</head>
<body>
<div id="moveable_1">
<div class="window" style="width: 350px; position: absolute; left: 100px; top: 150px;">
<div id="handle_1" class="title-bar">
<div class="title-bar-text">Login Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test</p>
</div>
</div>
</div>
</div>
<div id="moveable_2">
<div class="window" style="width: 650px; position: absolute; left: 450px; top: 300px;">
<div id="handle_2" class="title-bar">
<div class="title-bar-text">Chat Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test 2</p>
</div>
</div>
</div>
</div>
</body>
<script src="./renderer.js"></script>
<script> // Draggable Content JS
function makeDragable(dragHandle, dragTarget) {
let dragObj = null; //object to be moved
let xOffset = 0; //used to prevent dragged object jumping to mouse location
let yOffset = 0;
document.querySelector(dragHandle).addEventListener("mousedown", startDrag, true);
document.querySelector(dragHandle).addEventListener("touchstart", startDrag, true);
/*sets offset parameters and starts listening for mouse-move*/
function startDrag(e) {
e.preventDefault();
e.stopPropagation();
dragObj = document.querySelector(dragTarget);
dragObj.style.position = "absolute";
let rect = dragObj.getBoundingClientRect();
if (e.type=="mousedown") {
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
} else if(e.type=="touchstart") {
xOffset = e.targetTouches[0].clientX - rect.left;
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
/*Drag object*/
function dragObject(e) {
e.preventDefault();
e.stopPropagation();
if(dragObj == null) {
return; // if there is no object being dragged then do nothing
} else if(e.type=="mousemove") {
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
} else if(e.type=="touchmove") {
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
/*End dragging*/
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
}
makeDragable('#handle_1', '#moveable_1')
makeDragable('#handle_2', '#moveable_2')
</script>
</html>
Link to original code
Your problem was that you were storing a dragObj for each "window" inside the function call (captured via a closure). Hence when you switched to the other one, it all went a bit wrong. Moving the
let dragObj = null; line outside of your MakeDraggable function makes it work correctly.
You would be better developing a draggable/window class that encapsulates each window. You could then store a static variable that holds the dragObj there (rather than making it wholly global, as we have it now.
Let me know if you need any further help.
body {
background-image: url('https://www.betaarchive.com/imageupload/1304990899.or.90622.png');
font-family: "Pixelated MS Sans Serif",Arial;
font-size: 11px;
}
.grid-container {
display: grid;
gap: 10px;
font-size: 13px;
margin: 15px 35px 35px 35px;
}
.grid-container > div {
text-align: center;
margin: 10px 0px 10px 0px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/xp.css"/>
<link rel="stylesheet" href="styles_login.css"/>
<title>Login Screen</title>
</head>
<body>
<div id="moveable_1">
<div class="window" style="width: 350px; position: absolute; left: 100px; top: 150px;">
<div id="handle_1" class="title-bar">
<div class="title-bar-text">Login Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test</p>
</div>
</div>
</div>
</div>
<div id="moveable_2">
<div class="window" style="width: 650px; position: absolute; left: 450px; top: 300px;">
<div id="handle_2" class="title-bar">
<div class="title-bar-text">Chat Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test 2</p>
</div>
</div>
</div>
</div>
</body>
<script src="./renderer.js"></script>
<script> // Draggable Content JS
let dragObj = null; //object to be moved
function makeDraggable(dragHandle, dragTarget) {
let xOffset = 0; //used to prevent dragged object jumping to mouse location
let yOffset = 0;
document.querySelector(dragHandle).addEventListener("mousedown", startDrag, true);
document.querySelector(dragHandle).addEventListener("touchstart", startDrag, true);
/*sets offset parameters and starts listening for mouse-move*/
function startDrag(e) {
e.preventDefault();
e.stopPropagation();
dragObj = document.querySelector(dragTarget);
dragObj.style.position = "absolute";
let rect = dragObj.getBoundingClientRect();
if (e.type=="mousedown") {
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
} else if(e.type=="touchstart") {
xOffset = e.targetTouches[0].clientX - rect.left;
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
/*Drag object*/
function dragObject(e) {
e.preventDefault();
e.stopPropagation();
if(dragObj == null) {
return; // if there is no object being dragged then do nothing
} else if(e.type=="mousemove") {
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
} else if(e.type=="touchmove") {
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
/*End dragging*/
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
}
makeDraggable('#handle_1', '#moveable_1')
makeDraggable('#handle_2', '#moveable_2')
</script>
</html>

jQuery hover is too slow

Please run the snippet and drag you mouse over the bar to make it red.
If you drag the mouse very slowly, you will fill it red, but if you move it fast, there will be white holes in it.
How to fix it? (the white holes)
I want to make a bar divided into 500 parts and if you hover it, it becomes red and being able to drag fast and fill it without holes.
Any help appreciated :)
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
$(this).css("background-color","red");
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
With your design one way would be to iterate over the first to your current hovered element and fill it, which would lead no spaces. That said you may want to consider using the HTML5 Canvas and drawing a rectangle from 0 to your mouse position, which will perform significantly faster.
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
var self = this;
$("#line").children().each(function(){
$(this).css("background-color","red");
if(this == self) return false;
});
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Edit
Below is an example doing the same task but using the HTML 5 Canvas:
$("#line").mousemove(function(e){
var canvas = $(this)[0];
var ctx = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect()
var x = e.clientX - rect.left;
ctx.fillStyle="red";
ctx.fillRect(0, 0, x, canvas.height);
});
#line{ background-color: #ddd; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="line" width=500 height=50 ></canvas>
This is another approach with nextUntil to select siblings..
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
line.on( 'mouseover', function(ev){
$('.tile').first().nextUntil( $('.tile').eq(ev.pageX) ).css("background-color","red");
});
line.on( 'mouseleave', function(ev){
$('.tile').css("background-color","#ddd");
});
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Another solution makes use of jQuery's mousemove method. This allows the bar to go both forward and backwards, simply following the cursors position.
This detects movement inside of the div, then I calculate the position of the cursor within the div as a percentage and apply it as the width of the red bar.
$( ".bar" ).mousemove(function( event ) {
var xCord = event.pageX;
xPercent = (xCord + $('.pct').width()) / $( document ).width() * 100;
$('.pct').width(xPercent+'%');
});
.bar{
background:'#999999';
width:50%;
height:50px;
}
.pct{
height:100%;
background:red;
width:0%;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js">
</script>
<div class="bar" style="background:#999999">
<div class="pct"></div>
</div>

Moving css scaled div using javascript

I have posted my problem at http://jsfiddle.net/ugnf4/ as it would be make it easier.
Below is my html / javascript code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="mainContainer">
<div id="pageContainer" style="background: #cdcdcd;"></div>
</div>
<style>
BODY {
margin: 0px;
padding: 0px;
}
#pageContainer {
position: relative;
margin: 10px auto;
-webkit-transform-origin:50% 20%;
-webkit-transform:scale(1.37);
width: 1218px;
height: 774px;
border: 1px solid #000000;
}
#mainContainer {
width: 100%;
overflow: hidden;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</script>
<script type="text/javascript">
$(document).ready(function() {
setHeight();
$(window).resize(setHeight);
});
function setHeight()
{
$('#mainContainer').css({'height': $(window).height()});
}
$('#mainContainer').mousemove(function (e) {
});
</script>
</body>
</html>
Currently #mainContainer div has overflow hidden as i dont want to show scroll bars and #pageContainer div (inner div) is scaled at 1.37 using css3, as in certain cases based on screen / browser width height #pageContainer's content would be hidden because of overflow hidden.
I want to code javascript so that if somebody moves cursor in #mainContainer, based on position of mouse X and Y co-ordinates I would like to move #pageContainer so that similar position of #pageContainer would be visible (I hope it is clear).
I m having problem as I m using -webkit-transform-origin, unable to understand how to move #pageContainer around with respect to mouse co-ordinates of #mainContainer.
UPDATE:
I m looking something like what happens in issuu.com website when you open an ebook and zoom it more than the browser size (Should make it more clear)
I m looking for algo or pointer how to achieve it (how to calculate it) not necessarily a working script.
How can this be achieved.
Below is working html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="mainContainer">
<div id="pageContainer" >
<div id="pageContainerInner"style="background: #cdcdcd;">
</div>
</div>
<style>
BODY {
margin: 0px;
padding: 0px;
}
#pageContainer {
margin: 10px auto;
-webkit-transform-origin:50% 20%;
-webkit-transform:scale(1.37);
width: 1218px;
height: 774px;
}
#mainContainer {
width: 100%;
overflow: hidden;
}
#pageContainerInner {
position: relative;
width: 1218px;
height: 774px;
border: 1px solid #000000;
top: 0;
left: 0;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</script>
<script type="text/javascript">
var pageWidth = 1220;
var pageHeight = 776;
var scale = 1.37;
var scaledDelta = 5; //Percentage mouse position approximation
$(document).ready(function() {
setHeight();
$(window).resize(setHeight);
});
function setHeight()
{
$('#mainContainer').css({'height': $(window).height()});
}
$('#mainContainer').mousemove(function (e) {
// Calculate the offset of scaled Div
var offsetX = $('#pageContainer').offset().left;
var offsetY = $('#pageContainer').offset().top;
// Calculate div origin with respect to screen
var originX = (-1 * offsetX) / scale;
var originY = (-1 * offsetY) / scale;
var wWdt = $(window).width();
var wHgt = $(window).height();
// Now convert screen positions to percentage
var perX = e.pageX * 100 / wWdt;
var perY = e.pageY * 100 / wHgt;
// Div content which should be visible
var pageX = perX * pageWidth / 100;
var pageY = perY * pageHeight / 100;
// Calculate scaled divs new X, Y offset
var shiftX = (originX - pageX) + (e.pageX / scale);
var shiftY = (originY - pageY) + (e.pageY / scale);
$('#pageContainerInner').css({'left': shiftX+'px', 'top': shiftY+'px'});
});
</script>
</body>
</html>
Hope this will help others.
I have posted a probable solution at http://jsfiddle.net/PYP8c/.
Below are the modified styles for your page.
BODY {
margin: 0px;
padding: 0px;
}
#mainContainer {
width: 100%;
overflow: hidden;
position: relative;
margin: 10px auto;
-webkit-transform-origin:50% 20%;
-webkit-transform:scale(1.37);
width: 1218px;
height: 774px;
border: 1px solid #000000;
}
#pageContainer {
position:absolute;
top:0px;
}
This is the javascript code for the same.
$(document).ready(function() {
//setHeight();
//$(window).resize(setHeight);
});
function setHeight()
{
$('#mainContainer').css({'height': $(window).height()});
}
$('#mainContainer').mousemove(function (e) {
var contentHeight = $("#pageContainer").height();
var minTop = 774 - contentHeight;
if(minTop>0)
minTop = 0;
var currTop = ((e.pageY-10)/774.0)*(minTop);
document.getElementById("pageContainer").style.top = currTop+'px';
});
Its just a demo on how you could get the text to move based on the mouse coordinates.
You could make a lot of changes, like adding a scrollbar that fades which gives the user a feedback about how much content is still available in both the vertical directions.
Also I have used hard coded values for height, but in your final version I would recommend you get the height of the mainContainer division dynamically.

How can I add limits to a custom scrolling element?

I have a pretty huge image being displayed in a container, the image stretches with the view port as it gets resized, but as the image is so big I have added scroller buttons to the side of the page, up and down, the only problem I have now is that when I press up or down there is no limit, the user can keep going until the image is completely out of sight, how can I stop that from happening?
Here is the code I have thus far,
HTML:
<body>
<div id="wrapper">
<div class="scroll top"></div>
<div id="content">
<div id="zoom_container">
<img id="image" src="8052x2000px" />
</div>
</div>
<div class="scroll bot"></div>
</div>
</body>
CSS:
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#wrapper {
overflow: hidden;
height: 100%;
max-height: 100%;
}
#content {
min-height: 100% !important;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#image {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
jQuery:
//side scroller bar
$('.scroll').live('click', function(){
var direction = $(this).hasClass('top');
var img_pos_top = $("#zoom_container img").position().top;
var inc = 0;
inc = $("#zoom_container img").height() / 10;
if(direction)
{
inc = $("#zoom_container img").position().top + inc;
}
else
{
inc = $("#zoom_container img").position().top - inc;
}
$("#zoom_container img").css({ position: 'relative',top: inc });
});
so as you can see I am incrementing or decrementing the top positioning of the image by 10% of it's height each click, how can I make sure the top of the image will never go further down than the top of the viewport and the bottom of the image never further up than the bottom of the viewport?
Is there a better more efficient way of achieving the same result?
Have a try this one.
<html>
<head>
<title>Canvas Sizing</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
var canvasContext;
resizeCanvas();
$(window).resize(function() { resizeCanvas() });
function resizeCanvas()
{
var w = window.innerWidth - 40;
var h = window.innerHeight - 40;
var canvasString = '<canvas id="mainCanvas" width="' + w + '" height="' + h + '">Canvas is not supported</canvas>';
$('#contentholder').empty();
$(canvasString).appendTo('#contentholder');
canvasContext = $('#mainCanvas').get(0).getContext('2d');
drawOnCanvas();
}
function drawOnCanvas()
{
var x = 15;
var y = 35;
canvasContext.font = "30pt serif";
canvasContext.fillStyle="#0f0";
canvasContext.fillText("Hello World!", x, y);
}
});
</script>
<style>
#mainCanvas
{
background-color: #000;
border: solid 3px #0F0;
}
body
{
background: #000;
}
#contentholder
{
width: 99%;
height: 99%;
margin: auto;
}
</style
</head>
<body>
<div id="contentholder"></div>
</body>

Categories