get jquery touch position every x milliseconds - javascript

is there a way to get the touch position in a touchmove event every x milliseconds and then execute a function, when the x-coordinate at the moment and the one at the start are differing e.g. 50px?
Thanks

Try the below ;
$('document').ready(function() {
var touch,
action,
diffX,
diffY,
endX,
endY,
startX,
startY,
timer,
timerXseconds = 500, // Change to the Time(milliseconds) to check for touch position
xDifferenceX = 50, // Change to difference (px) for x-coordinates from starting point to run your function
xDifferenceY = 50; // Change to difference (px) for y-coordinates from starting point
function getCoord(e, c) {
return /touch/.test(e.type) ? (e.originalEvent || e).changedTouches[0]['page' + c] : e['page' + c];
}
function testTouch(e) {
if (e.type == 'touchstart') {
touch = true;
} else if (touch) {
touch = false;
return false;
}
return true;
}
function onStart(ev) {
if (testTouch(ev) && !action) {
action = true;
startX = getCoord(ev, 'X');
startY = getCoord(ev, 'Y');
diffX = 0;
diffY = 0;
timer = window.setInterval(checkPosition(ev), timerXseconds); // get coordinaties ever X time
if (ev.type == 'mousedown') {
$(document).on('mousemove', onMove).on('mouseup', onEnd);
}
}
}
function onMove(ev) {
if (action) {
checkPosition(ev)
}
}
function checkPosition(ev) {
endX = getCoord(ev, 'X');
endY = getCoord(ev, 'Y');
diffX = endX - startX;
diffY = endY - startY;
// Check if coordinates on Move are Different than Starting point by X pixels
if (Math.abs(diffX) > xDifferenceX || Math.abs(diffY) > xDifferenceY) {
// console.log('Start is :' + startX + ' End is : ' + endX + 'Difference is : ' + diffX);
$(this).trigger('touchend');
// here Add your function to run...
}
}
function onEnd(ev) {
window.clearInterval(timer);
if (action) {
action = false;
if (ev.type == 'mouseup') {
$(document).off('mousemove', onMove).off('mouseup', onEnd);
}
}
}
$('#monitor')
.bind('touchstart mousedown', onStart)
.bind('touchmove', onMove)
.bind('touchend touchcancel', onEnd);
});
body {
margin: 0;
padding: 0;
}
#monitor {
height: 500px;
width: 500px;
position: relative;
display: block;
left: 50px;
top: 50px;
background: green;
}
.box {
position: absolute;
top: 0;
left: 0;
right: 0;
text-align: center;
font-weight: bold;
bottom: 0;
background: white;
width: 50px;
height: 50px;
margin: auto;
font-size: 16px;
line-height: 23px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='monitor'>
<div class='box'>start here</div>
</div>
Read this post for a more detailed answer

This can be done in a few functions.
The first function is called when there is a movement of the touch event, this event stores the x and y of the touch in a separate variable.
Then we have a function that runs every X miliseconds, this function gets the x and y from the move event and dispatches then to your code.
Functions 3, 4 and 5 are used to handle the start, stop and cancel dragevents, and start/stop the second function:
var timerid;
var x;
var y;
var tick = 0;
function handleStart(evt) {
console.log("handleStart");
evt.preventDefault();
timerid = window.setInterval(timer, 50); // Replace 50 here with X
}
function handleEnd(evt) {
console.log("handleEnd");
evt.preventDefault();
window.clearInterval(timerid);
}
function handleCancel(evt) {
console.log("handleCancel");
evt.preventDefault();
window.clearInterval(timerid);
}
function handleMove(evt) {
console.log("handleMove");
evt.preventDefault();
// Select last point:
var point = evt.changedTouches[evt.changedTouches.length - 1];
x = point.pageX;
y = point.pageY;
}
function timer() {
console.log("timer");
tick++;
document.getElementById("output").innerHTML = "tick: " + tick + " x: " + x + " y:" + y;
}
var el = document.getElementById("canvas");
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchend", handleEnd, false);
el.addEventListener("touchcancel", handleCancel, false);
el.addEventListener("touchmove", handleMove, false);
<canvas id="canvas" width="300" height="300" style="border:solid black 1px;"></canvas>
<p id=output></p>
As long as the user is pressing the screen, the code will print out the x and the y coordinate to the screen. You can also integrate the reading of the x and y into your existing game loop instead of having a separate function if that is needed for your project.

Take a look at hammer.js, it has exactly what you need. It supports "touchmove" called pan, that is being called every few milliseconds when you pan. Also there is a threshold property which determine a length in pixels you have to pan before recognizing it as a pan.

Related

Move player using keyboard in javascript

I am making a web game (not with webGL, but with html elements) and I need to move character with WASD keys.
I tried these things:
Used event listeners keydown and keyup.
Problem is that it is unresponsive and doesnt work really well when multiple keys are pressed simultaneously
Used setInterval(20ms) and event listeners.
On my stronger laptop everything works fine, but I feel like it is using insane amount of cpu power because my laptop starts sounding like a plane. On weaker laptop it wasn't working as well as first one, it was choppy and laggy
keyDict = {}
document.addEventListener('keydown', key => keyDict[key.code] = true);
document.addEventListener('keyup', key => keyDict[key.code] = false);
moveID = setInterval(move, 20)
function move()
{
if(!finished)
{
newDirs = [0,0]
//Left
if(keyDict.ArrowLeft == true)
{
newDirs[0] -= 1;
}
//Right
if(keyDict.ArrowRight == true)
{
newDirs[0] += 1;
}
//Up
if(keyDict.ArrowUp == true)
{
newDirs[1] -= 1;
}
//Down
if(keyDict.ArrowDown == true)
{
newDirs[1] += 1;
}
map.updateDir(newDirs);
}
}
Used requestAnimationFrame and event listeners.
On stronger laptop it looks like it utilizes 144 fps and its even more smoother, but sometimes it doesn't even respond to my controls. My laptop still sounds as it is working too hard
keyDict = {}
document.addEventListener('keydown', key => keyDict[key.code] = true);
document.addEventListener('keyup', key => keyDict[key.code] = false);
requestAnimationsFrame(move)
function move()
{
same code...
requestAnimationFrame(move)
}
I want to make it responsive and very smooth and I know there is way but don't know how. Example of this is mouse, your laptop doesn't get worked up from scrolling (and, for example, moving google maps with mouse is smooth and doesn't use cpu as much).
Don't use the 20ms interval.
Move the player inside the requestAnimationFrame depending on which key Event.code is pressed and holds a truthy value inside of your keyDict object:
const keyDict = {};
const Player = {
el: document.querySelector("#player"),
x: 200,
y: 100,
speed: 2,
move() {
this.el.style.transform = `translate(${this.x}px, ${this.y}px)`;
}
};
const updateKeyDict = (ev) => {
const k = ev.code;
if (/^Arrow\w+/.test(k)) { // If is arrow
ev.preventDefault();
keyDict[k] = ev.type === "keydown"; // set boolean true / false
}
};
const update = () => {
// Determine move distance to account diagonal move: 1/Math.sqrt(2) = ~0.707
let dist =
keyDict.ArrowUp && (keyDict.ArrowLeft || keyDict.ArrowRight) ||
keyDict.ArrowDown && (keyDict.ArrowLeft || keyDict.ArrowRight) ? 0.707 : 1;
dist *= Player.speed;
if (keyDict.ArrowLeft) Player.x -= dist;
if (keyDict.ArrowUp) Player.y -= dist;
if (keyDict.ArrowRight) Player.x += dist;
if (keyDict.ArrowDown) Player.y += dist;
Player.move();
}
document.addEventListener('keydown', updateKeyDict);
document.addEventListener('keyup', updateKeyDict);
(function engine() {
update();
window.requestAnimationFrame(engine);
}());
#player {
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
background: #000;
border-radius: 50%;
}
Click here to focus, and use arrows
<div id="player"></div>
The above example uses Event.code for Arrows, which gives "ArrowLeft/Up/Right/Down" but you can change it accordingly to use "KeyW/A/S/D" instead.
"WASD" keys example
const keyDict = {};
const Player = {
el: document.querySelector("#player"),
x: 200,
y: 100,
speed: 2,
move() {
this.el.style.transform = `translate(${this.x}px, ${this.y}px)`;
}
};
const updateKeyDict = (ev) => {
const k = ev.code;
if (/^Key[WASD]/.test(k)) { // If is "KeyW,A,S,D" key
ev.preventDefault();
keyDict[k] = ev.type === "keydown"; // set boolean true / false
}
};
const update = () => {
// Determine move distance to account diagonal move: 1/Math.sqrt(2) = ~0.707
let dist =
keyDict.KeyW && (keyDict.KeyA || keyDict.KeyD) ||
keyDict.KeyS && (keyDict.KeyA || keyDict.KeyD) ? 0.707 : 1;
dist *= Player.speed;
if (keyDict.KeyA) Player.x -= dist;
if (keyDict.KeyW) Player.y -= dist;
if (keyDict.KeyD) Player.x += dist;
if (keyDict.KeyS) Player.y += dist;
Player.move();
}
document.addEventListener('keydown', updateKeyDict);
document.addEventListener('keyup', updateKeyDict);
(function engine() {
update();
window.requestAnimationFrame(engine);
}());
#player {
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
background: #000;
border-radius: 50%;
}
Click here to focus, and use keys WASD
<div id="player"></div>

