2013-05-01 2 views
1

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

Чтобы сделать это операцией O (1), я использую теневой холст, т. Е. Не отображаемый холст, который имеет точно такой же размер, где также нарисован каждый объект, нарисованный на обычном холсте, но с цветом который представляет собой ID.
Таким образом, простой ghostContex.getImageData() вместе с координатами щелчка мыши дает мне цвет в этом пикселе и, следовательно, ID объекта.

Все это работает нормально - за исключением случаев, когда я нажимаю на точную границу объекта.

Как нарисовано с сглаживанием на холсте призрак, я получаю неправильный цвет (так как этот цвет представляет собой смесь между правильным ID и ID объекта под ним, который был нарисован до ...). Это неправильный цвет, представляющий неправильный ID и, таким образом, я выбрать совершенно другой объект :(

Как я могу решить эту проблему

Примечание # 1: Я уже с помощью перевода (0,5, 0,5) трюк, чтобы предотвратить большинство сглаживания
Примечание № 2: Я пытался написать это приложение с помощью SVG раньше, но особенно этот выбор объекта был очень медленным, так как я предполагаю, что для обнаружения столкновений было слишком много объектов. Это основная причина почему я хочу использовать O (1) сейчас ... О, и таким образом я могу легко нарисовать гораздо большую линию на холсте призрак, чем линия нарисована на обычном холсте, чтобы сделать сбор намного проще.
N ote # 3: Релевантными браузерами являются Firefox, Chrome, Android 2.3+ родной и родной iOS

ответ

1

Причина, почему я не мог принять никакого ответа здесь довольно легко и довольно грустно: она не существует ... :(

антиалиасинга не может быть включен в стандартное не метод но в стандарте есть функция тестового теста (http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#hit-regions), которая будет делать именно то, что здесь необходимо. Даже в хорошем смысле, который скрывал бы неприятные детали для разработчика, но он не реализован ни в одном из браузеров прямо сейчас.
И реализация искала быть далеко до невозможного (см., Например, комментарий № 6 на https://code.google.com/p/chromium/issues/detail?id=328961). Но, по-видимому, это набрало силу за последний месяц ...

Так что можно сделать в среднем? Что я сделал?

В моем коде я мог бы реализовать для каждой формы метод isPointInShape(). Поэтому я использую трюк-трюк призрака, чтобы получить форму и проверить с помощью isPointInShape(), что я действительно выбрал правильную форму.Это помогает в пикселях с алиасированием не выбирать неправильную форму (просто подумайте о том, чтобы нажимать на границу формы №2, где у нас была прозрачность прозрачности на 50% - это скажет вам неверно выбор формы № 1 ...).

Если реализации унифицированного isPointInShape() довольно трудно для вашей фигуры, вы можете попробовать трюк, который я читал где-то еще (я не пробовал жестко, так что я не проверял ...):
Создайте дополнительный холст призрака размером 1x1 пиксель, который расположен точно в позиции мыши. Затем нарисуйте интересующую форму - когда A RGBA будет изменен, эта форма принадлежит к этому пикселю.

0

Я составил название контекста призрака! Вы используете мой старый учебник? :)

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

Удостоверьтесь, конечно, что вы переводите контекст призрака и нормальный контекст точно в одинаковых количествах. (и перевод их назад или сброс трансформации впоследствии).

+0

Время от времени я разочаровался в медленной скорости попадания SVG, которую я могу использовать, чтобы использовать скрытый холст (возможно, читал его где-то). Это было несколько месяцев назад. Когда я снова начал свои усилия и приступил к его внедрению в рамках проблем сглаживания, которые я исследовал в Интернете, - и там я наткнулся на вас, старое учебное пособие. Так я получил (по крайней мере?), Как назвать это оттуда - спасибо! – Chris

0

Я знаю, что это старый пост, но в последнее время у меня была аналогичная проблема. То, как я решил проблему «шов двух цветов», делал 10 × 10-пиксельную выборку вторичного холста вместо одного пикселя. Затем я стробил значения RGB и использовал их как ключи на карте, которая сопоставлена ​​с объектом, который представляет цвет. Таким образом, первоначально с использованием 1 пиксельной выборки я использовал карту сразу, чтобы определить связанный объект, но сглаживание создало половинные цвета, которых не было на карте. Метод 10x10 решает эту проблему, перебирая 100 возвращаемых значений RGB и создавая «счетную карту». Эта карта использует строгие цвета и сопоставляет их с подсчетом, но включает только допустимые цвета с первой карты в счете. Таким образом, вы получаете карту, в которой говорится, что вы подсчитали 65 красных пикселей и 23 синих пикселя (где остальные 12 пикселей были каким-то странным гибридом против алиасов). В том же цикле, где я подсчитывал цвета, я также поддерживал переменную для текущего максимального количества и текущего цвета, связанных с этим максимальным количеством (чтобы избежать повторения цикла через эту новую карту). Теперь в конце у вас есть цвет, который был подсчитан больше всего в этой выборке 10x10 и может использовать его для отображения обратно к связанному с ним объекту. Вы получите только неопределенный результат, если в образце 10x10, который вы можете разумно предположить, не было найдено допустимых цветов, означает, что был нажат «фон».

 Смежные вопросы

  • Нет связанных вопросов^_^