This code works in Google Chrome and IE but not in FireFox.
function drawChildren(names) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ctxcolor = "#000000";
if(listeners < 1){
c.addEventListener("click", getPosition, false);
listeners = 1;
} // At the click function "getPosition" is executed
}
function getPosition(event) {
if ( event.offsetX == null ) { // Firefox
clickedX = event.layerX;
clickedY = event.layerY;
} else { // Other browsers
clickedX = event.offsetX;
clickedY = event.offsetY;
}
checkCoordinates(clickedX, clickedY);
}
To answer your question posted in the above comment, your function getPosition() will be called whenever myCanvas is clicked. (Because your code says c.addEventListener("click", getPosition, false);)
Using your mouse position detection code, I'm not sure how the offset and layering works either, but if you use the following code, then I know you will always get x and y coordinates starting from the edge of the browser, rather than starting in any elements of your site:
if(evt.pageX){
var xPos = evt.pageX;
var yPos = evt.pageY;
}else if(evt.clientX){
var xPos = evt.clientX + ((document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
var yPos = evt.clientY + ((document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);
}
Your code may do the same thing as this, but I just wanted to provide what works for me also :)
Related
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 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
I have seen this question but it wasn't answered.
I have a object on a webpage that I want you to be able to drag and scroll the page. Reason behind this is that I set it up to be a swipe'able window but on some mobile devices the window takes up most of the screen. So in addition to horizontal "swiping" I want you to be able to vertically scroll the page as well.
This works great on a PC with a mouse. Everything is smooth and as expected. However, once you go to a mobile device (I have tried on Safari on an iPhone and the native browser on an Android 4 and both have the same issue) vertical scrolling is very "jittery".
At first I thought that it had to do with the fact that after you scroll the page, the next touchmove / MSPointerMove event will return a Ycord that different even though your finger might not have moved (due to the scrolling). But trying to accomidate for this didn't help.
Anyway, a demo of the whole thing can be found at http://www.leecolpi.com/NEW/m/
The full javascript can be found at http://www.leecolpi.com/NEW/m/JAVASCRIPT/slide_window.js
The relivant javascript is (might be easier to read via the link above):
function mouseMoveTrigger(evt)
{
if (!isDragging) return;
if (!touchEvents && !pointerEvents)
if (window.event) evt=window.event;
if (evt.preventDefault)
evt.preventDefault();
else
evt.returnValue = false;
var newX;
var newY;
if (touchEvents)
{
newX = offsetX - evt.changedTouches[0].pageX;
offsetX = evt.changedTouches[0].pageX;
newY = offsetY - evt.changedTouches[0].pageY;
offsetY = evt.changedTouches[0].pageY;
}
else
{
newX = offsetX - evt.clientX;
offsetX = evt.clientX;
newY = offsetY - evt.clientY;
offsetY = evt.clientY;
}
var thingsToSlide = document.getElementById("pictureFrame").getElementsByTagName("li");
newX = parseInt(thingsToSlide[0].style.right.replace(/px/g,'')) + newX;
if (newX < 0)
newX = 0;
if (newX > ((thingsToSlide[0].offsetWidth * (thingsToSlide.length - 1))) + 30)
newX = (thingsToSlide[0].offsetWidth * (thingsToSlide.length - 1)) + 30;
window.scrollBy(0, newY);
for (var i=0; i<thingsToSlide.length; i++)
thingsToSlide[i].style.right = newX + "px";
return false;
}
As you can see, all I am doing is a scrollBy of the difference of the Yvalue for the current and previous "move" events. Again, this works like a champ on a computer which is exactly where I don't care if it works or not. Only problem is every mobile device I have tried it on.
I am using preventDefault() (or setting the return value = false if I can't do that), but could I be triggering another event and not knowing it? I tried with my init to only listen for certian events. Here is my init function (might be easier to read via the link above):
function initSlider()
{
var pageBody = document.getElementsByTagName("body")[0];
var thingsToSlide = document.getElementById("pictureFrame");
if (thingsToSlide)
{
var thingsToSlideList = document.getElementById("pictureFrame").getElementsByTagName("li");
for (var i=0; i<thingsToSlideList.length; i++)
thingsToSlideList[i].style.right = "0px";
if (touchEvents)
{
thingsToSlide.addEventListener("touchstart", onTouchStart, false);
}
else if (pointerEvents)
{
thingsToSlide.addEventListener("MSPointerDown", onTouchStart, false);
}
else
{
thingsToSlide.ondrag=function() { return false; };
thingsToSlide.onselectstart=function() { return false; };
thingsToSlide.onmousedown=function(event) { mouseDownTrigger(this,event); };
}
if (touchEvents)
{
pageBody.addEventListener("touchmove", mouseMoveTrigger, false);
pageBody.addEventListener("touchend", mouseUpTrigger, false);
pageBody.addEventListener("touchcancle", mouseUpTrigger, false);
}
else if (pointerEvents)
{
pageBody.addEventListener("MSPointerMove", mouseMoveTrigger, false);
pageBody.addEventListener("MSPointerUp", mouseUpTrigger, false);
pageBody.addEventListener("MSPointerCancel", mouseUpTrigger, false);
}
else
{
document.onmousemove = mouseMoveTrigger;
document.onmouseup = mouseUpTrigger;
}
}
}
Any help would be greatly appreciated. Thanks in advance
<script type="text/javascript">
var IE = document.all?true:false
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.onmousemove = getMousePos;
// Temporary variables to hold mouse x-y pos.s
var tempX = 30;
var tempY = 30;
function getMousePos(e) {
if (IE) { // grab the x-y pos.s if browser is IE
tempX = event.clientX + document.body.scrollLeft
tempY = event.clientY + document.body.scrollTop
} else { // grab the x-y pos.s if browser is NS
tempX = e.pageX
tempY = e.pageY
}
// catch/correct negative values
if (tempX < 0){tempX = 0}
if (tempY < 0){tempY = 0}
// show the position values in the form
document.MouseDisplay.MouseX.value = tempX;
document.MouseDisplay.MouseY.value = tempY;
return true;
}
// execute function
if (tempY < 30) {
alert('tempY is found to be less than 30');
}
</script>
I found this code at hotscript and codelifter http://www.codelifter.com/main/javascript/capturemouseposition1.html, it was from an old thread but I believe it's got what I need to achieve. I want to execute a function whenever the mouse Y position is less than 30.
I'm a beginner at programming, hope that I can slowly learn from samples here.
My question is, why is the alert command not triggered? What am I missing here. I did a simple button to call the function it works tho.
<script type="text/javascript">
function myFunction() {
alert('tempY is found to be less than 30');
}
</script>
Haven't tried your code but assuming it does work when the mouse moves, to see your alert just move that line inside the function :
var IE = document.all?true:false
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.onmousemove = getMousePos;
// Temporary variables to hold mouse x-y pos.s
var tempX = 30;
var tempY = 30;
function getMousePos(e) {
if (IE) { // grab the x-y pos.s if browser is IE
tempX = event.clientX + document.body.scrollLeft
tempY = event.clientY + document.body.scrollTop
} else { // grab the x-y pos.s if browser is NS
tempX = e.pageX
tempY = e.pageY
}
// catch/correct negative values
if (tempX < 0){tempX = 0}
if (tempY < 0){tempY = 0}
// show the position values in the form
document.MouseDisplay.MouseX.value = tempX;
document.MouseDisplay.MouseY.value = tempY;
// execute function
if (tempY < 30) {
alert('tempY is found to be less than 30');
}
return true;
}
I made an little test to check out HTML 5.
In my test I have a <canvas> and want to drag this one.
But I have a little problem, my canvas is kinda shaking.
Could someone help me plz?
Fiddle:
http://jsfiddle.net/wnxFK/
Calculating layerX and layerY once at the start of the drag helps create a smoother effect:
http://jsfiddle.net/jB5YN/
So at the start you have:
var mousedown = false;
var layerX = 0;
var layerY = 0;
function onMouseDown(event)
{
var canvas = document.getElementById("myCanvas");
mousedown = true;
layerX = event.layerX;
layerY = event.layerY;
// Code
drag(event);
}
And when you come to drag you have:
function drag(event)
{
var clientX = ('clientX' in event) ? (event.clientX) : (event.offsetX);
var clientY = ('clientY' in event) ? (event.clientY) : (event.offsetY);
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d');
var x = (event.clientX- layerX);
var y = (event.clientY- layerY);
var log = document.getElementById("log");
log.innerHTML = "x: " + x + " y: " + y;
canvas.style.left = x + 'px';
canvas.style.top = y + 'px';
}
Also, I've moved the events to hook up only once at the start, just feels a bit neater to me!
Update
Just for a complete answer, if you want to avoid layerX and layerY which seem to be in the process of being deprecated in webkit, you can calculate them yourself:
http://jsfiddle.net/B3TYe/
The change being:
var offsetX= 0;
var offsetY= 0;
function onMouseDown(event)
{
var canvas = document.getElementById("myCanvas");
mousedown = true;
var left = (canvas.style.left=="")? 0:parseInt(canvas.style.left);
var top = (canvas.style.top=="")? 0:parseInt(canvas.style.top);
offsetX = event.pageX - left;
offsetY = event.pageY - top;
// Code
drag(event);
}
Andy
I wouldn't use clientX and layerX properties. Here's an example:
http://jsfiddle.net/wnxFK/3/
function drag(event)
{
var canvas = document.getElementById("myCanvas");
canvas.style.left = event.pageX - 50 + 'px';
canvas.style.top = event.pageY - 50 + 'px';
}