Задержки onmousemove
Приветствую, столкнулся с проблемой, когда при onmousemove быстро водить мышкой по экрану событие начинает пропускать некоторые промежуточные координаты, а мне нужно учитывать абсолютно все, как этого можно добиться?
Пример с canvas: Попробуйте быстро быстро поводить по холсту и круги начнут отделяться <head> <script type="text/javascript"> var brush = {size: 20}; function getOffset(elem) { if (elem.getBoundingClientRect) { // "правильный" вариант return getOffsetRect(elem) } else { // пусть работает хоть как-то return getOffsetSum(elem) } } function getOffsetSum(elem) { var top=0, left=0 while(elem) { top = top + parseInt(elem.offsetTop) left = left + parseInt(elem.offsetLeft) elem = elem.offsetParent } return {top: top, left: left} } function getOffsetRect(elem) { // (1) var box = elem.getBoundingClientRect() // (2) var body = document.body var docElem = document.documentElement // (3) var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft // (4) var clientTop = docElem.clientTop || body.clientTop || 0 var clientLeft = docElem.clientLeft || body.clientLeft || 0 // (5) var top = box.top + scrollTop - clientTop var left = box.left + scrollLeft - clientLeft return { top: Math.round(top), left: Math.round(left) } } function radian(deegree) { return (Math.PI / 180) * deegree; } function draw(coordinats) { var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(coordinats.x, coordinats.y, brush.size, 0, radian(360), true); ctx.closePath(); ctx.fill(); } </script> </head> <body> <canvas id="canvas" width="600" height="300" style="border: 2px black solid; margin-left: 50px;"> Ваш браузер не поддерживает canvas. </canvas> <script type="text/javascript"> (function(){ var coordinats = {}, node = document.getElementById('canvas'), drag = false; node.onmousedown = function (e) { e = e || window.event; drag = true; coordinats.x = e.clientX + document.body.scrollLeft - parseInt(getOffsetSum(node).left); coordinats.y = e.clientY + document.body.scrollTop - parseInt(getOffsetSum(node).top); draw({x: coordinats.x, y: coordinats.y}); } node.onmousemove = function (e) { e = e || window.event; var change = { x: e.clientX + document.body.scrollLeft - parseInt(getOffsetSum(node).left), y: e.clientY + document.body.scrollTop - parseInt(getOffsetSum(node).top) } if(drag) draw({x: change.x, y: change.y}); } document.body.onmouseup = function () {drag = false;} })(); </script> </body> p.s. перепутал, тему не в том разделе создал |
делайте масив metki
добавляйте туда: а) текущий тиместамп,б)коорд. x в) коорд Y пре каждом onmousemove и проверяйте если разнеца между тикущем и предыдущим тиместамп слишком маленькак то отрисовывайт круги от коорд. указаных в предыдущей метке до коорд указаных в текущей метке document.onmousemove=function() { metki.push([new Date ,event.pageX,event.pageY ]); tek=metki[metki.length-1]; pred=metki[metki.length-2]; if(tek[0]-pred[0]<10) for(t=pred[1];t <tek[1];t=t+1) {код для отриовски круга} } |
не получится отрисовать круги от прошлой до текущей, т.к. пользователь может выбрать любую траектория рисования, а отрисовать можно будет только прямой линией
|
если пользователь нарисует кривую линию
то записаные в масиве точки будут ей соответсвовать ведь запись идет для каждого onmousemove |
Да вот именно что onmousemove пропускает некоторые координаты, они в массив не запишутся, если быстро вести onmousemove может пропустить 20-100 пикселей.
|
прямая линия влюбом случаи лутше чем совсем ничего
попробуйте в своем скрипте нарисовать параболу быстро проволя мышкой будут пропуски,но если оставшиися круги соединить прямой линией,то получиться чтото похожее на параболу для наглятности приведу скрин http://s011.radikal.ru/i315/1101/59/0f6611113552.jpg линиями обозначены места,где будут круги,отрисованые не пользователем,а скриптом если попробовать моим способом дорисовать синусоиду или чтото посложнее то получиться ломаная линия но покажите мне человека,который может нарисовать синусоиду быстро водя мышкой |
Нет, это совсем не подойдёт проще заставить событие учитывать все точки.
|
попробуй код укоротить по максу. и возможно придётся обратить внимание на быстродействие участков кода и по возможности заменить их на более быстрые.
других проблем по идее нет.Есть книга-по моему её название "Моя бабушка кодирует быстрее чем ты" где всё внимание уделяться проблеме быстродействия кода. не найдёшь её маякни -скину тебе её |
dmitriymar, если банальным alert проверять всё равно показывает пропуски.
|
в код твой я не вчитывался-но наверное здесь проблема постановки событий в очередь-точнее наверное в том что эта очередь ограничена и старые события не выполнившиеся затираются более свежими(это вопрос конечно философский как браузер "думает").попробуй просто убрать рисование и проверь алертом только изменение координат-по идее должно теряться меньше или совсем не теряться-если так будет-то только сокращением кода
Или попробуй ввести конструкцию-пока событие он маусдаун-просто запоминай координаты а по окончанию события уже отрисовывай по собранным координатам-по идее это должно сработать по полной-но наверное в твоём случае это не вариант-рисовать когда не видишь что рисуешь. |
Если проверять алертом и резко перевести курсор он показывает например 50, а после этого показывает 235 например, отсюда следует что он просто 'не замечает' координаты между ними.
|
Цитата:
сделай чуть не так проверку. при онмаусдаун собирай координаты а при окончании выведи их и посмотри есть ли в таком варианте пробелы |
dmitriymar, да есть, вот например по координатам x что вывело:
0 2 4 5 7 7 9 10 11 13 14 15 17 19 22 25 28 32 34 41 44 49 55 63 70 79 87 94 106 115 128 137 149 159 167 177 184 192 196 202 205 210 213 216 218 221 223 224 227 228 229 |
ну дак тогда по идее ничего не сделаешь-браузер не обманешь(чем быстрее комп тем меньше будет разрывов). соединять разрывы прямой только в этом случае да и всё.в + этого способа-только одно-никто не будет пытаться рисовать со скоростью реактивного самолёта-так что пройдёт полностью.
|
Цитата:
|
если бы можно было от маусмува отказаться-то прошло бы быстрее-пропусков бы небыло-рисовать пока онмаусдаун нажато в той точке где находиться курсор. встречал как то код какой опрашивает нажата ли кнопка миши.-тоесть пока нажата рисовать круг по координатам курсора(тоесть програмно опрашивается порт к какому мышь подкючена) запоминать последнюю координату если она не изменилась то не рисовать. но я его не пробовал и не знаю рабочий он или нет и работает ли вообще. причём встречал его в книге.
|
Vulkan, често, я пытался вникнуть в код, но написано извиняюсь как "курица лапой", для того чтобы придать установить как должна заканчиваться линия, не нужно создавать обьект круга, для этого достаточно определить свойство lineCap, со значением 'round' (ширину пера задать нужно с помошью свойства lineWidth), чтобы убрать разрывы между отрезками используйте свойство LineJoin и обратите внимание на метож stoke()
function draw(){ var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var canvas = canvas.getContext('2d'); } canvas.beginPath(); canvas.lineWidth=2; canvas.lineCap='round'; canvas.lineJoin='meter'; //это значение установлено по умолочанию canvas.strokeStyle='black'; //тут методы способ отрисовки /* canvas.moveTo(0,10); //координаты canvas.lineTo(10,10); //координаты canvas.bezierCurveTo() //координаты */ canvas.stroke(); canvas.closePath(); } http://cosmos.on.ufanet.ru/ https://developer.mozilla.org/En/Can...les_and_colors |
monolithed,
так он вроде тестил без функций рисования и у него разрывы в координатах огромное иногда и его не устраивает то что разрыв можно закрыть но только прямой без учёта реальной траектории -насколько я понял. Vulkan, тот вариант что отслеживать нажатие и отпускание-возможен вроде на джиквери-хотя если не успевает отследить координаты -то не поможет. |
Не хочется прямых - рисуй кривые.
Те. не 2 точки бери а 3 и более, если есть разрывы и просчитывая результат. Те одна функция рисует сразу, вторая чуть спустя дорисовывает в местах пропуска рассчитанные кривые. Будет(почти) незаметно. Вообще это древняя проблема. В 80% онлайн редакторов на её решение вообще забили. |
monolithed, у меня в оригинале всё гораздо лучше написано)) просто здесь на форуме чтобы привести пример быстренько написал, линиями пробовал другим способом - разрыва не было, а если вашим способом то разрыв остаётся, но самое главное мне нужны не линии а рисование круга в опр. координатах линиями конечно всё было-бы проще, использовать способ закругления round, но с ним у меня линии получались исковерканные.
|
Aetae, хорошая идея, используя кривые Безье дорисовывать, сейчас попробую.
|
а что, в десктопных приложениях координаты мышки больше чем на единицу не изменяются? Вне зависимости от чувствительности?
|
Спасибо всем, проблему решил, сейчас всё идеально, короче написал проверку на разрывы:
записываю последнюю координату, если расстояние между последней и текущей координатой больше чем размер кисти дорисовываю линии по типу кисти: lineWidth = brush.size * 2; lineCap = 'round'; lineJoin = 'round';сейчас всё идеально дорисовывает. Схематично вот проверка: fault = brush.size, difference = { x: Math.abs(oldcoordinats.x - coordinats.x), y: Math.abs(oldcoordinats.y - coordinats.y) } ... if (oldcoordinats.x && (difference.x > fault || difference.y > fault)) { //то начинаем процесс дорисовки } |
Часовой пояс GMT +3, время: 15:28. |