Виртуальный холст
Вы должны определить виртуальный холст.Это идеальный холст с заданным размером, все координаты относительно этого холста.Центр этого виртуального холста - координата 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.");
}
Дополнительные точки
- Выше предполагается, что холст выровнен по экрану.
- Некоторые устройствабудет увеличено (увеличено).Для достижения наилучших результатов вам нужно будет проверить масштаб в пикселях устройства.
- Лучше всего установить размер виртуального холста равным максимальному разрешению экрана, которое вы ожидаете.
- Всегда работать в виртуальных координатах, преобразовывать в координаты устройства только тогда, когда вам нужно выполнить рендеринг.