Trying to get this smoother and more natural in behavior

My implementation,
http://kodhus.com/kodnest/land/PpNFTgp
I am curious, as I am not able for some reason to figure this out, how to get my JavaScript to make my slider behave more natural and smoother, if someone knows, how to, or can make this, feel free. I'd be happy to understand.
JavaScript:
const thumb = document.querySelector('.thumb');
const thumbIndicator = document.querySelector('.thumb .thumb-indicator');
const sliderContainer = document.querySelector('.slider-container');
const trackProgress = document.querySelector('.track-progress');
const sliderContainerStart = sliderContainer.offsetLeft;
const sliderContainerWidth = sliderContainer.offsetWidth;
var translate;
var dragging = false;
var percentage = 14;
document.addEventListener('mousedown', function(e) {
if (e.target.classList.contains('thumb-indicator')) {
dragging = true;
thumbIndicator.classList.add('focus');
}
});
document.addEventListener('mousemove', function(e) {
if (dragging) {
console.log('moving', e)
if (e.clientX < sliderContainerStart) {
translate = 0;
} else if (e.clientX > sliderContainerWidth + sliderContainerStart) {
translate = sliderContainerWidth;
} else {
translate = e.clientX - sliderContainer.offsetLeft;
}
thumb.style.transform = 'translate(-50%) translate(' + translate + 'px)';
trackProgress.style.transform = 'scaleX(' + translate / sliderContainerWidth + ')'
}
});
function setPercentage() {
thumb.style.transform = 'translate(-50%) translate(' + percentage/100 * sliderContainerWidth + 'px)';
trackProgress.style.transform = 'scaleX(' + percentage/100 + ')';
}
function init() {
setPercentage();
}
init();
document.addEventListener('mouseup', function(e) {
dragging = false;
thumbIndicator.classList.remove('focus');
});
EDIT: Is there a way to smoothly and naturally increment by one for every slow move?
Is it possible to make to behave as if, like when one clicks the progress bar so that it jumps there?
The kodhus site is very janky in my browser, so I can't tell if your code lacks responsiveness or whether it's the site itself. I feel that your code is a bit convoluted: translate and width / height are mixed unnecessarily; no need to use a dragging boolean when that information is always stored in the classlist. The following slider performs nicely, and has a few considerations I don't see in yours:
stopPropagation when clicking the .thumb element
drag stops if window loses focus
pointer-events: none; applied to every part of the slider but the .thumb element
let applySliderFeel = (slider, valueChangeCallback=()=>{}) => {
// Now `thumb`, `bar` and `slider` are the elements that concern us
let [ thumb, bar ] = [ '.thumb', '.bar' ].map(v => slider.querySelector(v));
let changed = amt => {
thumb.style.left = `${amt * 100}%`;
bar.style.width = `${amt * 100}%`;
valueChangeCallback(amt);
};
// Pressing down on `thumb` activates dragging
thumb.addEventListener('mousedown', evt => {
thumb.classList.add('active');
evt.preventDefault();
evt.stopPropagation();
});
// Releasing the mouse button (anywhere) deactivates dragging
document.addEventListener('mouseup', evt => thumb.classList.remove('active'));
// If the window loses focus dragging also stops - this can be a very
// nice quality of life improvement!
window.addEventListener('blur', evt => thumb.classList.remove('active'));
// Now we have to act when the mouse moves...
document.addEventListener('mousemove', evt => {
// If the drag isn't active do nothing!
if (!thumb.classList.contains('active')) return;
// Compute `xRelSlider`, which is the mouse position relative to the
// left side of the slider bar. Note that *client*X is compatible with
// getBounding*Client*Rect, and using these two values we can quickly
// get the relative x position.
let { width, left } = slider.getBoundingClientRect();
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Clamp `xRelSlider` between 0 and the slider's width
if (xRelSlider < 0) xRelSlider = 0;
if (xRelSlider > width) xRelSlider = width;
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
slider.addEventListener('mousedown', evt => {
let { width, left } = slider.getBoundingClientRect();
// Clicking the slider also activates a drag
thumb.classList.add('active');
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
changed(0);
};
let valElem = document.querySelector('.value');
applySliderFeel(document.querySelector('.slider'), amt => valElem.innerHTML = amt.toFixed(3));
.slider {
position: absolute;
width: 80%; height: 4px; background-color: rgba(0, 0, 0, 0.3);
left: 10%; top: 50%; margin-top: -2px;
}
.slider > .bar {
position: absolute;
left: 0; top: 0; width: 0; height: 100%;
background-color: #000;
pointer-events: none;
}
.slider > .thumb {
position: absolute;
width: 20px; height: 20px; background-color: #000; border-radius: 100%;
left: 0; top: 50%; margin-top: -10px;
}
.slider > .thumb.active {
box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.5);
}
<div class="slider">
<div class="bar"></div>
<div class="thumb"></div>
</div>
<div class="value"></div>

How to make mouseup fire anyehere?

I have a drag and drop script that is relatively functional. However, I want to be able to trigger mouseup anywhere on the screen. Is there a way to trigger mouseup outside of the window, or outside of the current element? I know this is possible and I've seen other questions like this. I wanted to find a way in vanilla Javascript to detect mouseups like this.
document.onmousemove = mouseCoords;
var x = 0;
var y = 0;
var cl1= false;
var divid;
var offs1;
var offs2;
var topPos;
var leftPos;
function mouseCoords(e) {
x = e.x
y = e.y
if(cl1 === true){
document.getElementById(divid).style.top = topPos + (y-offs1) + 'px';
document.getElementById(divid).style.left = leftPos + (x-offs2) + 'px';
}
}
var drag = function(i, cas) {
divid= i
switch(cas){
case 1:
var rect = document.getElementById(divid).getBoundingClientRect();
leftPos = rect.left;
topPos = rect.top;
offs1 = y;
offs2 = x;
cl1= true;
break;
case 0:
offs1 = 0;
offs2 = 0;
cl1= false;
break;
}
}
#block{
width: 100px; z-index: 20; height: 50px; background-color: blue; position: fixed; user-select: none; -webkit-user-select: none;
}
.drag{
width: 200px; height: 100px; background-color: red; position: fixed;
}
<div id="block">mouseup doesn't trigger over me!</div>
<div id="1" class="drag" onmousedown="drag(1, 1)" onmouseup="drag(1, 0)"></div>
Use
document.addEventListener("mouseup", drag(null, 0));
for mouseup,
and this code for mousedown.
document.addEventListener("mousedown", drag(null, 1));
Basically, document.addEventListener works for the whole window. "mouseup" tells the script that the event is a mouseup, and the final bit is the function to be executed (drag(1, 0))

Attemping to get a div to "follow" cursor on mousemove, but with a delay

I want to create the effect similar to the old mouse trails where the div is delayed but follows the cursor.
I have come reasonably close by using set interval to trigger an animation to the coordinates of the cursor.
$("body").mousemove(function (e) {
if (enableHandler) {
handleMouseMove(e);
enableHandler = false;
}
});
timer = window.setInterval(function(){
enableHandler = true;
}, 250);
function handleMouseMove(e) {
var x = e.pageX,
y = e.pageY;
$("#cube").animate({
left: x,
top: y
}, 200);
}
JSFiddle
There are two problems that remain now:
The 'chasing' div is very jumpy (because of the required use of set interval)
If the mouse move stops before the animation is triggered, the div is left in place, away from the cursor.
I did it slightly differently. Instead of using setInterval (or even setTimeout) - I just made the animation take x amount of milliseconds to complete. The longer the animation, the less responsive the following div will seem to be.
The only problem I notice is that it gets backed up if the mouse is moved a lot.
$(document).ready(function () {
$("body").mousemove(function (e) {
handleMouseMove(e);
});
function handleMouseMove(event) {
var x = event.pageX;
var y = event.pageY;
$("#cube").animate({
left: x,
top: y
}, 1);
}
});
https://jsfiddle.net/jvmravoz/1/
Remove SetInterval and add a $("#cube").stop(); to stop the old animation based on old (x,y) so you can start a new "faster" one.
$(document).ready(function() {
$("body").mousemove(function (e) {
$("#cube").stop();
handleMouseMove(e);
});
function handleMouseMove(event) {
var x = event.pageX,
y = event.pageY;
$("#cube").animate({
left: x,
top: y
}, 50);
}
});
Working example
https://jsfiddle.net/jabnxgp7/
Super late to the game here but I didn't really like any of the options for adding a delay here since they follow the mouse's previous position instead of moving towards the mouse. So I heavily modified the code from Mike Willis to get this -
$(document).ready(function () {
$("body").mousemove(function (e) {
mouseMoveHandler(e);
});
var currentMousePos = { x: -1, y: -1 };
function mouseMoveHandler(event) {
currentMousePos.x = event.pageX;
currentMousePos.y = event.pageY;
}
mouseMover = setInterval(positionUpdate, 15);
function positionUpdate() {
var x_cursor = currentMousePos.x;
var y_cursor = currentMousePos.y;
var position = $("#cube").offset();
var x_box = position.left;
var y_box = position.top;
$("#cube").animate({
left: x_box+0.1*(x_cursor-x_box),
top: y_box+0.1*(y_cursor-y_box)
}, 1, "linear");
}
});
-----------------------------------------------------------------------
body { overflow:hidden; position:absolute; height:100%; width:100%; background:#efefef; }
#cube {
height:18px;
width:18px;
margin-top:-9px;
margin-left:-9px;
background:red;
position:absolute;
top:50%;
left:50%;
}
.circleBase {
border-radius: 50%;
}
.roundCursor {
width: 20px;
height: 20px;
background: red;
border: 0px solid #000;
}
https://jsfiddle.net/rbd1p2s7/3/
It saves the cursor position every time it moves and at a fixed interval, it updates the div position by a fraction of the difference between it and the latest cursor position. I also changed it to a circle since the circle looked nicer.
One concern here is that it triggers very often and could slow down a weak machine, reducing the update frequency makes the cursor jump more than I'd like, but maybe there's some middle ground between update frequency and jumpiness to be found, or using animation methods I'm not familiar with to automate the movement.
Here is a solution that might mimic the mouse-trail a bit more because it is only remembering the last 100 positions and discarding older ones which kind of sets the length of the mouse trail.
https://jsfiddle.net/acmvhgzm/6/
$(document).ready(function() {
var pos = new Array();
$("body").mousemove(function (e) {
handleMouseMove(e);
});
timer = window.setInterval(function() {
if (pos.length > 0) {
$('#cube').animate(pos.shift(),15);
}
}, 20);
function handleMouseMove(event) {
var x = event.pageX,
y = event.pageY;
if (pos.length = 100) {
pos.shift();
}
pos.push({'left':x, 'top':y});
}
});
Old mouse-trail feature used a list of several windows shaped like cursors which updated their positions with every frame. Basically, it had a list of "cursors" and every frame next "cursor" in list was being moved to current cursor position, achieving effect of having every fake cursor update its own position with a delay of fake cursors - 1 frames.
Smooth, on-demand delayed movement for a single object can be simulated using requestAnimationFrame, performance.now and Event.timeStamp. Idea is to hold mouse events in internal list and use them only after specific time passed after their creation.
function DelayLine(delay, action){
capacity = Math.round(delay / 1000 * 200);
this.ring = new Array(capacity);
this.delay = delay;
this.action = action;
this._s = 0;
this._e = 0;
this._raf = null;
this._af = this._animationFrame.bind(this);
this._capacity = capacity;
}
DelayLine.prototype.put = function(value){
this.ring[this._e++] = value;
if (this._e >= this._capacity) this._e = 0;
if (this._e == this._s) this._get();
cancelAnimationFrame(this._raf);
this._raf = requestAnimationFrame(this._af);
}
DelayLine.prototype._get = function(){
var value = this.ring[this._s++];
if (this._s == this._capacity) this._s = 0;
return value;
}
DelayLine.prototype._peek = function(){
return this.ring[this._s];
}
DelayLine.prototype._animationFrame = function(){
if (this._length > 0){
if (performance.now() - this._peek().timeStamp > this.delay)
this.action(this._get());
this._raf = requestAnimationFrame(this._af);
}
}
Object.defineProperty(DelayLine.prototype, "_length", {
get: function() {
var size = this._e - this._s;
return size >= 0 ? size : size + this._capacity;
}
});
var delayLine = new DelayLine(100, function(e){
pointer.style.left = e.x - pointer.offsetWidth/2 + "px";
pointer.style.top = e.y - pointer.offsetHeight/2 + "px";
});
document.addEventListener("mousemove", function(e){
delayLine.put(e);
}, false);
https://jsfiddle.net/os8r7c20/2/
Try removing setInterval , using .css() , css transition
$(document).ready(function () {
var cube = $("#cube");
$("body").mousemove(function (e) {
handleMouseMove(e);
});
function handleMouseMove(event) {
var x = event.pageX,
y = event.pageY;
cube.css({
left: x + cube.width() / 2 + "px",
top: y + cube.height() / 2 + "px"
}).parents("body").mousemove()
}
});
body {
overflow:hidden;
position:absolute;
height:100%;
width:100%;
background:#efefef;
}
#cube {
height:50px;
width:50px;
margin-top:-25px;
margin-left:-25px;
background:red;
position:absolute;
top:50%;
left:50%;
transition:all 1.5s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div id="cube"></div>
</div>

Click And Drag function in javascript

I'm trying to create my own click and drag function in JavaScript without the use of jquery. I know that jquery is easy to implement, but I prefer my own code. What I have, as i click the div, then move the mouse, the div moves to the same spot and doesn't implement a "dragging" look to it. I'm not sure why this is. I want my outcome to be able to move the div over the image that way I can "crop" the image based on the div, etc. My code is:
index.js
function _(element) {
return document.getElementById(element);
}
index.css
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgb(255,255,255);
position: absolute;
}
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8"/>
<title>Image Cropping</title>
<link rel = "stylesheet" href = "index.css"/>
<script src = "index.js"></script>
</head>
<body>
<div class = "image">
<img src = "model.jpg" alt = "Model" id = "theImage"/>
<div class = "selection" id = "selection"/>
</div>
<script>
_("theImage").ondragstart = function() { return false; };
var m = _("selection");
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() {
window.removeEventListener("mousemove", move, true);
}
function mouseDown(e) {
window.addEventListener("mousemove", move, true);
}
function move(e) {
var x = m.style.left;
var y = m.style.top;
var mouseX = e.clientX;
var mouseY = e.clientY;
m.style.top += (mouseX - x) + "px";
m.style.left += (mouseY - y) + "px";
// Also tried: m.style.top = (mouseX - x) + "px";
// And : m.style.left = (mouseY - y) + "px";
}
</script>
</body>
</html>
To add the "dragging look to it", you can:
change the cursor (cursor: move;)
keep the cursor's offset relative to the mouse
For the second one, I reused a function I created for one of my projects, for which I implemented drag and drop for mobile, not wanting to use a big library:
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
Using this function, the math becomes simple:
m.style.left = (mouseX - offset.left) + "px";
m.style.top = (mouseY - offset.top) + "px";
Full demo
_("theImage").ondragstart = function () { return false; };
var m = _("selection"), offset;
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() { window.removeEventListener("mousemove", move, true); }
function mouseDown(e) {
// SAVE THE OFFSET HERE
offset = {
left: e.pageX - realOffset(m).left,
top: e.pageY - realOffset(m).top
};
window.addEventListener("mousemove", move, true);
}
function move(e) {
// REUSE THE OFFSET HERE
m.style.left = (e.pageX - offset.left) + "px";
m.style.top = (e.pageY - offset.top) + "px";
}
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
function _(element) { return document.getElementById(element); }
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgba(255,255,255,.5);
position: absolute;
cursor: move;
}
<div class="image">
<img src="http://i.imgur.com/vxkljMP.jpg" alt="Model" id="theImage" />
<div class="selection" id="selection"></div>
</div>

Categories

Resources