Почему в мобильных браузерах наблюдаются полосы с вращением <canvas>?

Я выполняю ротацию двухмерного холста, который довольно хорошо работает на рабочем столе, но есть одна маленькая проблема в мобильном пространстве. Вот увеличенное изображение на скриншоте:

Изображение большого пальца поворачивается на 0.2рад в течение 500 мс. Я думаю, что весь соответствующий код встроен ниже. Как видите, у каждого из верхних углов изображения есть своего рода "след".

var duration = 500;
var start = 0;
var stop = 0.287554326;
var step = (stop - start) / 10;
var steps = (stop - start) / step;
var current = 0;
var delay = duration / steps;
var first = true;
if (navigator.userAgent.match(/iP(hone|[ao]d)|android/i)) step *= 1.5;
var rotate_int = setInterval(function() {
  if (current >= stop) {
    clearInterval(rotate_int);
    callback && callback();
    return;
  }
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  ctx.translate(cvs.width / 2, cvs.height / 2);
  ctx.rotate(step);
  current += step;
  ctx.translate(cvs.width / -2, cvs.height / -2);
  ctx.drawImage(i, 0, 0);
  if (first) {
    first = false;
    thumb.hide();
  }
}, delay);

Заметки:

  1. Код очень хорошо работает на рабочем столе (самые последние версии Firefox, Chrome, Safari, Opera и даже IE)
  2. Я протестировал следующие устройства и браузеры:
    1. iPhone 3GS: сафари, опера мини
    2. iPhone 4S: Safari
    3. iPad (1-го поколения): Safari
    4. Android Galaxy S (с пряниками): браузер по умолчанию, Firefox mobile
    5. Motorola Droid X (с пряниками): браузер по умолчанию, мобильный Firefox
  3. Я не нашел настольный браузер (поддерживающий <canvas>) который демонстрирует поведение
  4. Я не нашел мобильное устройство, которое не показывает поведение
  5. Выложенное изображение - увеличенный скриншот с iPad
  6. Если это имеет значение, <canvas> (во время вращения) анимируется (через jQuery), чтобы проходить через изображение позади него и останавливаться, что видно на скриншоте.
  7. Есть второй <canvas> на странице также. Он использует тот же файл thumbs-up .png и вращается с использованием того же кода, который был размещен выше, а также анимирован для перемещения по другому фоновому изображению (но в противоположном направлении, т.е. один "большой палец вверх" перемещается на северо-запад, а другой на юго-восток), и следы появляются там же, в том же месте относительно контекста холста.

Я вылил всю грязь на эту стену, о которой я могу думать, в надежде, что что-то может привести к диагнозу. Кто-нибудь еще видел что-то подобное раньше? Что я мог попробовать по-другому? Я пропустил где-то большой красный ярлык с предупреждением на сайте учебника по HTML5, который предупреждает о таком поведении?

== РЕДАКТИРОВАТЬ 1==

Согласно комментарию @GGG, я удалил снифф UA (который предназначен для уменьшения количества и частоты перерисовок холста, потому что мобильные браузеры все пускают пыль, если я использую те же настройки, что и для рабочего стола), но это только заставило трейлы становиться более выраженными (например толще). Затем я поэкспериментировал, вернув нюхатель UA обратно, но вместо того, чтобы уменьшить петли на 50%, я увеличил их на 500%. Снова, это заставило следы стать еще более явными. Однако кажется, что это утолщение является асимптотическим - другими словами, есть предел тому, насколько толстым я могу быть, чтобы настроить трейлы, настраивая параметры скорости анимации.

== РЕДАКТИРОВАТЬ 2==

В соответствии с другим комментарием @GGG, я решил отредактировать изображение, чтобы добавить прозрачные данные в попытке найти подходящий обходной путь. Я увидел, что изображение выдвинуто к верхнему и левому краям холста (это "холст Photoshop ", а не "HTML5"). <canvas>"). Когда я добавил равные отступы прозрачных данных к верхней и левой сторонам, проблема с полосами исчезла. Здесь был оригинальный PSD (pre me-добавление-extra-spacing):

Поэтому возникает вопрос: даже если изображение заполняет (непрозрачными пикселями) весь холст [Photoshop], почему мой контекст холста не является clearRect() ведешь себя? Разве это не должно стирать что-либо в пределах холста? Если так, то почему он оставляет эти несколько пикселей?

== РЕДАКТИРОВАТЬ 3==

После некоторых исследований выяснилось, что Cairo довольно часто используется несколькими основными движками рендеринга (по крайней мере, WebKit и Gecko). Может ли быть так, как @JonasWielicki впервые предположил, что библиотека Cairo - когда она оптимизирована для мобильного исполнения - возможно, немного переусердствовала?

1 ответ

Решение

В качестве обходного пути попробуйте добавить несколько прозрачных пикселей по краю изображения.

Я действительно понятия не имею, почему это происходит. Я думаю, что это как-то связано со странной обработкой альфа-каналов на мобильных устройствах, но это всего лишь предположение.

Я заметил, что мобильные браузеры, кажется, отбрасывают или "оценивают" альфа-канал при прокрутке (медленно прокручивайте вверх и вниз, даже шрифты выглядят более "хрустящими"). Интересно, они отрисовывают вещи в два этапа, оставляя альфа-канал для второго этапа и пропуская второй этап, если есть еще один "кадр" для рендеринга сразу после текущего "кадра", если это имеет смысл. Возможно, это каким-то образом вводит в заблуждение то, что он не рисует вещи в тех местах, где он есть.

Во всяком случае, это, вероятно, заслуживает сообщения об ошибке. Мне было бы интересно услышать реальное объяснение того, что происходит, если ничего больше.

Другие вопросы по тегам