2016-11-30 2 views
1

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

<!DOCTYPE HTML> 
<html> 
    <head> 
    <style> 
     body { 
     margin: 0px; 
     padding: 0px; 
     } 

     #myCanvas { 
     background-color: cornflowerblue; 
     } 
    </style> 
    </head> 
    <body> 
    <canvas id="myCanvas" width="578" height="200"></canvas> 
    <script> 
     function writeMessage(canvas, message) { 
     var context = canvas.getContext('2d'); 
     context.clearRect(0, 0, canvas.width, canvas.height); 
     context.font = '18pt Calibri'; 
     context.fillStyle = 'black'; 
     context.fillText(message, 10, 25); 
     } 
     function getMousePos(canvas, evt) { 
     var rect = canvas.getBoundingClientRect(); 
     return { 
      x: evt.clientX - rect.left, 
      y: evt.clientY - rect.top 
     }; 
     } 
     var canvas = document.getElementById('myCanvas'); 
     var context = canvas.getContext('2d'); 

     canvas.addEventListener('mousemove', function(evt) { 
     var mousePos = getMousePos(canvas, evt); 
     var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y; 
     writeMessage(canvas, message); 
     }, false); 
    </script> 
    </body> 
</html> 

Когда страница загружается, вы видите полотно в виде синий прямоугольник в верхнем левом углу страницы. Переместите указатель мыши над ним, и текст в холсте изменится, чтобы отобразить положение мыши в виде двух целых чисел, по одному для X и Y.

Затем я изменил стиль холста, добавив верхнее и левое поле и оставил остальное страницы без изменений.

#myCanvas { 
    background-color: cornflowerblue; 
    margin-left: 30px; 
    margin-top: 30px; 
} 

Когда я оказал страницу сейчас, синий прямоугольник холста был смещен от верхней и левой странице, как я ожидал. Но пропуская мышь над холстом, теперь были координаты мыши X и Y, которые отображались в холсте, поднимаясь как плавающие со многими десятичными знаками. Прослеживая через код немного, кажется, что getBoundingClientRect() возвращает прямоугольник, где значения top и left являются float.

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

Как я могу использовать getBoundingClientRect() неправильно или ожидается, что он должен возвращать значения float?

И есть ли четкий способ получить точные координаты X и Y мыши над холстом при прослушивании различных событий мыши?

ответ

3

tldr; вы сделали масштабирование/unzoom в своем браузере.

Проблема

margin-left: 30px; 

В этом jsfiddle Thats имитирует вашу проблему она не работает, как вы говорили, что на моем компьютере, когда навигатор увеличения на 100% (нормальный). Но если вы увеличите масштаб в своем браузере, вы заметите такое поведение.

margin-left: 11%; 

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

Ответ

Дело в том, как он появляется на экране позиции мыши вычисляется: оно может только вся позиция координат, так как он основан пикселей.

Однако getBoundingClientRect возвращает то, что браузер вычисляет как «Bounding Client Rect of the element» после применения полей, масштабирования и других модификаторов, но прежде, чем сообщить GPU о его рендеринге. Короче говоря, он возвращает реальную позицию элемента, которая позже аппроксимируется графическим процессором, который будет отображаться в матрице пикселей. Если вы используете пиксельные поля/размеры/paddings/etc, позиции элементов остаются целыми, но если вы увеличиваете или используете значения em /% positioning, то это может привести к появлению плавающих позиций.

Решения

  1. круглые границы
  2. предположить, что это действительно плавающее положение, и это только GPU, что необходимо округлить его для того, чтобы подогнать его на экране

Редактировать : Забытые решения

+0

Наблюдал этот вопрос - хороший ответ. – VSO

+0

Я пытаюсь переварить ваш ответ. Но из ваших решений и моего наблюдения, что getBoundingClientRect() не всегда возвращает «почти закругленный» float, у меня есть этот вопрос: если я пытаюсь запрограммировать игру с использованием элемента canvas, могу ли я предположить, что есть нет способа сделать точное обнаружение столкновений с участием мыши и то, что нарисовано на холсте? – vfs23

+0

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

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