I'm attempting to make it, so that when the mouse is within the boundaries set by var play, it changes image. I used the same method I've used for changing images on click, but mouseover and mouseout don't want to work here.
var play = {
x: 650,
y: 360,
width: 200,
height: 100
}
var playUpButton = new Image();
playUpButton.src = "images/PlayUp.png";
var playDownButton = new Image();
playDownButton.src = "images/PlayDown.png";
var playHovering = false;
thisCanvas.addEventListener('click', checkPlay);
thisCanvas.addEventListener('mouseover', hoverPlay, false);
thisCanvas.addEventListener('mouseout', hoverPlay, false);
function seen_move(e)
{
var bounding_box = thisCanvas.getBoundingClientRect();
mouseX = ((e.clientX-bounding_box.left) *(thisCanvas.width/bounding_box.width));
mouseY = ((e.clientY-bounding_box.top) * (thisCanvas.height/bounding_box.height));
}
function draw_start()
{
context.drawImage(menubg, menubg.x, menubg.y, menubg.width, menubg.height);
if(playHovering)
{
context.drawImage(playDownButton, play.x, play.y, play.width, play.height);
}
}
function mouseInArea(top, right, bottom, left)
{
if(mouseX >= left && mouseX < right && mouseY >= top && mouseY < bottom)
{
return true;
}
else
{
return false;
}
}
function hoverPlay()
{
if(mouseInArea(play.y, play.x + play.width, play.y + play.height, play.x))
{
console.log("Hovering");
if(playHovering)
{
playHovering = false;
}
else
{
playHovering = true;
}
}
}
It looks like the following is missing from your code.
var thisCanvas = document.getElementById("thisCanvas");
The function checkPlay also seems to be missing.
Take a look at these articles:
http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
http://www.informit.com/articles/article.aspx?p=1903884&seqNum=6
You must call function seen_move(e) to get the mouse position.
BTW, I'm confused about what the extra code in seen_move is. I'm guessing you're making the mouse position relative to the bounding box. I just mention it in case that's also a problem:
// this usually get the mouse position
var bounding_box = thisCanvas.getBoundingClientRect();
mouseX = e.clientX-bounding_box.left;
mouseY = e.clientY-bounding_box.top;
// and you have this extra bit:
// *(thisCanvas.width/bounding_box.width)); and
// * (thisCanvas.height/bounding_box.height));
mouseX = ((e.clientX-bounding_box.left) *(thisCanvas.width/bounding_box.width));
mouseY = ((e.clientY-bounding_box.top) * (thisCanvas.height/bounding_box.height));
Related
I am trying to change the length of two bars (div) by mouse dragging (extending one example in eloquetjavascript book chapter 14, which involves changing the length of one bar by dragging the mouse.) The intended behavior is clicking on any bar, moving the mouse when holding the left mouse key would change the length of that bar.
Here is my implementation (also available on JSfiddle)
<script>
var lastX; // Tracks the last observed mouse X position
var rect1 = document.getElementById("bar1");
var rect2 = document.getElementById("bar2");
rect1.addEventListener("mousedown", function(){watchmousedown(rect1)});
rect2.addEventListener("mousedown", function(){watchmousedown(rect2)});
function watchmousedown(rec) {
if (event.which == 1) {
lastX = event.pageX;
addEventListener("mousemove",function(){moved(rec)});
event.preventDefault(); // Prevent selection
} else {
removeEventListener("mousedown", watchmousedown)}
}
function moved(rec) {
if (event.which != 1) {
removeEventListener("mousemove", moved);
} else {
var dist = event.pageX - lastX;
var newWidth = Math.max(10, rec.offsetWidth + dist);
rec.style.width = newWidth + "px";
lastX = event.pageX;
}
}
</script>
The problem is I can only change the length of the bar where the first mouse click event happened. I assume I didn't handle the mousedown event correctly (probably need a reset some how).
I am new to javascript, help on programming style is also appreciated.
Thanks!
Add rec. to addEventListener("mousemove", function () { so that the event listener is bound to the rec you clicked on instead of to the window.
function watchmousedown(rec) {
if (event.which == 1) {
lastX = event.pageX;
rec.addEventListener("mousemove", function () {
moved(rec)
});
event.preventDefault(); // Prevent selection
} else {
rec.removeEventListener("mousedown", watchmousedown)
}
}
Edit: I there are some event handlers not being cleaned up properly. I don't know if this would be my final code, but this is closer to how I would do it:
var lastX; // Tracks the last observed mouse X position
var rect1 = document.getElementById("bar1");
var rect2 = document.getElementById("bar2");
var moveRect1 = function () {
console.log(arguments);
moved(rect1)
};
var moveRect2 = function() {
console.log(arguments);
moved(rect2);
}
var watchRect1 = function () {
console.log(arguments);
watchmousedown(moveRect1)
};
var watchRect2 = function () {
console.log(arguments);
watchmousedown(moveRect2)
};
rect1.addEventListener("mousedown", watchRect1);
rect2.addEventListener("mousedown", watchRect2);
window.addEventListener("mouseup", function() {
removeEventListener("mousemove", moveRect1);
removeEventListener("mousemove", moveRect2);
});
function watchmousedown(moverec) {
if (event.which == 1) {
lastX = event.pageX;
addEventListener("mousemove", moverec);
event.preventDefault(); // Prevent selection
}
}
function moved(rec) {
if (event.which == 1) {
var dist = event.pageX - lastX;
var newWidth = Math.max(10, rec.offsetWidth + dist);
rec.style.width = newWidth + "px";
lastX = event.pageX;
}
}
Edit: removed a line that didn't do anything
I see other similar questions asked, but the answers don't actually solve the problem.
I have this event listener:
function bigButton(x, y, strTxt, doFunction)
{
var getID = document.getElementById("canvas_1");
if (getID.getContext)
{
var ctx = getID.getContext("2d");
var btnW = 150;
var btnH = 50;
var cx = x - btnW/2;
var cy = y - btnH/2;
var left = cx;
var right = cx + btnW;
var top = cy;
var bottom = cy + btnH;
bbWhite(cx, cy, btnW, btnH, strTxt);
getID.addEventListener("mousemove", function bbAnim(event)
{
var mousePos = getMousePos(getID, event);
var rect = getID.getBoundingClientRect();
var mouseX = mousePos.x;
var mouseY = mousePos.y;
if (mouseX >= left
&& mouseX <= right
&& mouseY >= top
&& mouseY <= bottom)
{
bbBlack(cx, cy, btnW, btnH, strTxt);
}
else
{
bbWhite(cx, cy, btnW, btnH, strTxt);
}
}, false);
getID.addEventListener("click", function bbClick(event)
{
var mousePos = getMousePos(getID, event);
var rect = getID.getBoundingClientRect();
var clickX = mousePos.x;
var clickY = mousePos.y;
if (clickX >= left
&& clickX <= right
&& clickY >= top
&& clickY <= bottom)
{
doFunction();
}
}, false);
}
}
I want to remove it, because once I click it, I want to clear the canvas and do other things. Yet I have to have a named function to remove it. As far as I know I can't have a named listener without losing all the variables used in the anonymous function. How do I have a named listener in this situation? This is one of the very first issues with events that I have come across with learning JavaScript for the canvas. I'm surprised this isn't one of the first things you find in any tutorial.
UPDATE:
I have made it into a named function, but I still have no way to remove it (and the mousemove event) after the button is clicked.
Removing it is pretty much the same as adding it
getID.addEventListener("click", handler, false);
function handler(event) {
this.removeEventListener('click', handler, false);
var mousePos = getMousePos(getID, event);
var rect = getID.getBoundingClientRect();
var clickX = mousePos.x;
var clickY = mousePos.y;
if (clickX >= left
&& clickX <= right
&& clickY >= top
&& clickY <= bottom)
{
doFunction();
}
}
and the event and value of this stays the same wether or not you reference it by name or not.
I am using jsDraw2D javascript library to draw diagrams like circle ,rectangle,line etc.in a div. Now u want to save these graphics whatever i have drawn as a div data , so that i can display it whenever i want . Is that possible ?? or as a image to the some directory? Any help is greatly appreciated
var canvasDiv=document.getElementById("canvas");
var gr=new jsGraphics(canvasDiv);
var penWidth;
var col;
var pen;
var d1,d2;
setPenColor(true);
var point;
var pointDiv;
canvasDiv.onmousemove = getMouseXY;
canvasDiv.onclick=drawPoint;
var mouseX = 0;
var mouseY = 0;
var points=new Array();
//Get mouse position
function getMouseXY(e)
{
if (ie)
{
mouseX = event.clientX + document.body.parentElement.scrollLeft;
mouseY = event.clientY + document.body.parentElement.scrollTop;
} else {
mouseX = e.pageX
mouseY = e.pageY
}
if (mouseX < 0){mouseX = 0}
if (mouseY < 0){mouseY = 0}
mouseX =mouseX - canvasDiv.offsetLeft;
mouseY =mouseY - canvasDiv.offsetTop;
return true;
}
function setPenColor(noAlert)
{
col=new jsColor("blue");
pen=new jsPen(col,1);
if(!noAlert)
{
if(!point)
{
alert("Please click at any location on the blank canvas at left side to plot the point!");
return false;
}
}
return true;
}
function drawPoint() {
pointDiv = gr.fillRectangle(new jsColor("green"),new jsPoint(mouseX-6,mouseY-6),6,6);
point = new jsPoint(mouseX-3,mouseY-3);
}
etc.
I want to achieve 'Panning' in svg while 'dragging' an element in particular direction.
Let say i select an element and start 'dragging' it upward untill it reached top of screen, now my svg should pan upwards automatically, without causing any problem with dragging. how i can achieve this.?
i have made a small mockup of this, where user can select and drag elements. it also contain two button, which cause svg to pan upward and downward. I am achiveing 'Panning' by changing 'ViewBox' of svg. ( i have to use this logic, i cannot use any other solution);
here is the fiddle link : http://jsfiddle.net/9J25r/
Complete Code:-
addEventListener('mousedown', mousedown, false);
var mx, my;
var dx, dy;
var mainsvg = document.getElementById('svg');
var selectedElement;
var eleTx, eleTy;
function getSvgCordinates(event) {
var m = mainsvg.getScreenCTM();
var p = mainsvg.createSVGPoint();
var x, y;
x = event.pageX;
y = event.pageY;
p.x = x;
p.y = y;
p = p.matrixTransform(m.inverse());
x = p.x;
y = p.y;
x = parseFloat(x.toFixed(3));
y = parseFloat(y.toFixed(3));
return {x: x, y: y};
}
function mousedown(event) {
if (event.target.id === 'arrow_t') {
panning('up');
}
else if (event.target.id === 'arrow_b') {
panning('down');
}
else if (event.target.id.split('_')[0] === 'rect') {
selectedElement = event.target;
var translatexy = selectedElement.getAttribute('transform');
translatexy = translatexy.split('(');
translatexy = translatexy[1].split(',');
eleTx = translatexy[0];
translatexy = translatexy[1].split(')');
eleTy = translatexy[0];
eleTx = parseFloat(eleTx);
eleTy = parseFloat(eleTy);
var xy = getSvgCordinates(event);
mx = xy.x;
my = xy.y;
mx = parseFloat(mx);
my = parseFloat(my);
addEventListener('mousemove', drag, false);
addEventListener('mouseup', mouseup, false);
}
}
function drag(event) {
var xy = getSvgCordinates(event);
dx = xy.x - mx;
dy = xy.y - my;
selectedElement.setAttribute('transform', 'translate(' + (eleTx + dx) + ',' + (eleTy + dy) + ')');
}
function mouseup(event) {
removeEventListener('mousemove', drag, false);
removeEventListener('mouseup', mouseup, false);
}
function panning(direction) {
var viewBox = svg.getAttribute('viewBox');
viewBox = viewBox.split(' ');
var y = parseFloat(viewBox[1]);
if (direction === 'up')
{
y+=5;
}
else if (direction === 'down')
{
y-=5;
}
viewBox=viewBox[0]+' '+y+' '+viewBox[2]+' '+viewBox[3];
svg.setAttribute('viewBox',viewBox);
}
here is the fiddle link : http://jsfiddle.net/9J25r/
EDIT:- (UPDATE)
I use the solution of Ian , it works well on the sample, but when i applied it to my original application, it did not work. check the below gif. You can see the 'gap' between mouse pointer and element. how i can remove that? .
This is one way, I've just done it with the Y/vertical for the moment...
You may want to adjust it, so that if the cursor is off the screen it adjusts the viewBox automatically as well, depends how you want it to drag (otherwise you will need to keep wiggling it to kick the drag func in).
var viewBox = svg.getAttribute('viewBox');
viewBoxSplit = viewBox.split(' ');
if( ely < viewBoxSplit[1] ) {
panning('down');
} else if( ely + +event.target.getAttribute('height')> +viewBoxSplit[1] + 300 ) {
panning('up');
}
jsfiddle here
This question already has answers here:
Moveable/draggable <div>
(9 answers)
Closed 5 years ago.
I want to create a movable/draggable div in native javascript without using jquery and libraries. Is there a tutorial or anythign?
OK, here's my personal code that I use for lightweight deployments (projects where using a library is either not allowed or overkill for some reason). First thing first, I always use this convenience function so that I can pass either an id or the actual dom element:
function get (el) {
if (typeof el == 'string') return document.getElementById(el);
return el;
}
As a bonus, get() is shorter to type than document.getElementById() and my code ends up shorter.
Second realize that what most libraries are doing is cross-browser compatibility. If all browsers behave the same the code is fairly trivial. So lets write some cross-browser functions to get mouse position:
function mouseX (e) {
if (e.pageX) {
return e.pageX;
}
if (e.clientX) {
return e.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
}
return null;
}
function mouseY (e) {
if (e.pageY) {
return e.pageY;
}
if (e.clientY) {
return e.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
}
return null;
}
OK, the two functions above are identical. There're certainly better ways to write them but I'm keeping it (relatively) simple for now.
Now we can write the drag and drop code. The thing I like about this code is that everything's captured in a single closure so there are no global variables or helper functions littering the browser. Also, the code separates the drag handle from the object being dragged. This is useful for creating dialog boxes etc. But if not needed, you can always assign them the same object. Anyway, here's the code:
function dragable (clickEl,dragEl) {
var p = get(clickEl);
var t = get(dragEl);
var drag = false;
offsetX = 0;
offsetY = 0;
var mousemoveTemp = null;
if (t) {
var move = function (x,y) {
t.style.left = (parseInt(t.style.left)+x) + "px";
t.style.top = (parseInt(t.style.top) +y) + "px";
}
var mouseMoveHandler = function (e) {
e = e || window.event;
if(!drag){return true};
var x = mouseX(e);
var y = mouseY(e);
if (x != offsetX || y != offsetY) {
move(x-offsetX,y-offsetY);
offsetX = x;
offsetY = y;
}
return false;
}
var start_drag = function (e) {
e = e || window.event;
offsetX=mouseX(e);
offsetY=mouseY(e);
drag=true; // basically we're using this to detect dragging
// save any previous mousemove event handler:
if (document.body.onmousemove) {
mousemoveTemp = document.body.onmousemove;
}
document.body.onmousemove = mouseMoveHandler;
return false;
}
var stop_drag = function () {
drag=false;
// restore previous mousemove event handler if necessary:
if (mousemoveTemp) {
document.body.onmousemove = mousemoveTemp;
mousemoveTemp = null;
}
return false;
}
p.onmousedown = start_drag;
p.onmouseup = stop_drag;
}
}
There is a reason for the slightly convoluted offsetX/offsetY calculations. If you notice, it's just taking the difference between mouse positions and adding them back to the position of the div being dragged. Why not just use the mouse positions? Well, if you do that the div will jump to the mouse pointer when you click on it. Which is a behavior I did not want.
You can try this
HTML
<div id="one" style="height:50px; width:50px; border:1px solid #ccc; background:red;">
</div>
Js Script for draggable div
window.onload = function(){
draggable('one');
};
var dragObj = null;
function draggable(id)
{
var obj = document.getElementById(id);
obj.style.position = "absolute";
obj.onmousedown = function(){
dragObj = obj;
}
}
document.onmouseup = function(e){
dragObj = null;
};
document.onmousemove = function(e){
var x = e.pageX;
var y = e.pageY;
if(dragObj == null)
return;
dragObj.style.left = x +"px";
dragObj.style.top= y +"px";
};
Check this Demo
This code corrects the position of the mouse (so the dragged object doesn't jump when you start dragging) and works with touch screens/phones as well
var dragObj = null; //object to be moved
var xOffset = 0; //used to prevent dragged object jumping to mouse location
var yOffset = 0;
window.onload = function()
{
document.getElementById("menuBar").addEventListener("mousedown", startDrag, true);
document.getElementById("menuBar").addEventListener("touchstart", startDrag, true);
document.onmouseup = stopDrag;
document.ontouchend = stopDrag;
}
function startDrag(e)
/*sets offset parameters and starts listening for mouse-move*/
{
e.preventDefault();
e.stopPropagation();
dragObj = e.target;
dragObj.style.position = "absolute";
var 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; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
function dragObject(e)
/*Drag object*/
{
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";
}
}
function stopDrag(e)
/*End dragging*/
{
if(dragObj)
{
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
div{height:400px; width:400px; border:1px solid #ccc; background:blue; cursor: pointer;}
<div id="menuBar" >A</div>
<div draggable=true ondragstart="event.dataTransfer.setData('text/plain', '12345')">
drag me
</div>
<div ondragover="return false;" ondrop="this.innerHTML=event.dataTransfer.getData('text/plain')">
drop on me
</div>