I wanted to change photos in a modal window by swiping my finger in two directions, and this piece of code from the Internet helped:
function swipedetect(el, callback) {
var touchsurface = el,
swipedir,
startX,
startY,
distX,
distY,
threshold = 150, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 300, // maximum time allowed to travel that distance
elapsedTime,
startTime,
handleswipe = callback || function (swipedir) {}
touchsurface.addEventListener('touchstart', function (e) {
var touchobj = e.changedTouches[0]
swipedir = 'none'
dist = 0
startX = touchobj.pageX
startY = touchobj.pageY
startTime = new Date().getTime() // record time when finger first makes contact with surface
e.preventDefault()
}, false)
touchsurface.addEventListener('touchmove', function (e) {
e.preventDefault() // prevent scrolling when inside DIV
}, false)
touchsurface.addEventListener('touchend', function (e) {
var touchobj = e.changedTouches[0]
distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
elapsedTime = new Date().getTime() - startTime // get time elapsed
if (elapsedTime <= allowedTime) { // first condition for swipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint) { // 2nd condition for horizontal swipe met
swipedir = (distX < 0) ? 'left' : 'right' // if dist traveled is negative, it indicates left swipe
} else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint) { // 2nd condition for vertical swipe met
swipedir = (distY < 0) ? 'up' : 'down' // if dist traveled is negative, it indicates up swipe
}
}
handleswipe(swipedir)
e.preventDefault()
}, false)
};
But when I wanted to use it this way:
let modall = document.getElementById('modall');
swipedetect(modall, function(swipedir) {
if (swipedir == 'right') plusSlides(-1);
if (swipedir == 'left') plusSlides(1);
});
closeModal() function and others in this modal stopped working. Could somebody say why?
P.S closeModal() and other functions are executed only when I click on some element. Everything was working before I pasted swiping code. Swiping code only works on touch screens, but it doesn't work on a computer, so closeModal() works without problems on a PC.
Related
I've created a slider. I have a touch event allow the user to slide using touch but the mouse event isn't working.
I'd like a mouse drag option as a fall back option. I thought a mouse event would work as standard.
I have the touch working but I can't get the mouse touch to work with it.
Here's the code. What am I doing wrong?
function swipedetect(el, callback){
var touchsurface = el,
swipedir,
startX,
startY,
distX,
distY,
threshold = 50, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 300, // maximum time allowed to travel that distance
elapsedTime,
startTime,
handleswipe = callback || function(swipedir){}
touchsurface.addEventListener('touchstart', function(e){
var touchobj = e.changedTouches[0]
swipedir = 'none'
dist = 0
startX = touchobj.pageX
startY = touchobj.pageY
startTime = new Date().getTime() // record time when finger first makes contact with surface
e.preventDefault()
}, false)
// Bind the functions...
el.onmousedown = function () {
_drag_init(this);
return false;
};
touchsurface.addEventListener('touchmove', function(e){
e.preventDefault() // prevent scrolling when inside DIV
}, false)
touchsurface.addEventListener('touchend', function(e){
var touchobj = e.changedTouches[0]
distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
elapsedTime = new Date().getTime() - startTime // get time elapsed
if (elapsedTime <= allowedTime){ // first condition for awipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
swipedir = (distX < 0)? 'left' : 'right' // if dist traveled is negative, it indicates left swipe
}
else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe
}
}
handleswipe(swipedir)
e.preventDefault()
}, false)
}
//USAGE:
var input = Inputs.Input;
const el = input.getDOMElement();
swipedetect(el, function(swipedir){
if (swipedir =='left') {
// alert(swipedir);
Outputs.swipeLeft()
}
else if (swipedir === 'right') {
// alert(swipedir);
Outputs.swipeRight()
}
});
Outputs.Done ();
if the mouse goes out of canvas and mouse move in -x -y axis , I want disable pan.
how can i disable viewpoint -x -y axis.
this is my code.
var panning = false;
canvas.on('mouse:up', function (e) {
if (isPaningMode) {
panning = false;
}
});
canvas.on('mouse:out', function (e) {
if (isPaningMode) {
panning = false;
}
});
canvas.on('mouse:down', function (e) {
if (isPaningMode) {
panning = true;
}
});
canvas.on('mouse:move', function (e) {
canvas.selection = !isPaningMode;
if (isPaningMode && e && e.e && panning) {
var units = 10;
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
}
});
Thank you, sorry i cant speak english well. :(
Edit
my canvas is size : 800x800
I just want to use the red striped area. I do not want to use sections with X. I do not want them to be shown by scrolling in these fields. I did what I said for the objects. But I could not do it for panning. In short, I want to panning only in the direction of the arrow.
Make sure you're using the latest version of FabricJS, they are continually improving it. I noticed in the past that canvas.on('mouse:out') was targeting objects and not the canvas.
Here's a working JSFiddle, https://jsfiddle.net/rekrah/bvgLvd3u/.
I'm assuming this was the issue because you were already disabling panning on mouse-out of the canvas.
canvas.on('mouse:out', function(e) {
if (isPaningMode) {
panning = false;
}
});
Let me know if I miss understood your English - which is very good, by-the-way!
After Your Edit
Bulk of the change is in the mouse-move event. In summary: Keeping track of the distance moved so we know where we started from, to get back to (with a tweak, if needed) - hope that makes sense???
var deltaX = 0;
var deltaY = 0;
canvas.on('mouse:move', function(e) {
if (isPaningMode && e && e.e && panning) {
moveX = e.e.movementX;
if (deltaX >= 0) {
deltaX -= moveX;
if (deltaX < 0) {
moveX = deltaX + moveX;
deltaX = 0;
}
}
moveY = e.e.movementY;
if (deltaY >= 0) {
deltaY -= moveY;
if (deltaY < 0) {
moveY = deltaY + moveY;
deltaY = 0;
}
}
if (deltaX >= 0 && deltaY >= 0) {
canvas.relativePan(new fabric.Point(moveX, moveY));
}
}
});
Here's a new, updated, and working :) JSFiddle, https://jsfiddle.net/rekrah/r3gm3uh9/.
I've written a function in Javascript to make images draggable within a container. Even if the image is enlarged it can be dragged all over the screen without disappearing from it. My function relies heaving on using style.top and style.left. Now I've heard that using translate3d might provide better performance. This is interesting because I changed my image scale function, which uses a slider, to scale3d and the scaling is clearly smoother, no doubt. So could anyone help me convert this function I've written to use translate3d? I've tried and tried but have kept failing. Many Thanks:
EDIT: I put up a jsfiddle
https://jsfiddle.net/bx4073tr/
Please note that imgRect is the parent div while img is the image itself (it's in an img tag contained in the div).
function makeImageDraggable(event) {
// Make an image draggable but within bounds of container
let overflow_vertical = false;
let overflow_horizontal = false;
// bounding rectangles to hold image and imageContainer
let imgRect = img.getBoundingClientRect();
let imgContainerRect = imageContainer.getBoundingClientRect();
// find out if image overflows it's container div
// check for vertical overflow, getBoundingClientRect().height will get the real height after the image is scaled
if ( imgRect.height > imageContainer.offsetHeight ) {
overflow_vertical = true;
}
// check for horizontal overflow
if ( imgRect.width > imageContainer.offsetWidth ) {
overflow_horizontal = true;
}
// if there is no overflow, either horizontal or vertical, then do absolutely nothing
if (!overflow_horizontal && !overflow_vertical) {
// nothing to do
} else {
// otherwise make image draggable
event = event || window.event;
// get initial mouse position
let startX = event.clientX;
let startY = event.clientY;
// get position of image to be dragged
let offsetX = pixelToFloat(img.style.left);
let offsetY = pixelToFloat(img.style.top);
// add onmousemove event now we are sure user has initiated a mousedown event
window.onmousemove = function(mousemove_event) {
if (mousemove_event == null) {
mousemove_event = window.event;
}
// calculate bounds so that image does not go off the page
// if there is an overflow, the image will be bigger than the container
// so we need to find the maximum distance we can go upwards, downwards and sideways
// using img.getBoundingClientRect, we can get the width of the scaled image, we also get the width of the container
// divide it by 2 so we can move the same number of pixels in either direction
// max right and left
let max_right = -1 * ( ((imgRect.right - imgRect.left) - (imgContainerRect.right - imgContainerRect.left))/2 );
// should be a positive number
let max_left = -1 * (max_right);
// max bottom and top
let max_bottom = -1 * ( ((imgRect.bottom - imgRect.top) - (imgContainerRect.bottom - imgContainerRect.top))/2 );
// should be a positive number
let max_top = -1 * (max_bottom);
// Dragging image left and right
if (!overflow_horizontal) {
} else {
let scrollX = (offsetX + mousemove_event.clientX - startX);
// img.style.left will keep increasing or decreasing, check if it approaches max_left or max_right
if (scrollX >= max_left || scrollX <= max_right) {
//return false;imageContainer.style.webkitTransform = 'translate3d(' + newX + 'px,' + newY + 'px, 0)';
} else {
if (scrollX < max_left) { img.style.left = min(scrollX, max_left) + 'px'; }
if (scrollX > max_right) { img.style.left = max(scrollX, max_right) + 'px'; }
}
}
// Dragging image top to bottom
if (!overflow_vertical) {
} else {
let scrollY = (offsetY + mousemove_event.clientY - startY);
// as an expanded image is pulled downwards, img.style.top keeps increasing to approach max_top
// if it reaches max top, simply do nothing, else keep increasing
// check for both conditions, approaching max_top and approaching max_bottom
if (scrollY >= max_top || scrollY <= max_bottom) {
// return false;
} else {
if (scrollY < max_top) { img.style.top = min(scrollY, max_top) + 'px'; }
if (scrollY > max_bottom) { img.style.top = max(scrollY, max_bottom) + 'px'; }
}
}
// return
return false;
}
}
// cancel mousemove event on mouseup
window.onmouseup = function(mouseup_event) {
window.onmousemove = null;
// Should not return false as it will interfere with range slider
}
// return false
return false;
}
Works now.
See makeDraggable method in the fiddle below:
https://jsfiddle.net/daibatzu/0u74faz6/6/
All you have to do is add this function to the event listener for the image like:
var img = document.getElementById('myImage');
img.addEventListener('mousedown', function(event) { makeDraggable(event); });
Code
function makeDraggable(event) {
// get bounding rectangle
let imgRect = img.getBoundingClientRect();
let parentRect = parent.getBoundingClientRect();
// check overflow
let overflow_horizontal = (imgRect.width > parent.offsetWidth ? true : false);
let overflow_vertical = (imgRect.height > parent.offsetHeight ? true : false);
// get start position
let startX = event.pageX - translateX, startY = event.pageY - translateY;
let max_left = parentRect.left - imgRect.left;
let max_top = parentRect.top - imgRect.top;
window.onmousemove = function(evt) {
// set event object
if (evt == null) { evt = window.event; }
// Say max_left is 160px, this means we can only translate from 160px to -160px to keep the image visible
// so we check if the image moves beyond abs(160), if it does, set it to 160 or -160 depending on direction, else, let it continue
translateX = (Math.abs(evt.pageX - startX) >= max_left ? (max_left * Math.sign(evt.pageX - startX)) : (evt.pageX - startX));
translateY = (Math.abs(evt.pageY - startY) >= max_top ? (max_top * Math.sign(evt.pageY - startY)) : (evt.pageY - startY));
// check if scaled image width is greater than it's container. if it isn't set translateX to zero and so on
translateX = overflow_horizontal ? translateX : 0, translateY = overflow_vertical ? translateY : 0;
// translate parent div
parent.style['-webkit-transform'] = 'translate(' + translateX + 'px, ' + translateY + 'px)';
// return
return false;
}
window.onmouseup = function(evt) {
// set mousemove event to null
window.onmousemove = null;
}
return false;
};
I have this carousel type item:
http://codepen.io/r3plica/pen/xOpzqK?editors=1111
What I am trying to do now, is change it's behaviour. I would like the drag to know the speed of the mouse and try to mimic the scroll to that speed. When I let go of the mouse I want the slider to continue sliding but slow down over a period of time.
My first step was trying to get the actual speed of the mouse, so I did this:
var eventHandler = function (e) {
var event = _options.event;
var timestamp = new Date().getTime();
var touches = event.touches = e.originalEvent !== undefined ? e.originalEvent.touches : null;
if (e.type === 'mousedown') {
// Assign the timer to our event
event.timer = $timeout(function () {
// If we have not already enabled the event
if (!event.enabled) {
// Set our startX and the time
event.startX = touches ? touches[0].pageX : e.clientX;
event.timestamp = timestamp;
//console.log(event);
// Enable our drag
event.enabled = true;
}
}, 100);
}
if (e.type === 'mousemove' && event.enabled) {
// Get our old position
var x = event.currentX;
//console.log(timestamp);
//console.log(event.timestamp);
//console.log('calc', timestamp - event.timestamp);
// Update our current position and speed
event.currentX = touches ? touches[0].pageX : e.clientX;
event.distance = event.currentX - (x || event.startX);
event.time = timestamp - event.timestamp;
event.timestamp = timestamp;
event.speed = (event.distance / event.time) * $window.innerWidth;
//console.log('distance', event.distance);
//console.log('time in seconds', event.time);
//console.log('speed', event.speed);
//console.log('------');
// Work out our offset
var offset = event.currentX / $window.innerWidth;
console.log(offset);
// If we have not started
if (!event.started) {
// Set our initial start position
event.xOffset = offset;
// Initial our position
event.oldX = event.pageX;
// Set to started
event.started = true;
}
// Udpate our position
event.pageX = (offset - event.xOffset) + event.oldX;
// Set our new offset
event.xOffset = offset;
// Update our element
_updateDragElement(_options.element, event);
// Update our old position
event.oldX = event.pageX;
}
if (['mouseup', 'mouseout'].indexOf(e.type) > -1) {
// Clear our timer
$timeout.cancel(event.timer);
//console.log(event);
// If our data is set
if (event.enabled) {
// Unset it
event.enabled = false;
}
// Stop the drag
event.start = false;
}
}
I will break this down into the events
Mouse down
As you can see from the eventHandler when the mousedown event is triggered, a start position startX is recorded along with the current timestamp.
Mouse move
When the mousemove event is triggered I check to see if we are already moving by getting the value in currentX. I then set currentX, the distance travelled (current position minus the last position OR the start position if there is no current position.) Then I work out the time and record the current timestamp and finally I work out the speed.
I then get the xOffset by dividing currentX by the width of the window.
If the animation has not started I set the xOffset and set the oldX to the current pageX and then I start the animation.
The pageX is worked out by xOffset minus the current xOffset plus the oldX, then I update the new xOffset.
Then I update the element with the new transform and finally set my oldX to the current pageX.
Mouse up
For this I just disable and stop the animation.
Problem
The problem I have is that the speed is very low, so the animation doesn't work well.
I decided to multiple the speed by the window width but the animation is no better because it just jerks around.
I think I am doing my calculations incorrectly so I was hoping someone could take a look and give me some advice.
I checked your codepen, your calculation looks fine. Only transition property seems to be missing for the scrolling element, try giving transition property to .pk-slider-base class.
.pk-slider .pk-slider-base {
-webkit-transition: all 2s ease;
transition: all 2s ease;
}
You can also try adding transition using Javascript in your updateView().
Please see below:
function updateView() {
"use strict";
finalX = pageX * mySpeed;
console.log('X', pageX);
console.log('speed', mySpeed);
yourTrans = 'translateX(' + finalX + 'px)';
yourElement.style.transform = yourTrans;
/*Adding transition*/
yourElement.style.WebkitTransition = "all 2s";
yourElement.style.transition = "all 2s";
}
I'm playing a bit with AMI Medical Imaging (AMI) JS ToolKit. Is there a way to move the windowing to a mouse event like right click & move?
I know that it's possible to change window/level with the menus on the examples, but I would like to change the controller to do it moving the mouse.
Thanks!
To control the window/level by moving the mouse you will have to listen to the mousemouve event then update the stackHelper -> slice -> windowWidth/Center as you wish.
You could enable window/level if the user press shift:
var drag = {
x: null,
y: null
}
var shiftDown = false;
function onKeyPressed(event){
shiftDown = event.shiftKey;
if(!shiftDown){
drag.x = null;
drag.y = null;
}
}
container.addEventListener('keydown', onKeyPressed);
container.addEventListener('keyup', onKeyPressed);
Then update the window/level on mouse move:
function onMouseMove(event){
if(!shiftDown || !stack || !stackHelper){
return;
}
if(drag.x === null){
drag.x = event.offsetX;
drag.y = event.offsetY;
}
var threshold = 15;
var dynamicRange = stack.minMax[1] - stack.minMax[0];
dynamicRange /= container.clientWidth;
if(Math.abs(event.offsetX - drag.x) > threshold){
// window width
stackHelper.slice.windowWidth += dynamicRange * (event.offsetX - drag.x);
drag.x = event.offsetX;
}
if(Math.abs(event.offsetY - drag.y) > threshold){
// window center
stackHelper.slice.windowCenter -= dynamicRange * (event.offsetY - drag.y);
drag.y = event.offsetY;
}
}
container.addEventListener('mousemove', onMouseMove);
See a live demo at (shift + mouse move to control the window level):
http://jsfiddle.net/vabL3qo0/41/