| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: Общие вопросы > Выделение области картинки с помощью мышки |
| Автор: Elfet 8.8.2005, 13:53 |
| Мне нужно выделить и отметить прямоугольную область на картинке. Не знаю как это сделать! |
| Автор: Elfet 8.8.2005, 21:15 |
| У меня не удаётся выделить цветом участок на картинке |
| Автор: sergejzr 8.8.2005, 21:19 |
| Значится так: Тебе надо разделить процесс. Отлавливаешь событие ondrag и когда отпустили мышь. По этим координатам вырешиваешь прямоугольник и рисуешь цветной квадрат поверх. Думаю, должно получится. не знаю правда, возможно ли сделать полупрозрачным квадрат.. |
| Автор: Sardar 8.8.2005, 21:34 |
| Рутинна это, довольно нудная Берём слой на релативной позиции, что бы не париться с координатами. Кладём в него картинку и четыре слоя на абсолютной позиции, в бекграунд которых ложим полупрозрачный(4 пиксельный, 2 прозрачных, 2 нет) .gif. Ловим клик(mousedown), ловим mousemove, считаем координаты(layer(X|Y), ofset(X|Y)). Изменяем размеры слоёв лжащих поверх картинки, так что бы затушевать часть картинки. Красиво будет если задать им бордер dotted 1px #555 у каждого со своей стороны + поставить маленькие квадратные синие слои по углам, как квадаратики. Ловим вхождение мыши на слоях, что бы "сдвигать" селекцию. Работа над такой фичей, что бы было как в любом сканере/редакторе потребует целого дня, уж больно рутины много. |
| Автор: Elfet 11.8.2005, 14:21 | ||
Ничего у меня не выходит |
| Автор: Elfet 12.8.2005, 12:08 |
| Как получить координаты мышки относительно начала картинки? |
| Автор: Sardar 12.8.2005, 16:31 |
| Под мозиллой это event.layer(X|Y), под ИЕ это event.offset(X|Y). |
| Автор: Гость_Elfet 13.8.2005, 09:23 |
| Sardar, ага, так работает, но только вот с выделением проблемы Но мне никак не выделить эту облость, у меня выделяется эта облость, но не относительно картинки, а относительно всей страницы: document.getElementById('xyselect').style.pixelLeft=this.event.offsetX; Что тогда делать? Вот это не помогает: document.getElementById('xyimg').style.pixelLeft - пишет, что 0 |
| Автор: Aliance 15.8.2005, 22:59 |
| Elfet Модератор: Пожалуйста, один топик - один вопрос. Пользуйся поиском, помню давно была подобная тема. Кажется, там и решение. Если не найдешь - попробую поискать... |
| Автор: Elfet 16.8.2005, 16:54 |
| Aliance, я посмотрел. Там такая тема есть, но там нет решения. А у меня по прежнему нечего не получается. Помогу плиз! |
| Автор: Elfet 18.8.2005, 17:08 |
| Вот, я понял, что нужно брать обе координаты, по картинке и глобальные. но все равно ничего не выходит Может кто видел уже такие скрипты? Где их можно поискать? |
| Автор: diam 18.8.2005, 20:41 |
| Такой реализации я не видел. Много реализаций, где просто водишь квадратик над картинкой, и где-нибудь в другом месте на сайте та часть картинки, на которой квадратик, видна у тебя. Но это не то. Я заинтересовался данной проблемой, попробую написать скрипт в свободное время. Elfet, если хочешь, можешь написать его быстрее меня Идея скрипта. Во-первых, просто так мы не можем выложить картинку и водить по ней мышкой, потому что firefox будет пытаться скопировать ссылку на данную картинку, опера потащит картинку за собой, может быть, ИЕ как-то накосячит (не знаю, не пользуюсь им). Во-вторых, нам нужен некий элемент прозрачности. Есть такое свойство в CSS: opacity, но оно не работает в Opera. Поэтому, если пользователи этих браузеров нам важны, придётся искать альтернативу. Я её вижу в полупрозрачном маленьком рисунке gif или png, который мы сможем размножить. Поэтому, предлагаю писать слоями в следующем порядке (относительно нашей конструкции): 1. На самом нижнем слое лежит картинка размерами X на Y. 2. На самом верхнем слое - div размерами X на Y со свойством background-color : transparent. Он будет выполнять роль стекла. 3. Посредине между ними div, размер которого будет меняться скриптом, а свойства фона будут задаваться background-image : url(transparent.gif) и background-repeat : repeat. Что тогда мы получаем? Когда кликаем мышкой по картинке (на самом деле, по верхнему диву Итак, это была идея. По моему, должно заработать. Повторюсь. Времени у меня очень мало, но задача мне очень интересна. Попробую написать. |
| Автор: Elfet 18.8.2005, 21:03 | ||
БЫло бы, здорово! |
| Автор: diam 23.10.2005, 00:56 | ||||
| Много времени прошло, но тему надо поднять, потому как лучше поздно, чем никогда Начнём. Сразу же выложу http://dmk.sky.ru/?j=1, что бы понимали, о чём речь. Логин: vingrad. Пароль: vingrad. Что мы имеем? 1. Картинка, область которой нужно выделить. 2. Полупрозрачный слой, который будет располагаться выше выделяемой картинки и будет показывать нам, какую область мы выделяем (или уже выделили). 3. Документ, в котором всё это располагается Для работы выделим координаты двух крайних точек картинки: 1. Координаты левой верхней точки картинки относительно начала документа (назовём эту точку pp0, а её координаты по осям абциссы и ординаты ppx0 и ppy0 соответственно). 2. Координаты правой нижней точки картинки относительно начала документа (назовём эту точку pp1, а её координаты по осям абциссы и ординаты ppx1 и ppy1 соответственно). Далее нужно разобраться с полупрозрачным слоем, который будет показывать нам выделенную нами область. Свойством CSS opacity нам не воспользоваться - опера не понимает. Красивыми полупрозрачными png'шками тоже, на этот раз тупит IE. А gif просто не умеет иметь полупрозрачный слой. Он умеет быть или прозрачным совсем (что нам не нужно), или совсем непрозрачным (что нам так же не подходит, так как не будем видеть то, что выделяем). Выход я нашёл следующий: я создал gif-файл размером 3x3 пикселя, фон у него сделал прозрачным и первый пиксель закрасил в серый цвет. Потом для нашего псевдополупрозрачного слоя применил такие правила CSS:
Таким образом, выделяемая область будет выглядеть как рамка с небольшими точками внутри, отдалённо будет напоминать полупрозрачность Теперь о том, что и как мы будем выделять. Мы будем отлавливать у всего документа события mousedown, mouseup, mousemove. Почему у всего документа? Что бы было удобнее для пользователя выделять (позже объясню почему). При нажатии на кнопку мыши будет запускаться функция, которая будет проверять, находимся ли мы внутри картинки. Если да, то будет фиксироваться флаг isAllocated, который скажет, что мы сейчас работаем с выделением, и координаты точки, где была опущена кнопка (назовём её ps0). Когда мы будем водить мышку по картинке с установленным флагом isAllocated, то будем получать ещё одну точку, которую назовём ps1, она то и будет завершать область выделения. Исходя из двух крайних точек (ps0 и ps1) мы будем знать, где нам расположить полупрозрачный слой и каким размером его сделать. После выделения мы будем отпускать кнопку мыши, при этом флаг isAllocated будет сброшен, а мы получим готовую выделенную область на картинке. Вот вроде бы и всё, смотрите код, в нём все более подробно. Можете его скопировать, вставить в файл, и просмотреть в браузере, но тогда вам нужно позаботиться о выделяемой картинке и о gif'ке с фоном.
Работает в следующих браузерах:
З.Ы. У меня просьба к модераторам: нельзя ли файл с примером поместить на vingrad, а то у меня машинка периодически перезагружается |
| Автор: diam 23.10.2005, 01:43 |
| Для данной реализации только что обнаружил баг, он касается всех тех, кто сидит в Windows и пользуется IE. Если Вы загрузите страничку и выделите какую-нибудь область на картинке, IE не даст Вам нажать ни одной кнопки в меню, пока окно не потеряет фокус, а потом снова его не поймает! Данный баг обнаружен на Windows XP SP2, запущенного под эмуляцией VMWare во FreeBSD (думаю, что баг останется, даже если загрузиться в винду без всяких эмуляторов). Правда, запустил IE через wine, такого бага обнаружено не было. |
| Автор: Elfet 23.10.2005, 09:46 |
| Ух ты! |
| Автор: Sardar 23.10.2005, 14:02 |
| diam обычно селекция обратная, т.е. активное поле (то что у тебя заливаеться) наоборот прозрачно, а всё вокруг заливаеться. Также в стилях нет однострочных коментариев //, есть блоковые /* */. Слой заливки(divid) лучше положить внутрь owndiv, последний положить на релативную позицию position: relative. Таким образом координаты divid будешь отсчитывать не от document.documentElement, a от owndiv, что горадо удобней, не нужно париться со скроллингом страницы. Не совсем корректно устанавливать обработчиков событий на document, ведь ты отлавливаешь события на конкретном слое. К тому же представь что у тебя таких картинок с выделениями много на странице. События лучше отлавливать на owndiv. В остальном очень хорошо получилось |
| Автор: diam 24.10.2005, 12:27 | ||
Хорошо, координаты divid получать относительно owndiv. Но как их соотнести с evt.clientX|evt.clientY? |
| Автор: Гость_12345 24.10.2005, 12:48 |
| diam: Но описанный баг в IE6 XP SP2 имеется. (Как в старой, так и в только что изменённой версии.) |
| Автор: Sardar 24.10.2005, 13:22 |
| А не замечал у event обьекта полей offset(X|Y) (для мозиллы layer(X|Y)), координаты от offsetParent элемента (для Оперы всегда от текущего элемента). Убираем все если связанные с разными браузерами, делаем стиль для owndiv position: relative (теперь он offsetParent для всего содержимого), ловим на нём мышь, опрашиваем выше назанные поля. Координаты от левого верхнего угла owndiv. |
| Автор: Guest 24.10.2005, 13:23 | ||
Не нашёл пока что описания функции .setCapture(false), вызывающей зависание, но "баг" исправляется добавлением такой функции (описание которой тоже не нашёл : ) ) в районе строки 100
|
| Автор: diam 24.10.2005, 13:42 |
| Точно, Sardar! Пропустил |
| Автор: Гость_12345 24.10.2005, 17:24 | ||
Тоже заинтересовавшись задачей, написал первый этап решения. С каждым протаскиванием рисуется область. Теперь бы придумать, чем их удалять : )).
|
| Автор: Sardar 24.10.2005, 17:46 |
| Гость_12345 набери в поиске -moz-opacity, выплывут как минимум две темы, где я приводил код с прозрачностью, там почти для всех браузеров. Убивать квадратики можешь отлавливая на них двойной клик, удобно. Xотя практическое применение такому скрипту трудно найти, ну квадратики... Кстати регистрируйся получишь свою историю, фавориты, почтовый ящик и многое другое. |
| Автор: Гость_12345 25.10.2005, 04:01 | ||
| Sardar : посмотрел. В конце концов, оказалось, что фильтр остался нужен только для IE, а ради Оперы пришлось применить полупрозрачный PNG, а он и FF захватил. А так - да, и CSS3-opacity в FF работает. Насчёт применения ты неправ - этот скрипт есть основа для решения исходной задачи. Ведь если я научился делать много "квадратиков", то ничего не стоит ограничиться одним и ограничить его рамками рисунка-подложки, как требовалось, с помощью логики. Другие применения - рисовать графические рамки комментариев к текстам форума в нужных местах (привязывая к тексту), организовать таким образом форум нового типа - "визуальный", оставлять более 1 комментария за раз. Писать комментарии к картинкам, как в этой задаче или как делают в сервисе flickr.com (фотообмен), выделяя прямоугольником комментируемое место. Кроссбраузерное решение:
|
| Автор: Sardar 25.10.2005, 14:49 |
| Не плохое решенение. О выделении картинки я уже говорил, "заливать" нужно не активные области, например управляя четыремя слоями с каждой стороны. Это наглядней, видно что выделенная область картинки действительно активная часть. |
| Автор: diam 26.10.2005, 17:12 |
| Немного переписал выделение области картинки. Сначала смотрим http://dmk.sky.ru/?j=3, потом http://dmk.sky.ru/?j=4 (выделенная область становится матовой). Вариант выделения, предложенный Sardar'ом, выложу чуть попозже |
| Автор: Sardar 27.10.2005, 02:44 |
| diam сервак пароли спрашивает... |
| Автор: diam 27.10.2005, 05:11 |
| login: vingrad password: vingrad |
| Автор: Sardar 27.10.2005, 11:02 |
| diam не плохо, остались два момента: как поместить на страницу несколько выделяемых картинок и явная передача в некоторую функцию координат и сорцов картинки. Последняя опросит сервер и обновит картинку. |
| Автор: diam 28.10.2005, 07:37 | ||||||
| Вариант с обратной селекцией, предложенный Sardar'ом, http://dmk.sky.ru/?j=5. Работает в Gecko, Opera. В IE проблема: у задающих обратную селекцию DIV'ов sd1..sd4 при установке свойства
фактическая высота DIV'а не становится равной 0, поэтому выглядит отстойно. Вопрос, наверное, в вёрстку. Ещё до вечера буду экспериментировать. Если у кого-нибудь будут мысли, почему так происходит, выкладывайте. Добавлено @ 07:40
А в чём проблема? Сейчас же события не привязываются к document, только к слою owndiv. Если нужно несколько картинок, то сделать несколько слоёв, в которые запихать эти картинки (один слой на одну картинку Добавлено @ 07:46
Зачем? Координаты левой верхней точки картинки pp0 (ppx0, ppy0) объявлены в глобальном контексте кода и доступны откуда угодно внутри документа. |
| Автор: Sardar 28.10.2005, 10:45 |
| Последний штрих: селекция должна появляться на картинки только в момент селектирования, т.е. нажатия кнопкой мыши Выставляй авторство/копирайты и в базу скриптов "Наши скрипты", хороший скрипт |
| Автор: diam 28.10.2005, 10:59 | ||||
Сейчас так и сделано. Единственный есть косяк, что если нажать на кнопку мыши на картинке, начать выделять, потом выйти за пределы слоя owndiv и отпустить клавишу мыши, тогда при возвращении на слой с картинкой при отпущенной клавише мыши выделение так же будет происходить. Что бы это исправить, можно отлавливать событие mouseup по всему document, но только если отпустим мышь за пределами окна браузера - опять получим двадцать пять. Или ты имеешь в виду, что бы до того, как мы стали выделять область картинки, последняя должна быть чистой? Тогда исправил.
Нужно ещё отладить, что бы в IE работало, хорошо откомментировать, а потом и в "Наши скрипты". |
| Автор: diam 28.10.2005, 13:02 |
| Ещё раз. Три варианта. http://dmk.sky.ru/?j=3 http://dmk.sky.ru/?j=4 http://dmk.sky.ru/?j=5 http://dmk.sky.ru/?j=3 Никаких графических выделений области картинки. Просто нажимаем на кнопку мыши на картинке, водим мышкой по картинке, потом отпускаем кнопку. Внизу смотрим координаты верхней левой точки выделяемой области, её ширину, высоту. http://dmk.sky.ru/?j=4 В дополнение к варианту N1 делает выделяемую область матовой. http://dmk.sky.ru/?j=5 Отличается от варианта N2 инверсным выделением. |
| Автор: Гость_12345 28.10.2005, 14:39 |
| diam: Чтобы в IE фактическая высота была равна 1, засунь в слой рисунок с высотой 1 без пробелов и переносов строк. |
| Автор: Guest 28.10.2005, 15:11 |
| Покрутил вариант 3 в IE, и виден баг при загрузке или рефреше страницы и первом выделении области - не отрисовывается нижний слой. С этим не стал разбираться - сподручнее автору. Побороть "отстойность" показа в IE можно ещё без рисунка, а с .sd {font-size:0px; ... или 1px} . Но там всё равно слой на слой немного налезает, и надо вводить особые условия, думаю. |
| Автор: Гость_12345 28.10.2005, 15:13 |
| Забыл спросить - какой особый смысл в записи имени файла в виде "./имя_файла", а не просто "имя_файла"? |
| Автор: Гость_12345 11.11.2005, 15:41 |
| Тут тоже такое делали, но под IE http://911.ru/to_rsdn/mouse_rect.html |
| Автор: chapchap 2.4.2006, 17:38 |
| Выложите пожалуйста скрипты, хотел посмотреть примеры, а ссылки не открываются. :( |
| Автор: diam 7.4.2006, 14:35 |
| К сожалению, моя машина, на которой были примеры, умерла от старости, скрипты остались в каком-то виде в бакапах. На следующей неделе выложу их, т.к. пока времени катастрофически не хватает. |
| Автор: chapchap 7.4.2006, 15:59 |
| Угу, заранее спасибо! Просто у самого ничего путного не получается (java к сожалению очень плохо знаю). Если javascript не получится, буду на чём-нибудь другом писать. |