Add touch event to html img control - html

I am trying to add a touch event to an img control on my html5 page.
This is what I have so far:
<img
src="Images/Home-icon.png"
onclick="Menu_Click('Home');"
ontouchend="Menu_Click('Home');"
draggable="false"
cssclass="iconImageStyle"
style="cursor: pointer;"
alternatetext="Home"
tooltip="Home"
height="32"
width="32" />
The click event from a normal web browser works properly.
But when I try to access it from my ipad, it does not react.
Help would be very welcomed.
Edit 1
Still no luck so far.
I tried to surround the img with a div and add the touchend event to the div, but it was not responding to it neither.
Edit 2
I followed a tutorial that works on my ipad.
Basically the tutorial is a canvas that displays the coordinates of the touch events inside the canvas.
I simply added the canvas and javascript to my page and let it overlap some of my img buttons.
My page reacts to the touch events and the canvas displays the coordinates properly.
Now this is where it is getting weird.
The buttons that appear inside the canvas now reacts to the touch end event but actually trigger the onclick event!
The same buttons that are not inside the canvas do not react to anything...
This is the tutorial code I pasted in my page
<script type="text/javascript">
var can, ctx, canX, canY, mouseIsDown = 0;
function init() {
can = document.getElementById("can");
ctx = can.getContext("2d");
document.body.addEventListener("mouseup", mouseUp, false);
document.body.addEventListener("touchcancel", touchUp, false);
}
function mouseUp() {
mouseIsDown = 0;
mouseXY();
}
function touchUp() {
mouseIsDown = 0;
// no touch to track, so just show state
showPos();
}
function mouseDown() {
mouseIsDown = 1;
mouseXY();
}
function touchDown() {
mouseIsDown = 1;
touchXY();
}
function mouseXY(e) {
if (!e)
var e = event;
canX = e.pageX - can.offsetLeft;
canY = e.pageY - can.offsetTop;
showPos();
}
function touchXY(e) {
if (!e)
var e = event;
e.preventDefault();
canX = e.targetTouches[0].pageX - can.offsetLeft;
canY = e.targetTouches[0].pageY - can.offsetTop;
showPos();
}
function showPos() {
// large, centered, bright green text
ctx.font = "24pt Helvetica";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "rgb(64,255,64)";
var str = canX + ", " + canY;
if (mouseIsDown)
str += " down";
if (!mouseIsDown)
str += " up";
ctx.clearRect(0, 0, can.width, can.height);
// draw text at center, max length to fit on canvas
ctx.fillText(str, can.width / 2, can.height / 2, can.width - 10);
// plot cursor
ctx.fillStyle = "white";
ctx.fillRect(canX - 5, canY - 5, 10, 10);
}
</script>
<canvas id="can" height="200" width="300" style="background-color: black">
</canvas>
I will continue to investigate.
But from what is looks like I will have to put a canvas behind my buttons...
I would prefer to avoid that if possible, but so far I do not see any other solutions.
If that works, I will post it as a solution unless someone wiser than me can propose something better.
Edit 3
I confirm that the javascript is not useful.
Just having the canvas behind the img make them respond to the click event.
I am not sure why this happen, but I will take it until I can find a better solution.
If anyone as an explanation or better solution, you are welcomed to post it.

Ok, finally figured it out.
Looks like the Touch Events do not work properly if you use absolute position for your elements.
I revised my div tables layout using css and now everything is working fine.

Related

is mouse in user drawn area on canvas

