Учет различий в размере холста при рисовании на изображении с сохраненными координатами - PullRequest
1 голос
/ 15 марта 2019

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

В основном я хочу отобразить изображение на холсте. Пользователь отметит две точки на области изображения и записи приложения, где были размещены эти маркеры. Идея состоит в том, что пользователь будет использовать приложение каждый нечетный день, сможет видеть, где было нарисовано Х количество предыдущих точек, и сможет добавить два новых к области, упомянутой в местах, еще не отмеченных предыдущими маркерами. Холст в настоящее время настроен для высоты = window.innerHeight и ширины = window.innerWidth / 2.

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

Ответы [ 2 ]

1 голос
/ 15 марта 2019

Используйте проценты !Пример:

Итак, скажем, на устройстве 1 размер холста равен 150x200,
Пользователь помещает маркер на пиксель 25x30.Вы можете сделать некоторую математику, чтобы получить процент.
И затем вы СОХРАНИТЕ этот процент, а не местоположение,
Пример:

let userX = 25; //where the user placed a marker
let canvasWidth = 150;
//Use a calculator to verify :D
let percent = 100 / (canvasWidth / userX); //16.666%

И теперь, когда у вас есть percent, вы можете установить местоположение маркера на основе этого процента.
Пример:

let markerX = (canvasWidth * percent) / 100; //24.999
canvasWidth = 400; //Lets change the canvas size!
markerX = (canvasWidth * percent) / 100; //66.664;

И вуаля: D просто возьмите размер холста иВы можете определить местоположение маркера каждый раз.

0 голосов
/ 15 марта 2019

Виртуальный холст

Вы должны определить виртуальный холст.Это идеальный холст с заданным размером, все координаты относительно этого холста.Центр этого виртуального холста - координата 0,0

. Когда координата введена, она преобразуется в виртуальные координаты и сохраняется.При визуализации они преобразуются в координаты экрана устройства.

Различные устройства имеют различные соотношения сторон, даже одно устройство может быть наклонено, что изменяет аспект.Это означает, что виртуальный холст не совсем подходит для всех устройств.Лучшее, что вы можете сделать, это убедиться, что весь виртуальный холст видим, не растягивая его в направлениях x или y.это называется масштабирование по размеру.

Масштабирование по размеру

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

Чтобы создать матрицу масштабирования устройства

const vWidth = 1920;  // virtual canvas size
const vHeight = 1080;

function scaleToFitMatrix(dWidth, dHeight) {
    const scale = Math.min(dWidth / vWidth, dHeight / vHeight);
    return [scale, 0, 0, scale, dWidth / 2, dHeight / 2];
}

const scaleMatrix = scaleToFitMatrix(innerWidth, innerHeight);

Положение шкалы, а не пиксели

Точка определяется как позиция на виртуальномхолст.Однако преобразование также будет масштабировать ширину линий и размеры объектов, которые вы не хотели бы использовать на устройствах с очень низким или высоким разрешением.

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

const point = {x : 0, y : 0}; // center of virtual canvas
const point1 = {x : -vWidth / 2, y : -vHeight / 2}; // top left of virtual canvas
const point2 = {x : vWidth / 2, y : vHeight / 2}; // bottom right of virtual canvas

function drawPoint(ctx, matrix, vX, vY, pW, pH) { // vX, vY virtual coordinate
     const invScale = 1 / matrix[0]; // to scale to pixel size
     ctx.setTransform(...matrix); 
     ctx.lineWidth = 1; // width of line
     ctx.beginPath();
     ctx.rect(vX - pW * 0.5 * invScale, vY - pH * 0.5 * invScale, pW * invScale, pH * invScale);
     ctx.setTransform(1,0,0,1,0,0); // reset transform for line width to be correct
     ctx.fill();
     ctx.stroke();
}
const ctx = canvas.getContext("2d");
drawPoint(ctx, scaleMatrix, point.x, point.y, 4, 4);

Преобразование с помощью процессора

Преобразование точки из координат устройства в виртуальные координатывам нужно применить обратную матрицу к этой точке.Например, вы получаете координаты pageX, pageY от мыши, вы конвертируете, используя масштабную матрицу следующим образом

function pointToVirtual(matrix, point) {
    point.x = (point.x - matrix[4]) / matrix[0];
    point.y = (point.y - matrix[5]) / matrix[3];
    return point;
}

Для преобразования из виртуального в устройство

function virtualToPoint(matrix, point) {
    point.x = (point.x * matrix[0]) + matrix[4];
    point.y = (point.y * matrix[3]) + matrix[5];
    return point;
}

Проверка границ

Может быть область выше / ниже или слева / справа от холста, которая находится вне координат виртуального холста.Чтобы проверить, находятся ли внутри виртуального холста, вызовите следующие

function isInVritual(vPoint) {
     return ! (vPoint.x < -vWidth / 2 || 
         vPoint.y < -vHeight / 2 ||
         vPoint.x >= vWidth / 2 ||
         vPoint.y >= vHeight / 2);
}
const dPoint = {x: page.x, y: page.y};  // coordinate in device coords
if (isInVirtual(pointToVirtual(scaleMatrix,dPoint))) {
     console.log("Point inside");
} else {
     console.log("Point out of bounds.");
}

Дополнительные точки

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