I have this canvas where I use 2 pictures, one is the main picture and the second picture is used as a clipping mask.
I need to be able to move the main picture and have the code already implemented, but when we click in the picture to drag, the image always assumes the initial position, and also when we drag the image it doesn't move along with the mouse, there's some kind of increasing delay. I tried to turn around this, but I'm not that good with math to come up with the right formula.
This is the code I use to capture the mouse moving:
$(window).mousemove(function(event) {
if( isDragging == true )
{
var cWidth = $("#stcanvas").width();
moveXAmount = (event.pageX / $(window).width())*cWidth;
moveXAmount = moveXAmount - (cWidth/2);
var cHeight = $("#stcanvas").height();
moveYAmount = (event.pageY / $(window).height())*cHeight;
moveYAmount = moveYAmount - (cHeight/2);
buildcanvas();
}
});
Any idea how can this be solved?
Here is a fiddle: http://jsfiddle.net/rVx5G/10/
It looks like you need to handle the delta in mouse movements instead of moving relative to window. Here is a jsfiddle. The change is:
var prevX = 0;
var prevY = 0;
$(window).mousemove(function(event) {
if( isDragging == true )
{
if( prevX>0 || prevY>0)
{
moveXAmount += event.pageX - prevX;
moveYAmount += event.pageY - prevY;
buildcanvas();
}
prevX = event.pageX;
prevY = event.pageY;
}
});
Does that achieve what you wanted?
Change this line like below for auto size
ctx.clearRect(0, 0, mask_image.width, mask_image.height);
function make_pic(ctx) {
// Mask for clipping
mask_image = new Image();
mask_image.src = 'mask.png';
ctx.clearRect(0, 0, mask_image.width, mask_image.height);
ctx.drawImage(mask_image, 0, 0);
ctx.save();
....
Related
In javascript, is there a way I can create a variable and a function that "simulates" smooth mouse movement? i.e., say the function simulates a user starts from lower left corner of the browser window, and then moves mouse in a random direction slowly...
The function would return x and y value of the next position the mouse would move each time it is called (would probably use something like setInterval to keep calling it to get the next mouse position). Movement should be restricted to the width and height of the screen, assuming the mouse never going off of it.
What I don't want is the mouse to be skipping super fast all over the place. I like smooth movements/positions being returned.
A "realistic mouse movement" doesn't mean anything without context :
Every mouse user have different behaviors with this device, and they won't even do the same gestures given what they have on their screen.
If you take an FPS game, the movements will in majority be in a small vertical range, along the whole horizontal screen.
Here is a "drip painting" I made by recording my mouse movements while playing some FPS game.
If we take the google home page however, I don't even use the mouse. The input is already focused, and I just use my keyboard.
On some infinite scrolling websites, my mouse can stay at the same position for dozens of minutes and just go to a link at some point.
I think that to get the more realistic mouse movements possible, you would have to record all your users' gestures, and repro them.
Also, a good strategy could be to get the coordinates of the elements that will attract user's cursor the more likely (like the "close" link under SO's question) and make movements go to those elements' coordinates.
Anyway, here I made a snippet which uses Math.random() and requestAnimationFrame() in order to make an object move smoothly, with some times of pausing, and variable speeds.
// Canvas is here only to show the output of function
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
var maxX = canvas.width = window.innerWidth;
var maxY = canvas.height = window.innerHeight;
window.onresize = function(){
maxX = canvas.width = window.innerWidth;
maxY = canvas.height = window.innerHeight;
}
gc.onclick = function(){
var coords = mouse.getCoords();
out.innerHTML = 'x : '+coords.x+'<br>y : '+coords.y;
}
var Mouse = function() {
var that = {},
size = 15,
border = size / 2,
maxSpeed = 50, // pixels per frame
maxTimePause = 5000; // ms
that.draw = function() {
if (that.paused)
return;
that.update();
// just for the example
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(show.checked){
ctx.drawImage(that.img, that.x - border, that.y - border, size, size)
}
// use requestAnimationFrame for smooth update
requestAnimationFrame(that.draw);
}
that.update = function() {
// take a random position, in the same direction
that.x += Math.random() * that.speedX;
that.y += Math.random() * that.speedY;
// if we're out of bounds or the interval has passed
if (that.x <= border || that.x >= maxX - border || that.y <= 0 || that.y >= maxY - border || ++that.i > that.interval)
that.reset();
}
that.reset = function() {
that.i = 0; // reset the counter
that.interval = Math.random() * 50; // reset the interval
that.speedX = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the horizontal direction
that.speedY = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the vertical direction
// we're in one of the corner, and random returned farther out of bounds
if (that.x <= border && that.speedX < 0 || that.x >= maxX - border && that.speedX > 0)
// change the direction
that.speedX *= -1;
if (that.y <= border && that.speedY < 0 || that.y >= maxY - border && that.speedY > 0)
that.speedY *= -1;
// check if the interval was complete
if (that.x > border && that.x < maxX - border && that.y > border && that.y < maxY - border) {
if (Math.random() > .5) {
// set a pause and remove it after some time
that.paused = true;
setTimeout(function() {
that.paused = false;
that.draw();
}, (Math.random() * maxTimePause));
}
}
}
that.init = function() {
that.x = 0;
that.y = 0;
that.img = new Image();
that.img.src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABJUlEQVRIic2WXbHEIAyFI6ESKgEJkVIJlYCTSqiESIiESqiEb19gL9Od3f5R5mbmPPHwBTgnIPJfChiAGbCkCQgtG7BpmgAWIALaDDyOI2bGuq40BasqIoKZATgwNAWHEEjHbkBsBhYRVJUYIwBNwVlFaVOwiDDPMylmQ1OwquY7d0CBrglYkuEeidoeOKt61I6Cq0ftKFhqR+0MOKuo2BQsInnndvnOr4JvR+0qWO5G7Q44K0XtOXDf96jqh9z9WXAy1FJ8l0qd+zbtvU7lWs7wIzkuh8SvpqqDi3zGndPQauDkzvdESm8xZvbh4mVZ7k8ud/+aR0C3YPk7mVvgkCZPVrdZV3dHVem6bju1roMPNmbAmq8kG+/ynD7ZwNsAVVz9dL0AhBrZq7F+CSQAAAAASUVORK5CYII=";
that.reset();
}
that.getCoords = function(){
return {x: that.x, y:that.y};
}
that.init()
return that;
}
var mouse = new Mouse()
mouse.draw();
html,body {margin: 0}
canvas {position: absolute; top:0; left:0;z-index:-1}
#out{font-size: 0.8em}
<label for="show">Display cursor</label><input name="show" type="checkbox" id="show" checked="true"/><br>
<button id="gc">get cursor Coords</button>
<p id="out"></p>
Last I heard the browser's mouse position cannot be altered with JavaScript, so the question really has no answer "as is". The mouse position can be locked though. I'm not certain whether it would be possible to implement a custom cursor that allows setting the position. This would include hiding and perhaps locking the stock cursor.
Having something smoothly follow the cursor is quite straight forward. You may be able to reverse this process to achieve what you need. Here's a code snippet which simply calculates the distance between the cursor and a div every frame and then moves the div 10% of that distance towards the cursor:
http://jsfiddle.net/hpp0qb0d/
var p = document.getElementById('nextmove')
var lastX,lastY,cursorX,cursorY;
window.addEventListener('mousemove', function(e){
cursorX = e.pageX;
cursorY = e.pageY;
})
setInterval(function(){
var newX = p.offsetLeft + (cursorX - lastX)/10
var newY = p.offsetTop + (cursorY - lastY)/10
p.style.left = newX+'px'
p.style.top = newY+'px'
lastX = p.offsetLeft
lastY = p.offsetTop
},20)
Hitbox Overlay IIFE Code
//CSS Hitbox Solution 08-26-2015
//StackOverflow - https://stackoverflow.com/questions/32233084/show-an-element-without-hitbox-does-not-take-mouse-touch-input
//Detect MouseOver https://stackoverflow.com/questions/1273566/how-do-i-check-if-the-mouse-is-over-an-element-in-jquery
//Source: https://stackoverflow.com/questions/3942776/using-jquery-to-find-an-element-at-a-particular-position
//https://css-tricks.com/snippets/jquery/get-x-y-mouse-coordinates/
(function($) {
$.mlp = {
x: 0,
y: 0
}; // Mouse Last Position
function documentHandler() {
var $current = this === document ? $(this) : $(this).contents();
$current.mousemove(function(e) {
jQuery.mlp = {
x: e.pageX,
y: e.pageY
};
});
$current.find("iframe").load(documentHandler);
}
$(documentHandler);
$.fn.ismouseover = function(overThis) {
var result = false;
this.eq(0).each(function() {
var $current = $(this).is("iframe") ? $(this).contents().find("body") : $(this);
var offset = $current.offset();
result = offset.left <= $.mlp.x && offset.left + $current.outerWidth() > $.mlp.x && offset.top <= $.mlp.y && offset.top + $current.outerHeight() > $.mlp.y;
});
return result;
};
})(jQuery);
$('.notification-box').on("click", function() {
$("button").each(function(i) {
var iteratedButton = $('button:eq(' + i + ')');
var buttonID = iteratedButton.attr("id");
if (iteratedButton.ismouseover()) {
iteratedButton.toggleClass(buttonID);
}
});
});
Example 01: Overlay Example for context
Example 02: Concept for auto generating content - Derived from this stackoverflow question.
There is a way by which one can have multiple objects underneath an overlay that masks them. Then, there is a way to have the pointer interact with the elements underneath said overlay if the user clicks at the predetermined point. My question is, may someone please write the code that would, marry the concept of the <map> tag with the IIFE that detects if the point of reference the user clicked is that image and then, act as though it was clicked.
If that did not make sense, simply, I am looking for a process that deviates away from manually setting up coordinates for <area> or having to use tool (which are profound) such as http://www.image-maps.com/. Rather, we would let the pointer do all the work.
We have the following high utility + highly compatible methods: .offset(), .position(), elementFromPoint() and the ability to put elements behind a mask utilizing basic CSS.
So we could combine the IIFE Overlay hitbox method above + ???? = Profit (good bye mapping coordinates via <map>).
I just do not know what the ???? is. I do know that whatever the solution is, I would prefer that it works in all browsers (including IE 5).
Lastly, the process should be fairly automatic in design, setup and implementation.
Whoever creates it, please dub it autoMapperJs (as it would not be limited to images).
Update:
A core feature component of the ???? has been realized as noted by #Alex in the comments. CreateJs notices when the pointer is hovered over a non-transparent area of a image. That is powerful and should be standard in the tool created. It also seems to utilize .mousemove() and z-index. Please keep commenting, as collectively, I feel a solution can be found.
Here's a start. Put images into an array of layers and placements on canvas then run through them on mouse over for hit. Also put over images in layers array to draw that image when hit.
var can = document.getElementById('image-map');
var W = can.width;
var H = can.height;
var ctx = can.getContext('2d');
var layers = [];
var mouse = {x:0,y:0};
can.addEventListener('mousemove', function(evt) {
mouse = getMousePos(can, evt);
drawCanvas();
}, false);
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
main();
function main() {
initLayers();
drawCanvas();
}
function drawCanvas() {
ctx.clearRect(0, 0, W, H);
var hit = -1;
for (var i =layers.length; i--;) {
var c = layers[i];
if(maskHit(c.img, c.x, c.y)) {
hit = i;
break;
}
}
for (var i =0; i < layers.length; i++) {
var c = layers[i];
var img = hit === i ? c.hov : c.img;
ctx.drawImage(img, c.x, c.y);
}
ctx.drawImage(circ(10,"rgba(255,200,0,.75)"), mouse.x-10/2,mouse.y-10/2);
}
// UTILITY TO DRAW SAMPLE IMAGES
function circ(size, color) {
var can = document.createElement('canvas');
can.width = can.height = size;
var to_rad = Math.PI / 180;
var ctx = can.getContext('2d');
ctx.beginPath();
ctx.moveTo(size, size / 2);
ctx.arc(size / 2, size / 2, size / 2, 0, 360 * to_rad);
ctx.fillStyle = color;
ctx.fill();
return can;
}
function initLayers() {
var s = 75; // size
// PUT YOUR IMAGES IN A LAYERS ARRAY WITH X,Y COORDS FOR CANVAS
// PLACEMENT. X AND Y ARE TOP LEFT CORNDER OF IMAGE. STORE HOVER
// IMAGE FOR MOUSE HIT.
layers = [{
img: circ(s, "#090"),
hov: circ(s, "#C0C"),
x: 123,
y: 12
}, {
img: circ(s, "#F00"),
hov: circ(s, "#C0C"),
x: 63,
y: 12
}, {
img: circ(s, "#00F"),
hov: circ(s, "#C0C"),
x: 3,
y: 12
}];
}
var maskCan = document.createElement("canvas");
maskCan.width=maskCan.height=1;
var maskCtx = maskCan.getContext('2d');
function maskHit(img, x, y) {
// get relative coords to image upper left corner
x = mouse.x - x;
y = mouse.y - y;
if (x < 0 || y < 0 || x > img.width || y > img.height) return false;
//return 1; // square hit, no alpha check
// ALPHA CHECK - draw one pixel, get and check alpha.
// sx sy sw sh dx dy dw dh
maskCtx.clearRect(0,0,1,1);
maskCtx.drawImage(img, x, y, 1, 1, 0, 0, 1, 1);
var imageData = maskCtx.getImageData(0,0,1,1);
//console.log(imageData.data[3])
return imageData.data[3] === 255;
}
#image-map {
border: 1px solid #ACE;
}
<canvas id="image-map" width="200" height="100"></canvas>
So I hit a snag while building an HTML5 canvas UI element. I want to make the circle in this toggle switch drag to the X-coordinate that the user drags it to (there's ultimately a lot more that this thing is going to have but I want to do it a step at a time!). I can output the x coordinates so I know that's working but for some reason I cannot get it to work in my animation loop to change the variable primX. Here's my code:
HTML:
<canvas id="toggle1" class="toggle" onmousemove="getCoords(event)"></canvas>
<p id="test"></p>
The CSS is irrelevant, as long as you set any width to .toggle or #toggle1
JavaScript:
var canvas=document.getElementById("toggle1");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height=cw/3;
var PI=Math.PI;
var PI2=(PI * 2);
var cx=ch/2;
var cy=ch/2;
var backStyle="#FFFFFF"
var globalID;
var lw=ctx.lineWidth=8;
var radius=ch/2-lw/2;
var half=cw/2;
var currX;
var globalID;
var mouseIsDown=false;
function getCoords(event) {
var currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
function backGround(){
if (primX > half){
Style="#00FF00";
} else {
Style="#FF0000";
};
ctx.fillStyle=backStyle;
ctx.strokeStyle=Style;
ctx.beginPath();
ctx.arc(cx+lw/2,cy,radius,(0.5 * PI),(1.5 * PI));
ctx.lineTo((cw-(ch/2)),0+lw/2);
ctx.arc((cw-(ch/2+lw/2)),cy,radius,(1.5 * PI),(.5 * PI));
ctx.lineTo(cx,ch-lw/2);
ctx.fill();
ctx.stroke();
};
function mainCir() {
if (primX > half){
Style="#00FF00";
on=true;
} else {
Style="#FF0000";
on=false;
};
ctx.beginPath();
ctx.arc(primX,cy,radius,0,PI2);
ctx.fillStyle=Style;
ctx.fill();
}
primX = cx;
function draw(){
backGround();
mainCir();
}
draw();
function animate() {
primX=currX;
globalID=requestAnimationFrame(animate);
draw();
}
$("#toggle1").mousedown(function() {
mouseIsDown=true;
});
$(document).mouseup(function() {
if(mouseIsDown){
animate();
mouseIsDown=false;
}
});
I've tried a ton of different things but nothing work. If I put a simple animation in the animate() function then that seems to work when the mouse is clicked and held on the element, such as primX++;
But I have no idea how to "animate" the circle to where it goes to the X coordinate that the user drags it to. I've tried a couple of different things and rearranged stuff but it just ends up either disabling animations completely or, as you can see by THIS FIDDLE the circle just disappears.
If anyone knows how to fix this issue, I'd be grateful. Thank you!
It was a little thing. In the function that get the coordinates:
function getCoords(event) {
var currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
you are declaring the currX variable. But it was alredy declared, so what you are doing is to create a new one whose scope get lost in the moment the function finish.
You want this:
function getCoords(event) {
currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
Hope it helps!
UPDATE:
There are two more details that maybe are useful for you:
First: you are getting the coordinates in the application's client area, not in the canvas. So maybe you want to add the canvas' left offset.
Second: canvas.width is the logical canvas width, different from the element.width CSS attribute. So most sure you want to make a units conversion.
Altogether:
function getCoords(event) {
currX = event.clientX - $(event.target).offset().left ;
currX = currX * (canvas.width / $(canvas).width());
if (currX < radius) currX = radius;
if (currX > canvas.width - radius) currX = canvas.width - radius;
document.getElementById("test").innerHTML = currX;
}
Here you can read more about getting mouse coordinates and here about the dimensions of a canvas.
I'm trying to make a website with links rotating around a circle. (Something like this) http://i.imgur.com/i9DzASw.jpg?1 with the different images and texts leading to different urls. The image is one unified image that also rotates as the user scrolls. Is there anyway I can do this? Also is there a way to make the page height infinite so that the user never gets to the bottom of the page as they scroll? Thanks!
Here's the jsfiddle and the code that allows for the rotation of the image.
http://jsfiddle.net/kDSqB/135/
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height();
$(window).scroll(function () {
$cog.css({
'transform': 'rotate(' + ($body.scrollTop() / bodyHeight * 30000) + 'deg)'
});
});
http://jsfiddle.net/Fezjh/1/
I have coloured the div to make it easier to understand how to do it - but you need to think carefully about compatiblity issues (older browsers etc.)
Just remove the background colour to get your desired effect.
A better way would be to split the image into divs and put those divs up against each other.
check http://www.gdrtec.co.uk - you will notice 4 images butted up against each other form the start menu - it would be easy to rotate the containing div and everything will still work as it should.
The code below is just for demonstration purposes and should be replaced with more robust solution.
$('#link1').click(function(){
alert("openURL");
});
Also consider making sure people don't have to rely on javascript for your site to work.
See this : http://jsfiddle.net/F8GTP/, and this final version : http://jsfiddle.net/MjnxP/.
Use WheelEvent like this for infinite scroll :
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height(),
rotate = 1;
var wheelEvent = function (event) {
var delta = 0;
if (event.wheelDelta) { delta = event.wheelDelta/120; } else if (event.detail) { delta = -event.detail/3; }
if (delta) {
rotate += delta * 1.12; //<== Increase speed.
console.log(rotate, delta);
$cog.css({ 'transform': 'rotate(' + rotate + 'deg)'});
}
if (event.preventDefault) { event.preventDefault(); }
event.returnValue = false;
};
window.onmousewheel = wheelEvent;
if (window.addEventListener) { window.addEventListener('DOMMouseScroll', wheelEvent, false); }
For detect link use canvas with "collision image", and this is final version :
$cog.click(function(e) {
if (rotate !== lastrotate) {
//http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/
context.save();
context.translate((image.width/2), (image.height/2));
context.rotate(rotate * Math.PI/180);
context.drawImage(image, -(image.width/2), -(image.height/2));
context.restore();
lastrotate = rotate;
}
var x = e.pageX, y = e.pageY;
console.log(x, y);
var color = context.getImageData(x, y, 1, 1).data;
// context.fillRect(x-5, y-5, 1+10, 1+10); <== See cursor position
if (color[0] == 255 && color[1] == 255 && color[2] == 255) { //white = rgb(255, 255, 255);
alert("click");
}
});
function setPixel(imageData, x, y, r, g, b, a) {
index = (x + y * imageData.width) * 4;
imageData.data[index+0] = r;
imageData.data[index+1] = g;
imageData.data[index+2] = b;
imageData.data[index+3] = a;
}
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
image = new Image(),
lastrotate = null;
image.onload = function(){
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0, image.width, image.height);
};
// http://i.imgur.com/UfjbW5l.png I use base64 for get image because else console return security error with "getImageData".
image.src = "data:image/png;base64,iVBORw0K...";
For "image.src", use your image in YOUR DOMAIN or use Base64 else this script return security error for convert image to base64 see : http://www.base64-image.de/.
If position of cog isn't (0, 0) replace actual line to this line :
var x_pos = 200, y_pos = 200; // No use .position() or .offset() for get this, or use parent element position.
var x = e.pageX - x_pos, y = e.pageY - y_pos;
I'm trying to drag an image around on my canvas but in doing so I have an issue where once the image is in negative coordinates I get a condition where its
mouseX - negativeImageCoords // 200 - minus 210 = 410
making my image jump around like a popcorn kitten on the canvas, not the desired effect.
Here is my code and I'm hoping it's something stupid and I can put this down to being tired..
function (e) {
var
// The mouse x and y positions
mx = e.offsetX,
my = e.offsetY,
// The last known position
lx = cache.lx, // These are from a JSON object
ly = cache.ly;
// The temporary image
var img = $('#loadedImage');
// Get the image context
var canvas_context = this.mask();
cache.lx = (mx - lx);
cache.ly = (my - ly);
console.log(mx, lx);
console.log(my, ly);
// Redraw
canvas_context.drawImage(img.get(0), cache.lx, cache.ly, img.width(), img.height());
}
here is the mask function (included in case it is the perpetrator..
function () {
var mask_name = 'circle';
var context = ctx.context();
var mask;
var isSameMask = false;
var composition = 'lighter';
// Add a check to see if it's the same mask
if (cache.mask && cache.mask.src) {
if (cache.mask.src !== 'images/masks/' + mask_name + '.png') {
isSameMask = false;
}
}
// If we don't have a cached mask, load it and cache it
if (!cache.mask && !isSameMask) {
// Create a new mask
mask = new Image;
// Draw when its loaded
mask.onload = function () {
//ctx.clear();
context.drawImage(this, 0, 0);
context.globalCompositeOperation = composition;
};
mask.src = 'images/masks/' + mask_name + '.png';
// Set the cache as this new mask
cache.mask = mask;
imageEvents.size(0);
} else {
ctx.clear();
// It's cached, so just redraw it
context.drawImage(cache.mask, 0, 0);
context.globalCompositeOperation = composition;
}
return context;
}
Why is the image jumping around?
It has to be noted that I have thrown this together for an appjs project, any help/advice from you all is greatly appreciated.
Right, managed to get this working. The fix was updating the cached image positions on mousedown and just adding the cached positions to the mouse positions. Here is the code:
function drag (e) { // :void
var
// The mouse x and y positions
mx = e.offsetX,
my = e.offsetY,
// The last known position
lx = mx+cache.lx,
ly = my+cache.ly;
// The temporary image
var img = $('#loadedImage');
// Get the image context
var canvas_context = this.mask();
cache.ix = lx;
cache.iy = ly;
// Redraw
canvas_context.drawImage(img.get(0), lx, ly, img.width(), img.height());
textEvents.draw();
}
And my down events
cache.ix = 0;
cache.iy = 0;
// Listen for a mousedown or touchstart event
canvas.on('mousedown touchstart', function (e) {
cache.lx = cache.ix - e.offsetX;
cache.ly = cache.iy - e.offsetY;
// Add a move listener
canvas.on('mousemove touchmove', function (e) {
that.drag.call(that, e);
});
});
It's hard to provide an answer without seeing the code in action but could it be those conditions you specify, e.g.:
if (lx < 0) {
cache.lx = (mx + lx);
} else {
cache.lx = (mx - lx);
}
Surely you don't want to change the sums if lx is less or more than 0. Just let the maths do its job. Mathematically:
mx + -1 is the same as mx - 1
mx + +1 is the same as mx + 1
mx - -1 is the same as mx + 1 [double negative]
That would be why '200 - minus 210 = 410'; that's actually correct.
EDIT
The variable lx is the cached (therefore old) position; mx is the new position.
Therefore lx - mx will return the difference between the cached and the new position, which I think (if I understand you correctly) is what you want to move your image by a certain amount. Same for ly - my.
When it comes to caching the new mouse positions, surely you just want to cache the current ones, e.g.
cache.lx = mx; // current position cached for future reference
Caching the difference or a summation will just add to the confusion (again, if I've understood what you're trying to do).