Basically, a user uploads a picture and then can paint on it, and save the result. Another user can then view the photo and if they click in the same area as painted, something happens.
So user 1 can make an area click-able for user 2 by drawing on the photo.
now the upload bit is fine, and painting with help from a tutorial and example I've got sussed out. But defining what area is click-able is a bit harder. For something like a rectangle its easy enough, I made an example.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var button = new Object();
button.x = 50;
button.y = 50;
button.width = 50;
button.height = 50;
button.rgb = "rgb(0, 0, 255)";
function drawbutton(buttonobject)
{
context.fillStyle = buttonobject.rgb;
context.fillRect (buttonobject.x, buttonobject.y, buttonobject.width, buttonobject.height);
context.strokeRect(buttonobject.x, buttonobject.y, buttonobject.width, buttonobject.height);
}
drawbutton(button);
function checkIfInsideButtonCoordinates(buttonObj, mouseX, mouseY)
{
if(((mouseX > buttonObj.x) && (mouseX < (buttonObj.x + buttonObj.width))) && ((mouseY > buttonObj.y) && (mouseY < (buttonObj.y + buttonObj.height))))
return true;
else
return false;
}
$("#myCanvas").click(function(eventObject) {
mouseX = eventObject.pageX - this.offsetLeft;
mouseY = eventObject.pageY - this.offsetTop;
if(checkIfInsideButtonCoordinates(button, mouseX, mouseY))
{
button.rgb = "rgb(0, 255, 0)";
drawbutton(button);
} else {
button.rgb = "rgb(255, 0, 0)";
drawbutton(button);
}
});
but when it comes to other shapes like circles, or just someone smothering the page, how would you go about detecting that ?
one thought I had was using the edited layer, making it hidden, and detecting a pixel color of say blue, from here but that limits the color use of the photo and im not entirely sure how to implement it. any other ideas ?
EDIT:
I figured out circles after some tinkering, using Pythagoras theorem to see if mouse coordinates are smaller than the radius, but this assumes circle center of 0,0, so then offset mouse by circles actual center. example
function checkIfInsideButtonCoordinates(buttonObj, mouseX, mouseY) {
actualX = mouseX - buttonObj.x
actualY = mouseY - buttonObj.y
mousesqX = actualX * actualX
mousesqY = actualY * actualY
sqR = buttonObj.r * buttonObj.r
sqC = mousesqX + mousesqY
if (sqC < sqR) return true;
else return false;
}
Here’s how to test whether user#2 is inside user#1’s paintings
Create a second canvas used to hit-test whether user#2 is inside of user#1’s paintings.
The hit-test canvas is the same size as the drawing canvas, but it only contains user#1’s paintings…not the image.
When user#1 is painting, also draw their paintings on the hit canvas.
When user#1 is done painting, save all their paintings from the hit canvas.
You have at least 2 ways to save user#1’s paintings from the hit canvas:
Serialize all the canvas commands needed to recreate the shapes/paths that user#1 paints.
Save the hit canvas as an image using canvas.toDataURL.
When user#2 clicks, check if the corresponding pixel on the hit canvas is filled or is transparent (alpha>0).
// getImageData for the hit-test canvas (this canvas just contains user#1's paintings)
imageDataData=hitCtx.getImageData(0,0,hit.width,hit.height).data;
// look at the pixel under user#2's mouse
// return true if that pixel is filled (not transparent)
function isHit(x,y){
var pixPos=(x+y*hitWidth)*4+3;
return( imageDataData[pixPos]>10)
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/etA5a/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:15px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var hit=document.getElementById("hit");
var hitCtx=hit.getContext("2d");
var user2=document.getElementById("user2");
var ctx2=user2.getContext("2d");
var canvasOffset=$("#user2").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var imageDataData;
var hitWidth=hit.width;
var img=document.createElement("img");
img.onload=function(){
// left canvas: image+user#1 paintings
ctx.globalAlpha=.25;
ctx.drawImage(img,0,0);
ctx.globalAlpha=1.00;
scribble(ctx,"black");
// mid canvas: just user#1 paintings (used for hittests)
scribble(hitCtx,"black");
// right canvas: user#2
ctx2.drawImage(img,0,0);
imageDataData=hitCtx.getImageData(0,0,hit.width,hit.height).data;
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";
function scribble(context,color){
context.beginPath();
context.moveTo(70,2);
context.lineTo(139,41);
context.lineTo(70,41);
context.closePath();
context.rect(39,54,22,30);
context.arc(73,115,3,0,Math.PI*2,false);
context.fillStyle=color;
context.fill();
}
function handleMouseMove(e){
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
// If user#2 has a hit on user#1's painting, mid-canvas turns red
var color="black";
if(isHit(mouseX,mouseY)){ color="red"; }
scribble(hitCtx,color);
}
function isHit(x,y){
var pixPos=(x+y*hitWidth)*4+3;
return( imageDataData[pixPos]>10)
}
$("#user2").mousemove(function(e){handleMouseMove(e);});
}); // end $(function(){});
</script>
</head>
<body>
<p>Left: original image with user#1 painting</p>
<p>Mid: user#1 painting only (used for hit-testing)</p>
<p>Right: user#2 (move mouse over hit areas)</p>
<canvas id="canvas" width=140 height=140></canvas>
<canvas id="hit" width=140 height=140></canvas>
<canvas id="user2" width=140 height=140></canvas><br>
</body>
</html>

