Растянуть canvas элемент (имеющий размер) на весь экран
Всем привет! Есть ли возможность растянуть канвас элемент на весь экран? фишка в том, что он имеет размер и мне не хотелось бы его менять:
var canvas = document.getElementById('canvas'); var canvasWidth = 1000; var canvasHeight = 1000; var ctx = canvas.getContext('2d');
canvas
То есть, хотелось бы, чтобы вот этот размер сохранился ( 1000 на 100 пикселей), но сам он занимал как бы всю страничку, то есть был растянут.
Отслеживать
Karlos Margaritos
задан 30 янв 2021 в 17:48
Karlos Margaritos Karlos Margaritos
45 5 5 бронзовых знаков
А если на весь экран, но без потери соотношения?
12 мая 2023 в 2:27
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Указать ему размеры в CSS: 100vw — это ширина окна, 100vh — высота.
let ctx = document.getElementById("canvas").getContext("2d"); ctx.fillRect(900, 900, 100, 100); // Демо, как выглядит 100x100 квадрат в углу.
body < background-color: #169; >canvas
Если хочется оставить блок квадратным, но растянуть в размере меньшего из сторон окна, можно так:
(function() < let style = document.createElement("style"); let css = [ "#canvas < width: 100vw >", // Если ширина окна меньше высоты, "#canvas < height: 100vh >", // Если высота меньше ширины. ]; document.head.appendChild(style); update_css_size(); window.addEventListener("resize", update_css_size); function update_css_size() < let index = Number(innerWidth >innerHeight); // 0 или 1 style.textContent = css[index]; > >)(); /***/ let ctx = document.getElementById("canvas").getContext("2d"); ctx.fillRect(900, 900, 100, 100);
canvas
Отслеживать
ответ дан 30 янв 2021 в 18:14
OPTIMUS PRIME OPTIMUS PRIME
27.1k 3 3 золотых знака 23 23 серебряных знака 48 48 бронзовых знаков
Спасибо за ответ! Возникла такая проблемка, так как (обычно) ширина экранов больше чем высота, то, находящиеся внутри канваса элементы как бы тянутся по ширине. Можно этого избежать?
30 янв 2021 в 18:28
@KarlosMargaritos О_о одно условие противоречит другому) Оно или не квадратное, растянутое на весь экран, или квадратное, но не на весь экран. Можно например потянуть только на всю высоту, или на всю ширину [ через JS взяв меньшее из двух ], оставив квадратным.
30 янв 2021 в 19:08
@KarlosMargaritos Добавил второй вариант для квадрата. Может есть что попроще, не додумался. Также можно придумать другой вариант: растянуть на весь экран, но сместить начало координат так, чтобы 1000×1000 попадало в центр. Также, считая innerWidth / innerHeight через JS. Но если в «минусовых» координатах ничего не должно рисоваться, легче залить всё, что не попадает в квадрат — тем же цветом, что и у canvas, делая вид, что это его часть.
30 янв 2021 в 19:33
Спасибо большое за примеры, буду думать, может как то поиграть со свойством scale css или отобразить только часть канваса
Изменение размера Canvas в WebGL
Вот, что вам следует знать об изменениях размера canvas.
Каждый canvas имеет 2 размера. Первый — размер буфера отрисовки. Он отвечает за то, сколько пикселей помещается в canvas. Второй — размер отображаемого на HTML-странице элемента canvas. Этот размер задаётся через CSS.
Размер буфера отрисовки можно задать двумя способами. Первый — через HTML:
Второй способ — через JavaScript:
var canvas = document.querySelector("#c"); canvas.width = 400; canvas.height = 300;
Что касается размера отображаемого элемента, то при отсутствии стилей CSS, которые влияют на элемент, размер элемента будет равен размеру буфера отрисовки. Поэтому в 2 примерах выше размер буфера отрисовки будет равен 400×300, и размер отображаемого элемента будет также равен 400×300.
А вот пример, когда размер буфера отображения — 10×15, а размер HTML-элемента — 400×300 пикселей:
или можно задать так:
Если мы отобразим вращающуюся линию шириной один пиксель, мы получим что-то вроде:
Почему она такая размытая? Потому что браузер принимает canvas 10×15, а затем растягивает его до размера 400×300 пикселей, применяя для этого фильтрацию.
Так что же делать, если, к примеру, нам нужно, чтобы canvas заполнил всё окно? Для начала нам нужны CSS-стили, чтобы браузер растянул canvas на всё окно. Например:
/* убираем границу */ body < border: 0; background-color: white; >/* растягиваем canvas на всю область просмотра */ canvas < width: 100vw; height: 100vh; display: block; >
Теперь нам нужно, чтобы размер буфера отрисовки соответствовал размеру HTML-элемента, как бы браузер его ни растянул. Мы можем использовать свойствами clientWidth и clientHeight , которые есть у любого HTML-элемента и которые позволяют JavaScript узнавать размер отображаемого элемента.
function resize(canvas) < // получаем размер HTML-элемента canvas var displayWidth = canvas.clientWidth; var displayHeight = canvas.clientHeight; // проверяем, отличается ли размер canvas if (canvas.width != displayWidth || canvas.height != displayHeight) < // подгоняем размер буфера отрисовки под размер HTML-элемента canvas.width = displayWidth; canvas.height = displayHeight; >>
Большинство приложений WebGL используют анимацию, поэтому будем вызывать эту функцию непосредственно перед отрисовкой, чтобы при отрисовке размер canvas всегда соответствовал размеру HTML-элемента.
function drawScene() < resize(gl.canvas); .
И вот результат:
Но что не так? Почему линия не занимает всю область?
Причина в том, что при изменении размера canvas нам также необходимо вызвать gl.viewport для установки размера области просмотра. gl.viewport сообщает WebGL, как и в какую область внутри canvas преобразовывать координаты пространства отсечения (от -1 до +1) в пиксели. При первом создании контекста WebGL область просмотра будет соответствовать размеру canvas, но после этого вам необходимо следить за её размерами. Если вы меняете размер canvas, вам также необходимо сообщить WebGL новые параметры области просмотра.
Изменим код, чтобы учитывать такую ситуацию. Более того, раз уж ссылка на canvas доступна из контекста WebGL, будем передавать его параметром функции resize.
function drawScene() < resize(gl.canvas); + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); .
Теперь линия отображается как мы и ожидали.
Откройте пример в отдельном окне и меняйте размер окна. Линия всегда заполняет всё окно.
Слышу, вы спрашиваете, почему WebGL не устанавливает область просмотра для нас автоматически при изменении размера canvas? Просто потому, что он не знает, как и для чего вы используете область просмотра. Например, вы можете выполнять отрисовку во фреймбуфер или заниматься чем-то другим, что требует различного размера области просмотра. WebGL никак не может знать ваши намерения, поэтому он не подстраивает область просмотра.
В разных программах WebGL люди по-разному обрабатывают изменение размера canvas. Если вам интересно, я описал несколько причин, почему я предпочитаю описанный выше подход.
Что насчёт дисплеев Retina или HD-DPI?
При указании размера через CSS или Canvas используются пиксели, называемые также CSS-пиксели, которые могут отличаться от действительных пикселей. Большинство современных смартфонов оснащены дисплеями высокой чёткости (HD-DPI) или, как их называет Apple, "дисплеями Retina". Для текста и большей части стилей CSS браузер способен автоматически отображать графику HD-DPI, но в случае с WebGL вы сами отвечаете за графику, и вам необходимо самим позаботиться об отображении графики с более высоким разрешением, если вы хотите получить качество HD-DPI.
Для этого мы можем посмотреть на значение window.devicePixelRatio . Это значение укажет, как много действительных пикселей помещаются в одном пикселе CSS. Мы можем внести изменения в функцию изменения размера для ориентации на действительный пиксель.
function resize(gl) < var realToCSSPixels = window.devicePixelRatio; // Берём заданный браузером размер canvas в CSS-пикселях и вычисляем нужный // нам размер, чтобы буфер отрисовки совпадал с ним в действительных пикселях var displayWidth = Math.floor(gl.canvas.clientWidth * realToCSSPixels); var displayHeight = Math.floor(gl.canvas.clientHeight * realToCSSPixels); // проверяем, отличается ли размер canvas if (gl.canvas.width !== displayWidth || gl.canvas.height !== displayHeight) < // подгоняем размер буфера отрисовки под размер HTML-элемента gl.canvas.width = displayWidth; gl.canvas.height = displayHeight; >>
Если вы откроете эту страницу на дисплее HD-DPI - например, на вашем смартфоне - вы заметите, что линия на примере ниже тоньше, чем в примерах выше, в которых не учитывались дисплеи HD-DPI.
Настраивать ли программу под использование дисплеев HD-DPI, зависит только от вас. На iPhone4 и iPhone5 window.devicePixelRatio равен 2 , что означает, что вы будете отображать в 4 раза больше пикселей. Думаю, что на iPhone6Plus это значение равно 3 , то есть вы будете отображать в 9 раз больше пикселей. Это может замедлить вашу програму. Вообще, для игр типично отображать меньше пикселей, чтобы видеокарта сама растянула их. Всё зависит от ваших целей. Например, если вы готовите график для печати, то, возможно, вам понадобится поддержка HD-DPI. Для игр, возможно, не понадобится такой поддержки, или вы сделаете настройку, чтобы можно было включить поддержку HD-DPI или выключить, если устройство недостаточно мощное для отрисовки такого количества пикселей.
- Основы
- Основы WebGL
- Как работает WebGL
- Шейдеры и GLSL в WebGL
- WebGL State Diagram
- Обработка изображений в WebGL
- Продолжаем обработку изображений в WebGL
- 2D-перенос в WebGL
- 2D-поворот в WebGL
- 2D-масштабирование в WebGL
- 2D-матрицы в WebGL
- WebGL 3D - Ортогональ
- WebGL 3D - Перспектива
- WebGL 3D - Камеры
- WebGL 3D - Направленное освещение
- WebGL 3D - Точечное освещение
- WebGL 3D - Прожектор
- WebGL - Меньше кода, больше веселья
- WebGL - Отрисовка нескольких объектов
- WebGL - Графы сцены
- WebGL 3D - Создание модели
- Loading .obj files
- Loading .obj w .mtl files
- WebGL 3D - Текстуры
- WebGL - Данные для текстур
- WebGL - Использование 2 и более текстур
- WebGL - Кросс-доменные изображения
- WebGL 3D - Перспективная коррекция текстур
- Planar and Perspective Projection Mapping
- WebGL - Рендеринг в текстуру
- Shadows
- 2D
- WebGL 2D - DrawImage
- WebGL 2D - Стек матриц
- Sprites
- Cubemaps
- Environment maps
- Skyboxes
- Skinning
- Fog
- Picking (clicking on stuff)
- WebGL текст - HTML
- WebGL текст - Canvas 2D
- WebGL текст - Используем текстуру
- WebGL текст - Используем глиф-текстуру
- Ramp Textures (Toon Shading)
- GPGPU
- Smallest Programs
- Drawing Without Data
- Shadertoy
- Pulling Vertices
- Indexed Vertices (gl.drawElements)
- Instanced Drawing
- WebGL Установка и настройка
- Шаблон WebGL
- Изменение размера Canvas в WebGL
- WebGL - Анимация
- Points, Lines, and Triangles
- Multiple Views, Multiple Canvases
- Visualizing the Camera
- WebGL и прозрачность
- WebGL - 2D и 3D библиотеки
- WebGL - Антипаттерны
- WebGL Matrices vs Math Matrices
- Precision Issues
- Taking a screenshot
- Prevent the Canvas Being Cleared
- Get Keyboard Input From a Canvas
- Use WebGL as Background in HTML
- Cross Platform Issues
- Questions and Answers
- Attributes
- Texture Units
- Framebuffers
- readPixels
- References
- Документация по вспомогательным функциям
- TWGL, лёгкая библиотека-помощник для WebGL
- github
Как сделать canvas во всю ширину и высота viewport?
Как сделать чтобы область canvas была во всю ширину и высоту viewport?
canvas.width = document.documentElement.clientWidth; canvas.height = document.documentElement.clientHeight;Но при уменьшении экрана появляются полосы прокрутки. Как сделать чтобы полос прокрутки не было? Чтобы канвас можно сказать адаптивным был..
- Вопрос задан более трёх лет назад
- 7324 просмотра
помогите пожалуйста по js Как растянуть canvas по высоте на весь экран, а ширина должна масштабироваться по высоте
Можно это сделать через CSS. Прямо как в первом ответе. Только сделать вот так
canvas#yourIDheight: 100%;
width: 100%;
position: fixed;
>
где yourID - айдишник твоего канваса Зачем тут JavaScript?ЯрославИскусственный Интеллект (107785) 5 лет назад
Затем что у Canvas помимо внешних (CSS) размеров есть еще и внутренние. Если тупо растягивать стилями, то пропорции изображения будут нарушаться.
И, если внимательно прочесть вопрос - станет понятно, что задача не предусматривает растягивание на всю ШИРИНУ.Макс ХХХ Просветленный (37664) Если изменить "внутренние размеры", то канвас будет очищен до девственного состояния. Тогда надо куда-то сохранять данные с него и потом отрисовывать их обратно. Если же менять размер через CSS ничего такого не произойдет.
Остальные ответы
тебе программно надо или что? Вопрос формулируй. С помощью CSS -
canvas#yourIDwidth: 100%;
>
где yourID - айдишник твоего канвасаcnvs.width = исходнаяШирина;
cnvs.height = исходнаяВысота;
const ratio = cnvs.width / cnvs.height,
updateCnvsW = () => cnvs.style.width = cnvs.offsetHeight * ratio + 'px';
cnvs.style.height = '100%';
updateCnvsW();
window.addEventListener('resize', updateCnvsW);
Либо, можно установить ширину в vh через стили, и скриптом обновлять внутренние размеры. Но тогда все операции отрисовки должны использовать относительные координаты, или пропорциональное масшабирование через scale().ЯрославИскусственный Интеллект (107785) 5 лет назад
Естессно, для того чтобы растягивание на высоту вьюпорта работало, контейнер канвы должен быть такой высоты (задается стилями).