Bug in Click Behavior of HTML5 Canvas on Webkit Browser Versions Below 535 for Android Native and iOS5 Safari

Recently, I encountered a peculiar bug in Android where positioning a canvas element on the Native Android Browser (WebKit 534.4) using css

position:absolute; top:10px; left:100px;
resulted in the duplicated Canvas being rendered to the browser while ignoring the positioning.

For example, if I positioned a canvas at top:100px; left:100px; it would be displayed correctly, but the GPU accelerated canvas would show up in the top left corner instead (refer to images in my previous query).

I managed to find a workaround by using CSS translate like so:

transform: translate(100px, 100px);
. This resolved the duplication issue as both canvases were now rendered in the same location without duplication. However, this fix introduced a clicking bug.

When centering the canvas and the window width is smaller than the device width, the X position becomes negative, restricting the clickable area of the canvas to only what would be visible without any positioning.

It's quite complicated to explain, so perhaps this image will provide better clarity.

Despite implementing this code snippet, the expected alert doesn't trigger from half of the screen:

canvas.addEventListener('click', function(e) { alert('click'; });


My assumption is that using CSS position top and left entails moving the canvas with CPU, causing misplacement of the GPU generated canvas. On the other hand, CSS translate uses GPU to relocate the canvas, resulting in correct positioning of the GPU generated canvas, yet the CPU registers mouse events without factoring in this offset... frustrating!


Update: Further testing on various devices confirms that this seems to be a prevalent issue among browsers using Webkit versions below 535, affecting most Android native browsers and Safari on iOS 5.

Answer №1

After some adjustments, I managed to solve the issue at hand. However, it seems like this solution is quite specific to this particular case.

if(webKitVer < 535) {
     document.body.style.paddingTop = pos.top + "px";
    if(canSeeWholeOfCanvas) {
        canwrap.style.transform = 'translateX('+pos.left+'px)';
        canwrap.style.left = 'auto';
    } else {
        canwrap.style.left = pos.left + "px";
        canwrap.style.transform  = 'none';
    }
} 
else 
{
    //standard all browsers
    canwrap.style.transform = 'translate('+pos.left+'px, '+pos.top+'px)';
}

Although it may appear somewhat unconventional and specific, this approach does get the job done.


In older webkit browsers (typically Android native browsers and IOS5 safari), there are two issues:

If the canvas is positioned using CSS properties for top and left, a duplicate GPU-rendered canvas generated for GPU hardware acceleration may not align correctly with these properties.

On the other hand, if the canvas is positioned using a CSS transform, the GPU duplicate canvas aligns properly. However, if the canvas is positioned at a negative X position, only the visible part of the canvas without the CSS transformation is clickable.

Hence, switching between the two positioning methods based on the visibility of the canvas is necessary.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on showcasing array elements on a HTML page using Ionic 3 framework

I'm currently learning how to work with Ionic. One challenge I encountered is displaying products added to the cart on the cart page. While I was able to retrieve values using the forEach method, I faced difficulty in displaying them on the page. car ...

Assigning automatic roles based on the Discord.js v12 presence status of users

When someone is playing, I want to add a role using the presenceUpdate event However, every time I attempt this in discord.js v12, I encounter the following error: TypeError: Cannot read property 'activities' of undefined What mistake am I maki ...

Monitoring the inclusion of a new item within the database

I am utilizing a Firebase Realtime Database where users have the ability to perform the following actions: add an item to the database update an item in the database Currently, I have a function that monitors a specific location within the database. ...

Card Resizes when Search Button is Pressed

Recently, I've delved into Bootstrap after focusing primarily on backend development. As part of my front end work, I am implementing a feature where users can search for a place and a list of nearby venues will appear in a card layout using Bootstrap ...

I'm looking for a way to securely transfer data, such as an authentication token, from a web application to an electron-based thin client. My current approach involves utilizing custom URL protocols to

Have you ever wondered how applications like Teams and Zoom produce a pop-up when clicking on a meeting link in the browser, giving you the option to continue in the browser or open in the app? When choosing to open in the app, it launches on the desktop a ...

Error encountered while using AngularJS and Node.js with the 'phantom' node module. The application is throwing an injection error as AngularJS attempts to load a directive with a suffix

Upon loading an AngularJS page, everything proceeds smoothly with no console errors and the content displays as expected. However, encountering a different scenario where attempting to load the same page from another application using the Node module &apo ...

Double loading issue with jQuery AJAX

I'm currently working on a website and I've encountered an issue. Below is the jQuery code that I am using: $('input[type="text"][name="appLink"]').keyup(function() { var iTunesURL = $(this).val(); var iTunesAppID = $('i ...

Guide to building a JavaScript array and storing data from a separate array into the newly created array in JavaScript

Can you help me create a JavaScript array and save another array of data to be part of the newly created array in JavaScript? I attempted it using the code below. Code: var vvv=this.new_products.length-this.quote.lines.length; let mmm={}; if(v ...

The function $(...) does not recognize tablesorter

Currently, I am encountering issues with the tablesorter plugin as my system is unable to recognize the existing function. It is unclear whether there might be a conflict with other JavaScript files, especially since I am implementing changes within a Word ...

Is there a way to change the background color of a redirected page by clicking on a tag?

I have a specific goal in mind: when clicking on an anchor tag, it should redirect to page2.html and change the background color of a particular div on that page. (The anchor tag contains a URL and an ID in its href to direct to a specific section.) pa ...

Scrolling container embedded within a parent with absolute positioning

I have encountered a tricky situation with an absolute positioned div and its nested div having overflowing content. My goal is to enable vertical scrolling for the child div, however, my attempts so far have been unsuccessful. The challenge here is that I ...

Utilizing Angular Components Across Various Layers: A Guide

Consider the following component structure: app1 -- app1.component.html -- app1.component.ts parent1 parent2 app2 -- app2.component.html -- app2.component.ts Is it possible to efficiently reuse the app2 component within the ap ...

Aligning Text Vertically with an Image in ul/li List Items

Apologies if this question has already been asked, but I've checked several similar inquiries in an attempt to merge the solution without much luck. I currently have a bootstrap row with two col-md-6's. The first column contains an image, while t ...

When encountering issues with the select element, such as when it is combined with AJAX or Bootstrap,

When attempting to use a foreach loop within the <select><option> ... </option></select> element with jquery + ajax, I encountered an issue where no values were displayed. Although there were no errors when reviewing the console lo ...

Encountering TypeError while attempting to assign an axios response to a data variable within a Vue component

Encountering the error message TypeError: Cannot set property 'randomWord' of undefined specifically at the line: this.randomWord = response.data.word; Confirming that console.log(response.data.word) does display a string. Vue Component Structu ...

Newcomers to Visual Studio Code facing a problem with images not displaying

As a beginner in all aspects, I am currently facing an issue with displaying an image on Visual Studio Code. The problem arose when I tried to create a separate folder for the image, which resulted in a cascade of subfolders that only made things worse eac ...

Efficiently converting arrays to strings in JavaScript using mapping techniques

My goal is to retrieve data through AJAX without formatting it as JSON, so I took the initiative to encode it myself. The data I am working with consists of client records: where the pound sign (#) separates the client records, the pipe sign (|) separates ...

Adsense displays empty ad banners regardless of their predetermined size

Having trouble with Adsense banners? I have a page with three fixed-size banners (336 x 280) and sometimes they appear blank. It's random - one might work while the others don't, or none may work at all. The code is the same for each banner: < ...

Retrieve the check box from the array that it was stored in

I need to create a new function that will retrieve the checkbox array (USER_CARD_DECLARE_DATA_List) on the model. Here is the existing function: userobj.SaveDeclarationForm = function () { var USER_CARD_DECLARE_DATA_List = [] $(".option").map(fu ...

Even after hitting ctrl+z, Node.js continues to listen on the port

I've been exploring some features of Node on Ubuntu, and I encountered an issue where even after pressing ctrl+z in my console to stop the server (to update my code changes), Node would still be listening on port 3000. This meant that every time I nee ...