move, delete and retrieve added rectangles positions in a HTML5 canvas

I have this code below to add a rectangle to a canvas, I have some questions regarding this.
Is it possible to move the added rectangle after it has been created?
Is it possible to delete a rectangle that has been added?
Can I retrieve all added rectangles positions (x, y, width and height) after I have added a bunch of rectangles and lets say by click of a button?
<script>
function rect()
{
var canvas = document.getElementById('drawing'),
ctx = canvas.getContext('2d'),
rect = {},
drag = false;
function init() {
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() {
drag = false;
}
function mouseMove(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY ;
//ctx.clearRect(0,0,canvas.width,canvas.height);
draw();
}
}
function draw() {
ctx.globalAlpha=0.5; // Half opacity
ctx.fillStyle= "#b0c2f7";
//ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
}
init();
}
</script>
<div id="canvasDiv">
<canvas id="drawing" width="580px" height="788px" style="border:2px solid #000; background: #FFF;"></canvas>
</div>
<script>
var canvas = document.getElementById('drawing');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 69, 50);
};
imageObj.src = 'http://localhost/test/Images/DSC0273446.jpg';
</script>
<div id="rect">
<p><button onclick="rect();">Rectangle</button></p>
</div>
Really appreciate all help I can get in this matter, thanks!
Is it possible to move the added rectangle after it has been created?
No, once drawn it is just pixels, there is no 'rectangle object' in the canvas. The usual approach to 'moving' a shape in canvas is to clearRect() (or the whole canvas) and then fillRect() in a slightly different position in a requestAnimationFrame controlled loop.
Is it possible to delete a rectangle that has been added?
As long as you've stored the location where you drew it, you can clearRect(). Note that this clears an area of pixels, not an object - the results of previous drawing operations will not automatically reappear.
Can I retrieve all added rectangles positions (x, y, width and height) after I have added a bunch of rectangles and lets say by click of a button?
No. The canvas does not store drawn objects, only pixel image data. If you want to keep track of the objects that have been drawn then you have to do that yourself. If you want to manipulate shapes instead of pixels then there are libraries like fabric.js which add an object manipulation layer on top of canvas, or you can use an svg element instead which will let you create graphics with normal DOM methods.

Actionscript Image with clickable spots

