Отзывчивый холст, сохраняющий заданное соотношение сторон

Я разрабатываю приложение для рисования и столкнулся с проблемой, которую пытался решить, но пока не нашел надежного решения:

Эскизы имеют исходное разрешение 1280 x 720, и я хотел бы изменить размер холста при открытии страницы до максимально возможного размера (учитывая размеры экрана за вычетом панели инструментов, которую я разместил в верхней части страницы). сохраняя соотношение сторон 1280 x 720. Холст должен располагаться по центру экрана, а все остальное покроют черные полосы: когда отношение размеров окна браузера меньше, чем отношение исходного эскиза к высоте, будут горизонтальные черные полосы (рис. 1), а когда он больше, вертикальные черные полосы (рис. 2).

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

Некоторые изображения того, что я пытаюсь сделать:

Я трачу много времени на эту мелочь и схожу с ума, потому что каждое решение, которое я нашел, слишком хакерское или ненадежное. Любая помощь будет очень признательна.

Я использую Angular + Ionic 4.


person jjssman    schedule 07.05.2020    source источник


Ответы (1)


Если я правильно вас понимаю, вы хотите динамически изменять размер холста в зависимости от размера окна. Единственное условие заключается в том, что он должен поддерживать соотношение сторон 1280 x 720 (1:0,5625).

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

HTML

<body>
  <canvas id="canvas"></canvas>
</body>

CSS

body {
  background-color: black;
}

JavaScript:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

startListening();

function startListening() {
  // resize the canvas every time the window is adjusted
  window.addEventListener('resize', resizeCanvas, false);
  // manually call the resizeCanvas() function as the window loads with it's starting dimensions (before a resize has happened)
  resizeCanvas();
}

function resizeCanvas() {
  // if the canvas height isn't maxed out, match it to the width of the page at the correct aspect ration (1:0.5625)
  if(canvas.height < window.innerHeight){
    canvas.width = window.innerWidth;
    canvas.height = canvas.width * 0.5625;
  }
  
  // if the canvas height is maxed out, stop widening the canvas and lock the canvas height at 0.5625 of that locked height
  if(canvas.height >= window.innerHeight){
    canvas.height = canvas.width * 0.5625;
  }
  
  // lastly, if we are shrinking the width back down, readjust both the width and height to match
  if(canvas.width > window.innerWidth){
    canvas.width = window.innerWidth;
    canvas.height = canvas.width * 0.5625;
  }
  // redraw the canvas with our newly calculated dimensions
  redraw();
}

function redraw() {
  ctx.fillStyle = "#FF0000";
  // Draw the canvas in the center of the screen at the height and width calculated above in the resizeCanvas() function
  ctx.fillRect((window.innerWidth - canvas.width) / 2, (window.innerHeight - canvas.height) / 2, canvas.width, canvas.height);
}
person Rick S    schedule 08.05.2020