It's more of a question really, but I don't know where to start with this one at all. I'm working on a site at the moment and we've cited the following sites as reference:
http://exhibitions.guggenheim.org/storylines/
http://www.apple.com/uk/start-something-new/
As you can see, both have the same effect and allow you to pan the 'canvas' within the viewport. I've search high and low but can't find any documentation or plugins for such a thing. The closest I found but it still doesn't allow you to pan with mouseMove is this: http://jmpressjs.github.io/jmpress.js/#/home
Like I say though, it's still quite far away from what I'm trying to achieve. Any thoughts, ideas, suggestions or plugins people might know of would be massively appreciated!
Pan canvas with mouse
You can pan the canvas with the ctx.translate(x,y) function, but this function is relative and can be tricky to use if you do not understand matrix math. Or with ctx.setTransform(1,0,0,1,x,y) where the last two numbers set the origin location on the canvas. This function is absolute so you do not need to track the current transformation matrix. The origin is the where coordinates 0,0 are.
Using setTransform
So if you set the the origin to
ctx.setTransform(1,0,0,1,canvas.width/2,canvas.height/2)
and then draw a circle at 0,0
ctx.beginPath();
ctx.arc(0,0,100,0,Math.PI*2);
ctx.fill();
it will appear in the center of the canvas as that is where the new origin is.
Implementing
Now all you need is to use the mouse to pan.
First create var to track the origin location
var originX = 0; // default to the top left of the canvas.
var originY = 0;
Depending on how you render the following will flag when to update the canvas transform
var panOnMouse = true; // if you are using requestAnimationFrame
// or another realtime rendering method this should
// be false
Then create a helper function to set the origin
function setCanvasOrigin(ctx){
ctx.setTransform(1,0,0,1,originX,originY);
}
The mouse
Now the mouse event listener and tracking the mouse movements First a object to hold mouse information.
var mouse = {
x : 0, // holds the current mouse location
y : 0,
lastX : null, // holds the previous mouse location for use when mouse down
lastY : null, // as this is unknown start with null
buttonDown : false, // true if mouse button down;
panButtonID : 1, // the id of the pan button 1 left 2 middle 3 right
}
Then create an event listener to get the mousemove, mousedown, and mouseup
function mouseEvent(event){
if(buttonDown){ // if mouse button is down save the last mouse pos;
mouse.lastX = mouse.x;
mouse.lastY = mouse.y;
}
mouse.x = event.offsetX;
mouse.y = event.offsetY;
if (mouse.x === undefined) { // for browsers that do not support offset
mouse.x = event.clientX;
mouse.y = event.clientY;
}
// now handle the mouse down
if (event.type === "mousedown" && event.which === mouse.panButtonID ) {
mouse.buttonDown = true; // flag the pan button is down;
mouse.lastX = mouse.x; // set the last pos to current
mouse.lastY = mouse.y;
}
// now do the pan is the mouse is down
//
if(mouse.buttonDown){
originX += mouse.x - mouse.lastX; // add the mouse movement to origin
originY += mouse.y - mouse.lastY;
if(panOnMouse ){
setCanvasOrigin(ctx);
}
}
// handle the mouse up only for the pan button
if (event.type === "mouseup" && event.which === mouse.panButtonID) {
mouse.buttonDown = false;
}
}
If you have panOnMouse as false then call setCanvasOrigin at the start of your main render loop.
All that is needed now is to add the mouse event listener to the canvas.
canvas.addEventListener("mousemove",mouseEvent);
canvas.addEventListener("mousedown",mouseEvent);
canvas.addEventListener("mouseup",mouseEvent);
Last notes
So now when the user clicks and drags with the correct mouse button the canvas origin will be dragged to where ever it is wanted. It can even be off screen. Just draw everything as you normally did.
To reset the pan just set the origin to zero
originX = 0; // default to the top left of the canvas.
originY = 0;
setCanvasOrigin(ctx); // set the transform
Because the origin has moved the mouse position on the canvas does not match the panned canvas coordinates. To get the position of the mouse over the panned canvas just subtract the origin from the mouse. You can add it to the end of the mouse event function
mouse.realX = mouse.x - originX; // get the mouse position relative to the
mouse.realY = mouse.y - originY; // panned origin
If the user moves off the canvas while panning you may lose the mouse up event and have the button stuck down. You can listen to mouseout and mouseover events to control what happen in those situations.
And that is how to pan the canvas with the mouse.
Related
I am using next code to force content of canvas to follow finger touch movement on screen (drag and drop).
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canavasMovex=e.targetTouches[0].pageX-canvasLeftofset-canvas.width/2;
var canavasMovey=e.targetTouches[0].pageY-canvasTopofset-canvas.height/2;
document.getElementById("a").innerHTML= canavasMovex;
document.getElementById("b").innerHTML= canavasMovey;
var delta = new fabric.Point(-canavasMovex,-canavasMovey);
canvas.absolutePan(delta);
canvas.renderAll();
}
}, false);
Note: "-canavasMovex,-canavasMovey" values have the negative sign (I had to use it because otherwise the canvas was moving opposite to finger moment(I think you can ignore this fact and that it has noting to do with offset, which I am trying to solve asking for help here))
I have displacement of position proportional to the distance of touch point from the centre of canvas. If I start the movement pressing from the centre of screen, then displacement is not so notable. But if I start from top corner (for example) I get centre of canvas there in that touch point. From attached drawing I was trying with taking of consideration of "d" parameter (distance of touching point to the centre of canvas), to find right value for the equation for the canvas.absolutePan() function, but no success. Can you help me with this case,pleas? I was trying to use some solutions from browsing the internet to find the way to move canvas content. But then I had lost some of functions of my app because "new" libraries were not interacting correctly with my existing fabric.min.js library. Image info(external rectangle-web page,internal rectangle-canvas): a-canvas offset,b-distance to centre of canvas,c- touch point,d-distance from touch point to centre of canvas. So on the end I am trying to get to accomplish this task in this way.
Malfunction:
Bigger than distance "d" is on starting of dragging , bigger is then the offset. (actuary if I start dragging from canvas corner, canvas content transfers its centre there)
The solution is to get the finger position, calculate the difference to previous position, add difference to the previous position and then finally do the panning.
var canvasMovexoold = 0;
var canvasMoveyoold = 0;
document.addEventListener('touchstart', function(e){
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}, false);
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canvasMovexo += canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX-canvasMovexoold ;
var canvasMoveyo +=canvasTopofset+canvas.height/2- e.targetTouches[0].pageY-canvasMoveyoold ;
var delta = new fabric.Point(canvasMovexo,canvasMoveyo);
canvas.absolutePan(delta);
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}
}, false);
I am trying to create a canvas that allows me to draw on it rectangles using mouse events. Very similar to the way selection works in windows, I want to be able to click down anywhere on my page, drag left/right/up/down, then once I release, a rectangle is drawn with the starting coordinates (x1 and y1) on mousedown and the ending coordinates (x2, y2) on mouseup.
I've been trying to create eventListeners bound to my canvas that return the starting and ending coordinates on mousedown and mouseup respectively, but my variables stay undefined.
My canvas spans the entire length of my window so no need to take into account relative positioning. Also the solution has to be implemented using purely Javascript, no JQuery allowed.
Thank you for your help!
UPDATE
Ignore most of what is underneath, re-reading your question, it seems like you have the theory nailed. Your problem is most likely the mousedown and mouseup function parameters are missing. Try the following;
document.getElementsByTagName('canvas')[0].addEventListener('mousedown', function(e){
// I THINK IT'S THE e ON THE LINE ABOVE THIS THAT YOU'RE MISSING.
// YOU CAN THEN ACCESS THE POSITION OF THE MOUSE USING;
mouse.x = e.pageX;
mouse.Y = e.pageY;
})
I won't write the code for you, but I can give you theory.
Store your mouse x & y variables in an object such as mouse = {}.
Add an event listener to the canvas for mouse down (click) and store the e.pageX and e.pageY in mouse.firstX and mouse.firstY. Use something like:
document.getElementsByTagName('canvas')[0].addEventListener('mousedown', function(e){
mouse.firstX = e.pageX;
mouse.firstY = e.pageY;
})
Create a second event listener for the canvas for mouseup and store this set of e.pageX and e.pageY in mouse.secondX and mouse.secondY.
Calculate the difference between firstX and secondX, firstY and secondY to work out big your rectangle sound be.
var width = mouse.firstX + mouse.secondX // rect width
var height = mouse.firstY + mouse.secondY // rect height
Then, using these calculations, draw a rectangle on your canvas using firstX and firstY as the position parameters.
I hope this is relatively clear and helpful for you. If not, this might help;
http://simonsarris.com/blog/140-canvas-moving-selectable-shapes
I have made a little toy thing that would get the angle of my mouse in relation to the center point on the canvas. I attempted to make it so I can click to move that point, and came up with this:
http://jsfiddle.net/Strontium/7htLjvqs/
I have figured out how to make it so I can change the center point once without things acting weird, but passed that, I don't know what to do. I know what this is the case, though. It's because it is checking the relation between the original location of the coordinate grid and the new one, but after I move it, the numbers I used are no longer valid.
I need a way to get the location of the coordinate grid after using ctx.translate(), but I am not sure if that is even possible.
Instead of moving the whole canvas, why not just move the center point of your 'toy thing'?
So instead of
//move the location of the coordinate grid on click
canvas.addEventListener('click', function (evt) {
var mousePos = getMousePos(canvas, evt);
gridOffsetX = mousePos.x - 250;
gridOffsetY = mousePos.y - 250;
ctx.translate(gridOffsetX, gridOffsetY);
}, false);
var centerPoint = {x: 250, y:250}
//move the location of the coordinate grid on click
canvas.addEventListener('click', function (evt) {
centerPoint = getMousePos(canvas, evt);
}, false);
Demo:
http://jsfiddle.net/7264eahd/
I have some problem. I need to calculate some mouse move in pixels from mousedown event to mouseup. So i have this code:
selectArea.on({
mousedown : function(e) {
select = true;
},
mousemove : function(e) {
var x2, y2, offset = $(this).offset();
x2 = e.pageX - offset.left,
y2 = e.pageY - offset.top,
width = ?,
height = ?
...
},
mouseup : function() {
select = false;
}
});
Now i need to know how many pixels i have moved mouse from mousedown offset to mouseup offset, is there any posible to calculate this? Much thx for help.
There are two different solutions, depending on your definition of "how many pixels i have moved"
Scenario: Mouse moves 25px to the right and 75px to the left.
Solution 1: 50px; (distance between start and end)
In the mousedown handler you save the coordinates of the mouse. In the mouseup handler you compute the difference between the current mouse coordinates and the saved ones.
Solution 2: 100px; (distance traveled)
In the mousedown handler you set a boolean to indicate you are recording and save the coordinates of the mouse and initialize the distance with 0. In the mousemove handler you compute the difference between the current mouse coordinates and the saved coordinates (add it to distance) and then you overwrite the saved coordinates with your current mouse coordinates. In the mouseup handler you output the distance and unset the boolean.
You code seems to be for the second solution, but the question asks for the first.
Hello allWhat I mean is while the mouse is moving towards the edge of the window (x or y or both), I want the page to scroll, and when the mouse stops moving, I want the page to stop scrolling.There are numerous examples of how to scroll based on using a onClick event or a scroll zone at the edge of a window, but not much based on the movement of the mouse cursor.
Any help would be much appreciated.
Web pages are already designed to scroll using the scroll bar, page/home/end/arrow keys, etc. Is there any reason that's insufficient for your page? It's usually not a good idea to alter expected functionality.
You can read up on the mousemove event here. Anyway, the code below should work, but I really don't recommend using it. It can be especially disorienting for people with sensitive mice:
// Variables for current position
var x, y;
function handleMouse(e) {
// Verify that x and y already have some value
if (x && y) {
// Scroll window by difference between current and previous positions
window.scrollBy(e.clientX - x, e.clientY - y);
}
// Store current position
x = e.clientX;
y = e.clientY;
}
// Assign handleMouse to mouse movement events
document.onmousemove = handleMouse;