Can any one help in suggesting a solution for the following:
i have a large image, consider it as a map, i want to put this image in a viewer that is smaller than the image and i have to be able to scroll the image by clicking and dragging it.
and i want to put in this image a clickable spots in a specified x and y coordinated, and be able to click the spots.
when clicking any spot in the image, the image will be changed with a new spots.. and so on..
can you help in suggesting what is the best object to load the image in and be able to do all the mentioned points.
Thanks in advance.
This is easier than you think. You have a few goals to consider:
"i want to put this image in a viewer that is smaller than the image": You dont need anything special to do this. The concept of this is simply that you have a mask overlay where you want the large image visible.
var viewer:Sprite = new Sprite; //200x200
var imageMask:Sprite = new Sprite; //200x200
var imageContainer:Sprite = new Sprite; //400x500
imageContainer.mask = imageMask;
viewer.addChild(imageContainer);
//this will allow you to visibly see only 200x200 of the
//imageContainer at any time
"i have to be able to scroll the image by clicking and dragging it": This is a little more logic as the imageContainer will have to move in the -(negative) direction of the mouse. Add some listeners to check for mouse actions, and drag as required.
var allowDrag:Boolean = false;
imageContainer.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
imageContainer.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
imageContainer.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
function onMouseDown(e:Event):void{
allowDrag = true;
}
function onMouseUp(e:Event):void{
allowDrag = false;
}
function onMouseMove(e:Event):void{
//return if not dragging
if(!allowDrag) return;
//move the imageContainer in a -(negative) direction of the mouse
//use an index relative to the size of the viewer and imageContainer
var speed:Number = 0.5;
imageContainer.x -= (viewer.width/imageContainer.width)*speed;
imageContainer.y -= (viewer.height/imageContainer.height)*speed;
//clean the positions so the image remains within the viewer
if(imageContainer.x > 0) imageContainer.x = 0;
if(imageContainer.x < -viewer.width) imageContainer.x = -viewer.width;
if(imageContainer.y > 0) imageContainer.y = 0;
if(imageContainer.y < -viewer.height) imageContainer.y = -viewer.height;
}
"i want to put in this image a clickable spots in a specified x and y coordinated, and be able to click the spots": This also requires a little more thinking. In this case what you want to do is create [hotspots] on the image that are clickable, when clicked = do actions.
//USAGE
//define the click area coords
var clickCoords:Rectangle = new Rectangle();
clickCoords.x = 10; //starts at x 10
clickCoords.y = 10; //starts at y 10
clickCoords.width = 100; //100 wide
clickCoords.height = 100; //100 tall
//add the click listener
var clickArea:Sprite = hotSpot(imageContainer,clickCoords);
clickArea.addEventListener(MouseEvent.CLICK, onHotSoptClick);
//hot spot factory
function hotSpot(target:Sprite,coords:Rectangle):Sprite{
//create the hotspot
var hs:Sprite = new Sprite;
hs.graphics.beginFill(0,0);
hs.graphics.drawRect(0,0,coords.width,coords.height);
hs.graphics.endFill();
//add the hotspot to the target
hs.x = coords.x;
hs.y = coords.y;
target.addChild(hs);
}
function onHotSoptClick(e:MouseEvent):void{
//do something
}
IMPORTANT:
You may want to keep a list of hot spots you create so you can do garbage cleanup, and you plan on dynamically generating hotspots per image... then YOU MUST keep an active list of hot spots and remove when not in use.
You can catch the events MouseDown, MouseUp, MouseMove, MouseOut, on your viewing window, this way you can control exactly what do you want to do.
Here is the pseudo-code:
reset()
{
isDown=false;
downPointX=0;
downPointY=0;
distanceX=0;
distanceY=0;
}
onMouseDown()
{
isDown=true;
downPointX=mouseX;
downPointY=mouseY;
}
onMouseUp()
{
if(distanceX+distanceY==0 and isDown)
click(downPointX,downPointY);
reset();
}
onMouseMove()
{
if isDown then
distanceX=mouseX-downPointX;
distanceY=mouseY-downPointY;
drag(distanceX,distanceY);
endif;
}
onMouseOut()
{
reset();
}
drag(distanceX,distanceY)
{
change your map coordinates
}
click(downPointX,downPointY)
{
if(inSpot(downPointX,downPointY)==true)
changeMap();
endif;
}
changeMap()
{
change your maps and spots
}
avoid implementing any event for your spots sprites or you can get unexpected results.
You can check these for more information
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Sprite.html#eventSummary

Mouse Coordinates in HTML5 Canvas

