4

I am having a strange issue. When I have hardware acceleration enabled, if I am drawing to a canvas element, whatever is drawn on the canvas, will be re-drawn to the top of the page.

If I turn off Hardware Acceleration, this issue does not occur.

I have only personally tested it on Android 4.1.1, but I've noticed this issue before on one of our users awhile ago that I couldn't replicate (They were on Android 3+ atleast)

I can't exactly grab a screenshot (not too sure how to do that on Android), but I will try break down the process.

with hardware accel enabled

  1. user fills out usual details.
  2. user scrolls to bottom of page, draws out a Signature on canvas element.
  3. If user forgot something at top of page and scrolls to top of page
  4. A visual bug occurs, the signature they drew appears at the top of the page

However with no hardware accel, step 4 does not occur. Is there something I'm supposed to do to the HTML5 Canvas?

I'm not sure what information I need to pass over here - it seems to occur on Samsung, HTC and Google Nexus Phones/Tablets so its a consistant bug.

I tried searching around, but I always end up getting Game Development threads or the likes.

I really would like to have Hardware Accel enabled, this is the only issue that occurs from it - the peformance gains are soooo incredible

DdD
  • 453
  • 4
  • 19
  • probably won't help, but with hardware acceleration, form inputs sometimes behave erratic, too = the typed in text appears at the top of the screen and the input box is scrolling out of view, too. The problem only occurs when the page is larger than the screen. My idea would be to fix the page height to the screen height, when starting to draw his signature. Maybe this helps. – frequent Nov 07 '12 at 23:43
  • unfortunately these pages are very dynamic (and exist within phonegap space), as its apart of a service – DdD Nov 08 '12 at 01:35
  • also to mention, i designed a section that uses a canvas on a non-scrollable page (ment for tablets only). The same issue occurs ( the canvas on that page is approx 40px away from the top of the page, it'll redraw on the same position) – DdD Nov 08 '12 at 01:38
  • I've got a lead atleast - Hardware Accel. changes canvas into a 'surface view'. Can I make it redraw in any way? – DdD Nov 08 '12 at 03:23
  • I can confirm, that bug still exists on my Galaxy Nexus, with (now) Android 4.3. It (naturally) also existed in Android 4.2.2, which this phone has before. – trejder Aug 08 '13 at 05:25

6 Answers6

8

The duplicated HTML5 canvas issue in Android has emeerged with version 4.1.1 and it's not fixed in the latest 4.2 yet.

The solution is that none of the parents HTML elements to the canvas will have overflow:hidden or overflow:scroll

guya
  • 5,067
  • 1
  • 35
  • 28
  • 2
    I can confirm, that bug still exists on my Galaxy Nexus, with (now) Android 4.3. It (naturally) also existed in Android 4.2.2, which this phone has before. It is a little bit strange, that this bug hasn't been fixed for so many Android versions. Can we confirm, that it was actually reported to Android's dev team? – trejder Aug 08 '13 at 05:23
  • 3
    Thanks - this solved it for me and I used this code to implement a quick fix: `$(".canvasElement").parents("*").css("overflow", "visible");` – SammyBlackBaron Aug 14 '13 at 15:04
  • If your using the fix `$(".canvasElement").parents("*").css("overflow", "visible");` with Jquery mobile, dont forget to call this in the pageshow event else it wont work. e.g. `$('[data-role="page"]').bind('pageshow', function() { $(".canvasElement").parents("*").css("overflow", "visible"); });` – leenix Oct 18 '13 at 16:44
  • @SammyBlackBaron these comments seems to be the only correct workaround (other than disabling hardware acceleration completely). If any parent of the canvas has overflow hidden, the GPU will blit parts of the canvas to the wrong places. Unfortunately, jQuery Mobile has a nasty habit of adding an extra 20 pixels or so to the right of a page element, even if nothing on the page is overflowing. Making overflow-x visible with JQM pages allows an overscroll to the right on the page, exposing a blank strip on the side. So pretty much any combination of GPU+Canvas+JQM is broken. – joshstrike Nov 14 '13 at 16:14
  • Does anyone know which versions this affects? Was it fixed in 4.4? I can't seem to find an official bug? – Deej Mar 19 '18 at 14:14
2

Ok so I've come up with the HACKIEST solution ever. After my onTouchEnd event has fired, I must do the following

1. Append changes to the canvas. It'll double-draw
2. Create a clone of the canvas
3. remove the canvas, re-add it
4. Copy the data from the clone over

then the bug disappears... ridicolous.

I had to get it to work, after removing hardware accel I noticed how clunky jQM feels

DdD
  • 453
  • 4
  • 19
  • 1
    @frequent I feel dirty for doing it...its soo hacky – DdD Nov 08 '12 at 06:15
  • ah. Android sometimes feels like IE6... you could also post your hack as an issue [here](https://github.com/scottjehl/Device-Bugs). – frequent Nov 08 '12 at 08:31
  • what do you mean by "copy the data from the clone"... what data do you mean ? – Greg Bala Dec 20 '12 at 18:54
  • exactly that, copy after you've cloned the canvas, created a new canvas - copy the old canvas data onto the new one – DdD Jan 08 '13 at 08:12
  • 2
    @DimitriAdamou People, who hasn't managed to fix such tiny bug between 4.1.1 and 4.3 (three general system updates, four?) should feel dirty! Not you, as you're providing hacky, but still workaround for their incompetence... – trejder Aug 08 '13 at 09:09
2

I had the same problem. Seems to be caused by jquery mobile css in my case.

Going into a little more detail to what guya added, go to the jquery.mobile.structure.css file and change this line:

.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; }

to

.ui-content { border-width: 0; overflow: visible; padding: 15px; }

Removing the overflow-x: hidden attribute fixes the problem.

Source: Github / thomasjbradley / signature-pad / Issues

Edit: Strangely enough, I noticed the problem didn't occur when the canvas width was 256px width or less.

David Welsh
  • 119
  • 4
  • 10
  • No, the very same problem exists, when you're not using jQuery Mobile. I run into this issue when using Twitter Bootstrap in my PhoneGap application (which uses "normal" jQuery) and in a simple HTML-based application, that uses non of the frameworks. – trejder Aug 08 '13 at 05:28
  • *"Strangely enough, I noticed the problem didn't occur when the canvas width was 256px width or less."* -- Because under 256px Chrome does not kick in hardware acceleration for the canvas. This further confirms that it's a hardware acceleration issue. – John Weisz Jan 30 '18 at 20:07
1

For anyone interested, Android 5 is working amazing, canvas works at much better speeds.

DdD
  • 453
  • 4
  • 19
0

I'm using Segment Display library and it is also affected by this problem. After long discussion with lib's author, he came out with a quick workaround. He told me to add these two lines:

context.fillStyle = '#fff';
context.fillRect(0, 0, display.width, display.height);

right after this line:

// clear canvas
context.clearRect(0, 0, display.width, display.height);

Solution was tested and works like a charm.

From a quick analysis of given code I assume that a transparent (clearRect) canvas is causing these problems and changing it to non-transparent one (fillRect) fixes the bug.

trejder
  • 17,148
  • 27
  • 124
  • 216
0

I have fixed the issue when creating the view:

if (Build.VERSION.SDK_INT >= 16) {
  try {
    Method method = root.getClass().getMethod("setLayerType", int.class, Paint.class);
    method.invoke(root, 0x01/* View.LAYER_TYPE_SOFTWARE */, null);
    Log.d(TAG, "hardware accelaration disabled");
  } catch ...
}
Maxxxx
  • 31
  • 4