Today I wanted to write the second part of my Framework Design mini series - but then I found out something interesting about HTML5 canvas. I will write the framework design post later this week.
Soooo…. I was again experimenting with the HTML5 canvas. When I was writing scribblingspree.com, I found out that the canvas uses it’s own width and height properties when calculating coordinates, no matter how big it really is. This means, the following canvas will work as if it was 100x100 pixels large, even though it really is larger, depending on the screen size:
<head> <style> .drawing_canvas { width: 100%; height: 100%; cursor: crosshair; } </style> </head> <body> <canvas class="drawing_canvas" width="100" height="100" style="--yt-width: 100px; --yt-height: 100px"> </canvas> </body>
So, in the above canvas, a line from [0, 0] to [100, 100] will be drawn across the entire window, not just from the top left corner to the point [100px, 100px]. This behavior was pretty consistent across browsers - at least on the desktop, but also on Android - so I calculated a factor based on canvas.width
and canvas.scrollWidth
and used that to calculate the correct coordinates.
Also, when processing mouse events, the event object has properties offsetX
and offsetY
. These properties represent the mouse position relative to the element on which the event occured. So, these properties can be used directly for calculating the coordinates within the canvas as described above.
This did not work on the iPad. Not at all.
It seems like the browser on the iPad uses the actual size of the canvas to calculate coordinates. Setting the width and height of the canvas to be equal to the scroll width and scroll height did it for me, but it only works as long as the window is not resized. On resize this has to be done again.
Also, the touch event on the iOS browser does not contain the properties offsetX
and offsetY
. This means that I have to work with the page coordinates of the touch event. But there is one little inconvenience with using the page coordinates: One has to know the top and left offset of the canvas, which is not immediately available in JavaScript. With this neat trick I came up with the following solution that works on the iPad and on the desktop:
DrawingCanvas = function(canvasId) { var canvas = document.getElementById(canvasId); this.canvas = canvas; this.canvas.width = this.canvas.scrollWidth; this.canvas.height = this.canvas.scrollHeight; var that = this; this.canvas.addEventListener('touchstart', function(e) { e.preventDefault(); that.canvasTouchDragStart(e);}); /* ... */ } DrawingCanvas.prototype = { canvasTouchDragStart : function(e) { var x = e.touches[0].offsetX; var y = e.touches[0].offsetY; if(x === undefined) { var totalOffsetX = 0; var totalOffsetY = 0; var curElement = this.canvas; do{ totalOffsetX += curElement.offsetLeft; totalOffsetY += curElement.offsetTop; } while(curElement = currentElement.offsetParent) x = event.pageX - totalOffsetX; y = event.pageY - totalOffsetY; } this.canvasDragStart(e, x, y); }, /* ... */ }
You might also be interested in...
- CSS Vertical Align: Divs A short tutorial that shows you how you can align your divs vertically.
- Software Quality for Developers Learn about software quality, TDD, ... in this 6-part video course.
- Offline Web Applications: A mini series where you'll learn how to create web applications that are available offline.