I have tried many different ways of trying to get mouse coordinates in HTML5 canvas in compliment with video and none have seemed too work very well in either Chrome or Safari.
At the moment I am using:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="modernizr-1.6.min.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded,false);
var videoElement;
var VideoDiv;
var Object1;
var Mouse = {
x:0
x:y}
function eventWindowLoaded(){
videoElement = document.createElement("video");
videoDiv = document.createElement('div');
document.body.appendChild(videoDiv);
videoDiv.appendChild(videoElement);
videoDiv.setAttribute("style", "display:none;");
var videoType = supportedVideoFormat(videoElement);
if (videoType == ""){
alert("no video support");
return;
}
videoElement.setAttribute("src", "different_movement>" + videoType);
videoElement.addEventListener("canplaythrough", videoLoaded, false);
}
function supportedVideoFormat(video){
var returnExtension= "";
if(video.canPlayType("video/webm") =="probably" || video.canPlayType("video/webm") == "maybe"){
returnExtension = "webm";
} else if (video.canPlayType("video/mp4") == "probably" || video.canPlayType("video/mp4") == "maybe"){
returnExtension = "mp4";
}else if(video.canPlayType("video/ogg") == "probably" || video.canPlayType("video/ogg") == "maybe"){
returnExtension = "ogv";
}
return returnExtension;
}
function videoLoaded(event){
canvasApp();
}
canvasOne.onmousemove = function (event){
Mouse={
x: event.offsetX,
y: event.offsetY}
}
}
function canvasApp(){
function drawScreen(){
context.drawImage(videoElement, 0, 0);
context.fillStyle = '#ffffff';
context.fillText(Mouse.x, 280, 280);
context.fillText(Mouse.y, 280, 300);
}
var theCanvas = document.getElementByID('canvasOne');
var context = theCanvas.getContext('2d');
videoElement.play();
setinterval(drawScreen, 33);
}
</script>
</head>
<body>
<canvas id="canvasOne" width="640" height="480">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
</body>
</html>
The result of this is the 0,0 will be shown on the video from the initial variable set at 0,0 but then instead of changing as the mouse is moved around the screen, it stays 0,0. This leads me to believe that it is the part of the code that is finding the mouse coordinates that is not working.
I have tried various other attempts at finding mouse coordinates including:
Mouse={
x: event.pageX,
y: event.pageX}
,
if (e.pageY) {
posy = e.pageY;
} else if (e.clientY) {
posy = e.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
}
,
var mouseX;
var mouseY;
var pieceX;
var pieceY;
if (e.pageX || e.pageY) {
mouseX = e.pageX;
mouseX = e.pageY;
} else {
mouseX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
mouseY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
My end product is supposed to be a video that has mouse interactions that will play sounds when certain parts on the video are clicked (thus the part of video). I have tried not using canvas at all for this, and instead positioning a image on top of the canvas which has image mapping on it, but it doesn't seem to work.
Another issue I am going to run into when I figure out mouse coordinates is what I will test collisions with the mouse coordinates to initiate it to play the sounds.
EDIT:
Completely rewrote the code using e.offset, seems to work.
I used <iframe> to set an html page with a canvas element positioned top left of document. Then when I get clientX-Y it's origin is the top left of the canvas document, that's in the iframe, that you can have positioned anywhere on the canvas-containing document. It's easy as pie.
<iframe scrolling="no" height="100%" width="100%" src="canvas.html"></iframe>
also, I got the canvas to scale when it is scaled by style sheet. I added this to my canvas program.
c = canvas element, ctx = canvas context;
ctx.scale(c.width/630,c.height/800); // I originally intended it to be 630x800
(note: I am not sure if this answers your problem, but it is how I find coordinates without having to offset.)

Frame by frame animation in HTML5 with canvas

I have a flash animation I am trying to convert to HTML5. Now I have taken out all the images. For example in the hand animation, I have taken images of all hand images. I have made the canvas with the base drawing but I don't know how to replace those images frame by frame.
function draw(){
var canvas = document.getElementById('canvas');
if(canvas.getContext){
// canvas animation code here:
var ctx = canvas.getContext('2d');
var lhs = new Image();
lhs.src = "images/left_hnd_1.png";
lhs.onload = function(){
ctx.drawImage(lhs, 293, 137);
}
} else {
// canvas unsupported code here:
document.getElementById('girl').style.display = "block";
}
}
Now I have three more frame for this image. left_hnd_2.png, left_hnd_3.png & left_hnd_4.png. I would've used one image but the difference in frames is way too much for it to be done with one image. How can I animate this with the time differences I want.
Any ideas would be greatly appreciated. Thanks!
Try this:
var imgNumber = 1;
var lastImgNumber = 4;
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function(){
ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
ctx.drawImage( img, 0, 0 );
};
var timer = setInterval( function(){
if (imgNumber>lastImgNumber){
clearInterval( timer );
}else{
img.src = "images/left_hnd_"+( imgNumber++ )+".png";
}
}, 1000/15 ); //Draw at 15 frames per second
An alternative, if you only have 4 images, would be to create a single huge image with all four in a 'texture atlas', and then use setTimeout or setInterval to call drawImage() with different parameters to draw different subsets of the image to the canvas.
This worked for me as well! For some reason, it didn't work when I had used the OP's opening code: function draw(){
However when I used: window.onload = function draw() { the animation plays on the canvas. I'm also using about 150 PNG images with an Alpha channel so this is a great way to bring 'video' or create composites to the iPad/iPhone. I confirm that it does work on iPad iOS 4.3.