220 lines
5.4 KiB
JavaScript
220 lines
5.4 KiB
JavaScript
// Context and canvas creation helper functions
|
|
var check = require('./util/check')
|
|
var extend = require('./util/extend')
|
|
|
|
function createCanvas (element, onDone, pixelRatio) {
|
|
var canvas = document.createElement('canvas')
|
|
extend(canvas.style, {
|
|
border: 0,
|
|
margin: 0,
|
|
padding: 0,
|
|
top: 0,
|
|
left: 0,
|
|
width: '100%',
|
|
height: '100%'
|
|
})
|
|
element.appendChild(canvas)
|
|
|
|
if (element === document.body) {
|
|
canvas.style.position = 'absolute'
|
|
extend(element.style, {
|
|
margin: 0,
|
|
padding: 0
|
|
})
|
|
}
|
|
|
|
function resize () {
|
|
var w = window.innerWidth
|
|
var h = window.innerHeight
|
|
if (element !== document.body) {
|
|
var bounds = canvas.getBoundingClientRect()
|
|
w = bounds.right - bounds.left
|
|
h = bounds.bottom - bounds.top
|
|
}
|
|
canvas.width = pixelRatio * w
|
|
canvas.height = pixelRatio * h
|
|
}
|
|
|
|
var resizeObserver
|
|
if (element !== document.body && typeof ResizeObserver === 'function') {
|
|
// ignore 'ResizeObserver' is not defined
|
|
// eslint-disable-next-line
|
|
resizeObserver = new ResizeObserver(function () {
|
|
// setTimeout to avoid flicker
|
|
setTimeout(resize)
|
|
})
|
|
resizeObserver.observe(element)
|
|
} else {
|
|
window.addEventListener('resize', resize, false)
|
|
}
|
|
|
|
function onDestroy () {
|
|
if (resizeObserver) {
|
|
resizeObserver.disconnect()
|
|
} else {
|
|
window.removeEventListener('resize', resize)
|
|
}
|
|
element.removeChild(canvas)
|
|
}
|
|
|
|
resize()
|
|
|
|
return {
|
|
canvas: canvas,
|
|
onDestroy: onDestroy
|
|
}
|
|
}
|
|
|
|
function createContext (canvas, contextAttributes) {
|
|
function get (name) {
|
|
try {
|
|
return canvas.getContext(name, contextAttributes)
|
|
} catch (e) {
|
|
return null
|
|
}
|
|
}
|
|
return (
|
|
get('webgl') ||
|
|
get('experimental-webgl') ||
|
|
get('webgl-experimental')
|
|
)
|
|
}
|
|
|
|
function isHTMLElement (obj) {
|
|
return (
|
|
typeof obj.nodeName === 'string' &&
|
|
typeof obj.appendChild === 'function' &&
|
|
typeof obj.getBoundingClientRect === 'function'
|
|
)
|
|
}
|
|
|
|
function isWebGLContext (obj) {
|
|
return (
|
|
typeof obj.drawArrays === 'function' ||
|
|
typeof obj.drawElements === 'function'
|
|
)
|
|
}
|
|
|
|
function parseExtensions (input) {
|
|
if (typeof input === 'string') {
|
|
return input.split()
|
|
}
|
|
check(Array.isArray(input), 'invalid extension array')
|
|
return input
|
|
}
|
|
|
|
function getElement (desc) {
|
|
if (typeof desc === 'string') {
|
|
check(typeof document !== 'undefined', 'not supported outside of DOM')
|
|
return document.querySelector(desc)
|
|
}
|
|
return desc
|
|
}
|
|
|
|
module.exports = function parseArgs (args_) {
|
|
var args = args_ || {}
|
|
var element, container, canvas, gl
|
|
var contextAttributes = {}
|
|
var extensions = []
|
|
var optionalExtensions = []
|
|
var pixelRatio = (typeof window === 'undefined' ? 1 : window.devicePixelRatio)
|
|
var profile = false
|
|
var onDone = function (err) {
|
|
if (err) {
|
|
check.raise(err)
|
|
}
|
|
}
|
|
var onDestroy = function () {}
|
|
if (typeof args === 'string') {
|
|
check(
|
|
typeof document !== 'undefined',
|
|
'selector queries only supported in DOM enviroments')
|
|
element = document.querySelector(args)
|
|
check(element, 'invalid query string for element')
|
|
} else if (typeof args === 'object') {
|
|
if (isHTMLElement(args)) {
|
|
element = args
|
|
} else if (isWebGLContext(args)) {
|
|
gl = args
|
|
canvas = gl.canvas
|
|
} else {
|
|
check.constructor(args)
|
|
if ('gl' in args) {
|
|
gl = args.gl
|
|
} else if ('canvas' in args) {
|
|
canvas = getElement(args.canvas)
|
|
} else if ('container' in args) {
|
|
container = getElement(args.container)
|
|
}
|
|
if ('attributes' in args) {
|
|
contextAttributes = args.attributes
|
|
check.type(contextAttributes, 'object', 'invalid context attributes')
|
|
}
|
|
if ('extensions' in args) {
|
|
extensions = parseExtensions(args.extensions)
|
|
}
|
|
if ('optionalExtensions' in args) {
|
|
optionalExtensions = parseExtensions(args.optionalExtensions)
|
|
}
|
|
if ('onDone' in args) {
|
|
check.type(
|
|
args.onDone, 'function',
|
|
'invalid or missing onDone callback')
|
|
onDone = args.onDone
|
|
}
|
|
if ('profile' in args) {
|
|
profile = !!args.profile
|
|
}
|
|
if ('pixelRatio' in args) {
|
|
pixelRatio = +args.pixelRatio
|
|
check(pixelRatio > 0, 'invalid pixel ratio')
|
|
}
|
|
}
|
|
} else {
|
|
check.raise('invalid arguments to regl')
|
|
}
|
|
|
|
if (element) {
|
|
if (element.nodeName.toLowerCase() === 'canvas') {
|
|
canvas = element
|
|
} else {
|
|
container = element
|
|
}
|
|
}
|
|
|
|
if (!gl) {
|
|
if (!canvas) {
|
|
check(
|
|
typeof document !== 'undefined',
|
|
'must manually specify webgl context outside of DOM environments')
|
|
var result = createCanvas(container || document.body, onDone, pixelRatio)
|
|
if (!result) {
|
|
return null
|
|
}
|
|
canvas = result.canvas
|
|
onDestroy = result.onDestroy
|
|
}
|
|
// workaround for chromium bug, premultiplied alpha value is platform dependent
|
|
if (contextAttributes.premultipliedAlpha === undefined) contextAttributes.premultipliedAlpha = true
|
|
gl = createContext(canvas, contextAttributes)
|
|
}
|
|
|
|
if (!gl) {
|
|
onDestroy()
|
|
onDone('webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org')
|
|
return null
|
|
}
|
|
|
|
return {
|
|
gl: gl,
|
|
canvas: canvas,
|
|
container: container,
|
|
extensions: extensions,
|
|
optionalExtensions: optionalExtensions,
|
|
pixelRatio: pixelRatio,
|
|
profile: profile,
|
|
onDone: onDone,
|
|
onDestroy: onDestroy
|
|
}
|
|
}
|