Fullscreen, full dpi WebGL canvas on mobile device
The easiest way is to use CSS to decide what size you want the canvas. Then look up what size the browser is displaying the canvas in CSS pixels using canvas.clientWidth
and canvas.clientHeight
. Now multiply that by window.devicePixelRatio
to get the number of device pixels those CSS pixels represent and set the canvas's content/drawingbuffer size to match.
Example:
Make a canvas
<canvas id="c"></canvas>
Set its size using CSS
Here I'm making the canvas be the size of the viewport (the window).
body {
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}Look up the size it's displayed and match its drawingbuffer size.
function resizeToMatchDisplaySize(canvas) {
var displayWidth = canvas.clientWidth * window.devicePixelRatio;
var displayHeight = canvas.clientHeight * window.devicePixelRatio;
if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
canvas.width = displayWidth;
canvas.height = displayHeight;
return true;
}
return false;
}Before rendering each frame adjust the size
function render() {
// resize before rendering in case of resizing or rotation
if (resizeToMatchDisplaySize(gl.canvas)) {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
}
// render scene
requestAnimationFrame(render);
}
requestAnimationFrame(render);
Here's an example drawing some lines
var gl = document.querySelector("#c").getContext("webgl", { alpha: false });var programInfo = twgl.createProgramInfo(gl, ['vs', 'fs']);var ids = [];for (var i = 0; i < 500; ++i) { ids.push(i);}var arrays = { vertexId: { size:1, data: ids},};var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var uniforms = { time: 0, numIds: ids.length, resolution: [0, 0],};
function resizeToMatchDisplaySize(canvas) { var displayWidth = canvas.clientWidth * window.devicePixelRatio; var displayHeight = canvas.clientHeight * window.devicePixelRatio; if (canvas.width !== displayWidth || canvas.height !== displayHeight) { canvas.width = displayWidth; canvas.height = displayHeight; return true; } return false;}
function render(time) { // resize before rendering in case of resizing or rotation if (resizeToMatchDisplaySize(gl.canvas)) { gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); } // render scene gl.useProgram(programInfo.program); uniforms.time = time * 0.001; uniforms.resolution[0] = gl.drawingBufferWidth; uniforms.resolution[1] = gl.drawingBufferHeight; twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo); twgl.setUniforms(programInfo, uniforms); twgl.drawBufferInfo(gl, gl.LINES, bufferInfo); requestAnimationFrame(render);}requestAnimationFrame(render);
body { margin: 0;}canvas { width: 100vw; height: 100vh; display: block;}
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"><canvas id="c"></canvas> <script id="vs" type="notjs">attribute float vertexId;
varying vec4 v_color;
uniform float numIds;uniform float time;uniform vec2 resolution;
#define PI radians(180.0)
vec3 hsv2rgb(vec3 c) { c = vec3(c.x, clamp(c.yz, 0.0, 1.0)); vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);}
void main() { vec4 offsets = vec4( sin(time), sin(time * .13) * PI * 2., sin(time * .43) * .5 + 1., cos(time * .17) * .5 + .5);
vec4 centers = vec4( sin(time * .163) * .5, cos(time * .267) * .5, sin(time * .367) * .5, cos(time * .497) * .5);
vec4 mult = vec4( 1., (sin(time * .1) * .5 + .5) * 3., 0., 0.);
vec2 position = vec2(vertexId / numIds, mod(vertexId, 2.)); vec2 offset = mix(offsets.xz, offsets.yw, position.y); float a = mult.x * position.x * PI * 2.0 + offset.x;//mix(u_offsets.x, u_offsets.y, a_position.y); float c = cos(a * mult.y); vec2 xy = vec2( cos(a), sin(a)) * c * offset.y + mix(centers.xy, centers.zw, position.y); vec2 aspect = vec2(resolution.y / resolution.x, 1); gl_Position = vec4(xy * aspect, 0, 1); float hue = position.x; float sat = 1.; float val = 1.; v_color = vec4(hsv2rgb(vec3(hue, sat, val)), 1);} </script> <script id="fs" type="notjs">precision mediump float;varying vec4 v_color;void main() { gl_FragColor = v_color;} </script> <script src="https://twgljs.org/dist/twgl-full.min.js"></script>
javascript - Fullscreen rectangle in Canvas (Android/iOS web app)
You can use pixel aspect ratio as a factor when calculating the canvas size.
var ratio = window.devicePixelRatio || 1;
var width = window.innerWidth * ratio;
var height = window.innerHeight * ratio;
canvas.width = width;
canvas.height = height;
CSS:
#canvasID {
position: fixed;
left: 0;
top: 0;
}
How can I have a full-screen canvas at full resolution in an iPhone 4?
You can try keeping the initial-scale=1, then set the canvas.width and canvas.height to be double the appropriate dimensions you've determined, and use CSS to set the CSS width and CSS height to be the correct size. This should give you a higher resolution canvas. The canvas.height and canvas.width properties set the actual number of pixels in the canvas, while the CSS height and width simply stretch (or in this case, compress) the canvas to a particular size.
Related Topics
Option.Style.Display = "None" Not Working in Safari
Size of Createelement("Svg") Is 0,0
JavaScript Show Element on Click
How to Style a Title? (And with CSS or Js)
Using JavaScript to Compare Two Input Numbers in HTML
Attribute Onclick="Function()" Not Functioning as Intended
Impossible to Hide Navigation Bars in Safari iOS 7 for Iphone/Ipod Touch
How to Host Material Icons Offline
Twitter's Typeahead.Js Suggestions Are Not Styled (Have No Border, Transparent Background, etc.)
Include CSS and JavaScript in My Django Template
Targeting Pure Elements in Next.Js with CSS Modules
Firefox Not Able to Enumerate Document.Stylesheets[].Cssrules[]
How to Get the Grid Coordinates of an Element Using JavaScript
Jquery: Animate Margins to Auto
Jquery Animate a -Webkit-Transform