Last active
September 24, 2022 04:40
-
-
Save greggman/c2e4cdca322620bdaf4e46764d6ce761 to your computer and use it in GitHub Desktop.
Checking ResizeObserver devicePixelContentBoxSize
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 0; | |
background-color: white; | |
} | |
.outer { | |
margin: 0 auto; | |
width: 80%; | |
} | |
#compare, | |
canvas { | |
width: 100%; | |
height: 100px; | |
display: block; | |
} | |
#compare { | |
background-color: red; | |
} | |
.bad { | |
color: red; | |
font-weight: bold; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="outer"> | |
<div>using ResizeObserver (<span id="dpr-support"></span>)</div> | |
<canvas id="use-ResizeObserver"></canvas> | |
<pre id="c1"></pre> | |
<div>just a div</div> | |
<div id="compare"></div> | |
<pre id="c2"></pre> | |
<button>save canvas to png</canvas> | |
</div> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Canvas Resize Method Comparison | |
// from https://webglfundamentals.org/webgl/webgl-resize-the-canvas-comparison.html | |
'use strict'; | |
const log1Elem = document.querySelector('#c1'); | |
const log2Elem = document.querySelector('#c2'); | |
function setupCanvas(canvas, resizeFn) { | |
const gl = canvas.getContext('webgl2', {antialias: false, preserveDrawingBuffer: true}); | |
const createShader = (gl, type, src) => { | |
const sh = gl.createShader(type); | |
gl.shaderSource(sh, src); | |
gl.compileShader(sh); | |
console.log(gl.getShaderInfoLog(sh)); | |
return sh; | |
}; | |
const prg = gl.createProgram(); | |
gl.attachShader(prg, createShader(gl, gl.VERTEX_SHADER, `#version 300 es | |
void main() { | |
ivec2 unitQuad = ivec2( | |
gl_VertexID / 6 + gl_VertexID % 2, | |
(gl_VertexID / 2 + gl_VertexID / 3) % 2); | |
gl_Position = vec4(vec2(unitQuad) * 2.0 - 1.0, 0, 1); | |
} | |
`)); | |
gl.attachShader(prg, createShader(gl, gl.FRAGMENT_SHADER, `#version 300 es | |
precision highp float; | |
uniform vec2 resolution; | |
out vec4 fragColor; | |
void main() { | |
vec2 odd = floor(mod(gl_FragCoord.xy, vec2(2))); | |
vec4 hStripe = mix(vec4(1,0,0,1), vec4(0, 1, 1, 1), odd.y); | |
vec4 vStripe = mix(vec4(1,0,0,1), vec4(0, 1, 1, 1), odd.x); | |
fragColor = mix(hStripe, vStripe, step(resolution.x / 2.0, gl_FragCoord.x)); | |
} | |
`)); | |
gl.linkProgram(prg); | |
gl.useProgram(prg); | |
const resolutionLoc = gl.getUniformLocation(prg, 'resolution'); | |
const drawFn = (displayWidth, displayHeight) => { | |
canvas.width = displayWidth; | |
canvas.height = displayHeight; | |
//console.log(displayWidth, displayHeight, gl.drawingBufferWidth, gl.drawingBufferHeight); | |
gl.viewport(0, 0, displayWidth, displayHeight); | |
gl.uniform2f(resolutionLoc, displayWidth, displayHeight); | |
gl.drawArrays(gl.TRIANGLES, 0, 6); | |
}; | |
resizeFn(canvas, drawFn); | |
{ | |
const saveBlob = (function() { | |
const a = document.createElement('a'); | |
document.body.appendChild(a); | |
a.style.display = 'none'; | |
return function saveData(blob, fileName) { | |
const url = window.URL.createObjectURL(blob); | |
a.href = url; | |
a.download = fileName; | |
a.click(); | |
}; | |
}()); | |
const elem = document.querySelector('button'); | |
elem.addEventListener('click', () => { | |
const canvas = gl.canvas; | |
canvas.toBlob((blob) => { | |
saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`); | |
}); | |
}); | |
} | |
} | |
setupCanvas(document.querySelector('#use-ResizeObserver'), (canvas, drawFn) => { | |
const canvasToDisplaySizeMap = new Map([[canvas, [300, 150]]]); | |
const resizeAndDraw = () => { | |
const [displayWidth, displayHeight] = canvasToDisplaySizeMap.get(canvas); | |
drawFn(displayWidth, displayHeight); | |
}; | |
function onResize(entries) { | |
for (const entry of entries) { | |
const displayWidth = entry.devicePixelContentBoxSize[0].inlineSize; | |
const displayHeight = entry.devicePixelContentBoxSize[0].blockSize; | |
log1Elem.textContent = `canvas devicePixelContentBoxSize: ${displayWidth}, ${displayHeight}`; | |
canvasToDisplaySizeMap.set(entry.target, [displayWidth, displayHeight]); | |
resizeAndDraw(); | |
} | |
} | |
resizeAndDraw(); | |
const resizeObserver = new ResizeObserver(onResize); | |
resizeObserver.observe(canvas, {box: 'content-box'}); | |
}); | |
const patternSize = 4; | |
function createPatternDataURL() { | |
const ctx = document.createElement('canvas').getContext('2d'); | |
ctx.canvas.width = patternSize; | |
ctx.canvas.height = patternSize; | |
const b = [0, 0, 0, 255]; | |
const t = [0, 0, 0, 0]; | |
const r = [255, 0, 0, 255]; | |
const g = [0, 255, 0, 255]; | |
const imageData = new ImageData(patternSize, patternSize); | |
imageData.data.set([ | |
b, t, t, r, | |
t, b, g, t, | |
t, r, b, t, | |
g, t, t, b, | |
].flat()); | |
ctx.putImageData(imageData, 0, 0); | |
return {patternSize, dataURL: ctx.canvas.toDataURL()}; | |
} | |
/** | |
* Set the pattern's size on this element so that it draws where | |
* 1 pixel in the pattern maps to 1 devicePixel and then set | |
* its position so it's aligned to the pattern of the body element. | |
*/ | |
{ | |
const { patternSize, dataURL } = createPatternDataURL(); | |
const setPattern = (elem) => { | |
const oneDevicePixel = 1 / devicePixelRatio; | |
const patternPixels = oneDevicePixel * patternSize; | |
elem.style.backgroundImage = `url("${dataURL}")`; | |
elem.style.backgroundSize = `${patternPixels}px ${patternPixels}px`; | |
} | |
const div = document.querySelector('#compare'); | |
div.style.backgroundImage = `url("${dataURL}")`; | |
const resizeObserver = new ResizeObserver(entries => { | |
const entry = entries[0]; | |
const displayWidth = entry.devicePixelContentBoxSize[0].inlineSize; | |
const displayHeight = entry.devicePixelContentBoxSize[0].blockSize; | |
log2Elem.textContent = `div devicePixelContentBoxSize: ${displayWidth}, ${displayHeight}`; | |
setPattern(div); | |
}); | |
resizeObserver.observe(div, {box: 'content-box'}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"name":"Checking ResizeObserver devicePixelContentBoxSize","settings":{},"filenames":["index.html","index.css","index.js"]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment