I have a simple html5/canvas and js-setup:
HTML
<canvas id="canvas" width="500" height="500" ></canvas>
JS
var canvas = $("#canvas"),
c = canvas[0].getContext("2d");
c.fillStyle = "gray";
c.fillRect(0, 0, 500, 500);
$(document).mousedown(function() {
console.log('down');
});
$(document).mouseup(function() {
console.log('up');
});
What buffles me is that I am able to log events with google chrome like so
down
up
down
up
down
down
down
down
up
down
down
down
meaning, I get consecutive down events. I think it is caused by the canvas element, because I am not able to reproduce this behavior without it.
Here is a fiddle: http://jsfiddle.net/SunnyRed/zcmaT/
Update
I think it only happens, when the user clicks and drags, which might be the case in my scenario. Here is a simple clicking demo. I can't reproduce it in Firefox and Opera.
The only way that I could replicate this is in your demo was that I either:
started a click outside the page (in another iframe from JS fiddle) and then did the mouse up over the canvas. Or
start the click on the canvas and then release it outside the bounds of the page (such as over the page padding).
I believe this is the correct behaviour.
Related
I'm working on an interface to allow the user to drag an object around the screen using hammer.js. In a desktop browser it works, but on mobile when I start dragging it works briefly, then suddenly acts as if the event's client coordinates suddenly went to 0,0.
I've got a simple SVG circle I'm trying to drag:
<svg version="1.1" viewBox="0 0 640 480" id="svg" style="width: 640px; height: 480px; top:0px; left: 0px; position: absolute;">
<circle class="selhan" cx="320" cy="240" r="200" id="circ"
style="fill: none; stroke: rgb(0, 0, 0); pointer-events: all;
touch-action: none; user-select: none; -webkit-user-drag: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
</circle>
</svg>
I'm setting up a simple pan handler:
var circ = document.getElementById("circ")
var Hn1=new Hammer(circ, {/*domEvents:true*/})
Hn1.add( new Hammer.Pan({ direction: Hammer.DIRECTION_ALL, threshold: 0, pointers:1 }) )
var X0,Y0
Hn1.on("panstart", function(e) {
var ob = e.target
var cx = ob.getAttribute("cx")
var cy = ob.getAttribute("cy")
X0=e.center.x-cx
Y0=e.center.y-cy
})
Hn1.on("pan", function(e) {
var ob = e.target
var X = e.center.x-X0
var Y = e.center.y-Y0
ob.setAttribute("cx",X)
ob.setAttribute("cy",Y)
})
I have created a Fiddle to demonstrate. On mobile, if I put my finger in the center of the circle and move very slowly I see the circle track for a brief period of time, but then suddenly the center jumps to 0,0, whereas on desktop it follows the pointer around all day.
I created an Updated Fiddle which displays when panstart, pancancel, and panend events occur. What I am seeing is that when the circle jumps to the origin I am getting a pancancel event. Why is my pan being cancelled even though I haven't lifted my finger from the screen?
Even stranger is this version. All I did was reverse the order of the spans (which display counters of how many times panstart, pancancel, and panend have occurred). If the spans come after the SVG, then suddenly I can pan the circle, but only horizontally. But if the spans come before or aren't there, then panning gets abruptly cancelled after a short amount of finger movement. Ok, turns out it's the element that is scrolling, not the circle. However, version 41 behaves strangely on desktop too... when I first tried it, I couldn't get it to respond to mouse events at all, but then it started working, and then it stopped again, all by simply changing to different versions and back.
Update: In an attempt to get to the bottom of why the pancancel callback is being called, I instrumented my copy of hammer.js. The PanRecognizer directionTest function (line 1778) is returning false, causing the cancel to be generated. What happens is always some form of "nothing happened", resulting in hasMoved being false, or distance being 0 (I tried setting threshold to -1, but this just moved where the problem showed up), or direction being DIRECTION_NONE.
This still doesn't make a lot of sense - I see this happen even when I'm panning at a fast enough rate that I should never get zero movement between two events, and even if I was panning slowly I wouldn't expect this to be a problem.
Update 2:
I added the following instrumentation:
Hn1.on("hammer.input",function(ev) {
console.log("debug",ev)
})
When I do this, I see a source event pointercancel which suggests that the browser is cancelling the pointer motion in the middle of is actually being used. In reviewing the documentation for this event, none of the four reasons mentioned for a pointer event being cancelled applies in this case. What is going on here?!
Michael, I ran into the same problem as you. I've filed a bug report on GitHub with example and video. Interesting to see you uncovered it has something to do with "pointercancel" being triggered by the browser, but so far it hasn't helped me figure out how to patch this issue. Did you make any progress on the matter?
For reference, this StackOverflow thread talks about the same issue. Unfortunately, none of the fixes has so far worked for me for HammerJS.
EDIT:
It turns out that preventing the default "touchmove" event handling on the window will solve this problem for any SVG element on the page. That's great news, but it also disables all scrolling behaviour on the page. What I've done instead is catching the "touchmove" event on the SVG object, so any descendants in it will pan properly. I'm not yet sure if it has any bad side effects, but so far it has meant that my panning in SVG finally works on Android browsers!
For completeness' sake, here is the necessary code:
const options = { passive: false }; // needed because Chrome has this set to "true" by default for "touchmove" events
mySVG.addEventListener(
"touchmove",
e => e.preventDefault(),
options
);
I just remembered that I just need to add jquery.ui.touch-punch.js and it works fine on mobile
library:
http://touchpunch.furf.com/
I want to do mouse click simulation on flash content. I found this document from firefox developer site Simulating mouse and key events. I used this html drawing page to test it and it works (see the image below). But when I do same thing on this drawing page which is flash based, it seems that firefox actually not click on flash content. But anyway it focus the page but I can't see that content has clicked.
This is the code I use for click. (I test this code on scratchpad)
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendMouseEvent("mousedown", x, y, 0, 1, 0);
utils.sendMouseEvent("mouseup", x, y, 0, 1, 0);
and this is the actual code I used to test it on scatchpad
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var x=580;
var y=400;
var counter=0;
var timer;
function simulate(){
utils.sendMouseEvent("mousedown", x, y, 0, 1, 0);
utils.sendMouseEvent("mouseup", x, y, 0, 1, 0);
x++;
y++;
if(counter>200){
clearTimeout(timer);
}
counter++;
}
timer=setInterval(function(){simulate();},10);
This is what I got when I run it in a html drawing page. But I got nothing when run this script in flash based page.
What I'm asking is how can I do mouse click simulation from firefox addon. But I don't like to use js-ctypes. Is it impossible to do mouse simulation on flash content without using native ctypes codes ?
there is some reasons why i don't like ctypes .for example it can click on any window not only browser also browser need to be maximized but above method click only on browser and work even when browser is minimized.
A canvas styled with visibility: hidden; is supposed to appear window-sized after one second with this code, right?
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// draw on canvas.getContext("2d") ...
window.setTimeout(function() {
canvas.style.visibility = "visible";
}, 1000);
It works with IE11, but not with Chrome32 (running on Windows7).
(Phew, I never though I would find something that works with IE but not with Chrome!)
I tried using display: none; and canvas.style.display= "block"; to hide and show the canvas and got the same behavior.
Here is a test: http://jsfiddle.net/CX49R/
Oddly, in jsfiddle with Chrome, the canvas (and its drawn content) appears after you move the mouse over the document area (after the function triggered by setTimeout is called, of course). But it never appears if the same HTML+CSS+JS code runs in a single Chrome tab/window (unless you open "Development tools" through "Inspect element", or click on the document area).
What am I missing here? I tried to reduce the code to the minimum of my original scenario.
It seems like it's somehow related to the canvas element. Creating a hidden parent div and showing that instead of the canvas element seems to solve the issue:
http://jsfiddle.net/CX49R/2/
<div id="wrapper">
<canvas id="myCanvas">Your browser does not support canvas.</canvas>
</div>
I don't have enough reputation to comment, so I'll give you an answer instead. The issue is not the setTimeout, the issue is with canvas.style.visibility = "visible";. I set up an alert in your timeout and it fired after a second, no problem. My only guess is that canvas.style.visibility is waiting on a mouse event to trigger itself.
I'm playing around with html5 and some javascript to make a minor sketchpad. Whenever I click down on the canvas in chrome, the cursor becomes a text cursor. I have tried putting cursor: hand in the css, but that doesn't seem to work. This has got to be an easy thing, but I look it up and can't find it anywhere
Use the disable text selection on the canvas. This works like a charm.
var canvas = document.getElementById('canvas');
canvas.onselectstart = function () { return false; } // ie
canvas.onmousedown = function () { return false; } // mozilla
Cheers,
Kris
While the other guys were absolutely bang on referring you to the quirksmode reference, that won't fix the problem you are having, and essentially you need to implement a variation of Kris's answer.
In my own implementation, I found that preventing default behaviour in the mousedown event was all that was required to stop that pesky text selection cursor:
function handleMouseDown(evt) {
evt.preventDefault();
evt.stopPropagation();
// you can change the cursor if you want
// just remember to handle the mouse up and put it back :)
evt.target.style.cursor = 'move';
// rest of code goes here
}
document.addEventListener('mousedown', handleMouseDown, false);
Hope that helps.
Cheers,
Damon.
Use pointer for your cursor property instead, like this:
canvas { cursor: pointer; }
hand is IE/Opera specific, you can see a full list of which cursors work in which browsers here.
I'm creating a web app that allows users to enter a number of colors, by specifying RGB values. Upon submission, the user will see a canvas with a solid rectangle drawn in the color chosen.
On this page, I have 7 canvases. The first one draws just fine, but none of the rest show up. The browser is Safari. Here's the relevant code:
First, the script element in the header, which defines the function I use to draw to the canvas.
<script language="JavaScript" TYPE="text/javascript"><!--
function drawCanvas(canvasId, red, green, blue) {
var theCanvas = document.getElementById("canvas" + canvasId);
var context = theCanvas.getContext("2d");
context.clearRect(0,0,100,100);
context.setFillColor(red,green,blue,1.0);
context.fillRect(0,0,100,100);
}
// -->
</script>
Next, the HTML source, where I have my canvas tags and some embedded Javascript to call my drawCanvas function
<canvas id="canvas0" width="100" height="100">
</canvas>
<script language="JavaScript" TYPE="text/javascript"><!--
drawCanvas(0,250,0,0);
// -->
</script>
.
. //more source
.
<canvas id="canvas1" width="100" height="100">
</canvas>
<script language="JavaScript" TYPE="text/javascript"><!--
drawCanvas(1,4,250,6);
// -->
</script>
Also provided is a screenshot. As you can see, the "red" canvas comes up just fine, but the second one, which should be green, doesn't show up at all. Any ideas?
There is some strangeness with the way setFillColor is interpreting the color values -- change the second call to drawCanvas(1,0,250,0) (instead of 4, 250, 6 for the last three args) and the green canvas shows just fine (on showing a local HTML file -- #Chetan's suggestion is worthwhile for pages that don't load that fast, but it doesn't solve your problem;-). This occurs in both Safari and Chrome. Unfortunately I cannot find a documentation for setFillColor (the coming HTML5 standard uses a different approach and does not appear to define such a method) so I can't check whether that's a webkit bug (webkit being what both Safari and Chrome are using for rendering) or a difference in what args setFillColor wants!
Edit: I experimented a bit and it seems it wants the RGB component in the range 0.0 to 1.0, not 0 to 255. Changing the call to setFillColor to:
context.setFillColor(red/256,green/256,blue/256,1.0);
therefore appears to work just fine.
You need to wait until the page has loaded until you can reliably do document.getElementById. You'd usually do DOM manipulation in window onload or DOMContentLoaded event.
This should work:
window.onload = function() {
drawCanvas(0,250,0,0);
drawCanvas(1,4,250,6);
}