Skip to content

Instantly share code, notes, and snippets.

@fuunnx
Created July 31, 2017 08:48
Show Gist options
  • Save fuunnx/ee3f914c7d8fac1fd65773aa74f6e04b to your computer and use it in GitHub Desktop.
Save fuunnx/ee3f914c7d8fac1fd65773aa74f6e04b to your computer and use it in GitHub Desktop.
flexible-canvas-component
import {addResizeListener} from './resizeListener'
import canvasPixelRatio from './pixelRatio'
export class FlexibleCanvas extends HTMLDivElement {
static get observedAttributes() {return ['width', 'height', 'pixelRatio'] }
createdCallback () {
this.canvas = this.appendChild(document.createElement('canvas')) //eslint-disable-line
this.canvas.setAttribute('style', `
display: block;\
position: absolute;\
top: 0;\
left: 0;\
width: 100%;\
height: 100%;\
overflow: hidden;\
`)
this.resizeCb()
this.style.overflow = 'hidden'
//https://github.com/WebReflection/document-register-element#common-issues--caveat
this.disposeResizeListener = addResizeListener(
this,
this.resizeCb.bind(this),
)
}
disconnectedCallback () {
this.disposeResizeListener()
}
attributeChangedCallback () {
this.resizeCb()
}
disposeResizeListener () {}
resizeCb () {
const pixelRatio =
parseFloat(this.dataset['pixelRatio'])
|| canvasPixelRatio
this.canvas.getContext('2d').scale(pixelRatio, pixelRatio)
this.canvas.width = (this.clientWidth * pixelRatio || this.width)
this.canvas.height = (this.clientHeight * pixelRatio || this.height)
}
}
export default FlexibleCanvas
require('document-register-element')
const FlexibleCanvas = require('./component').default
document.registerElement(
'flexible-canvas',
FlexibleCanvas,
{extends: 'div'},
)
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
// http://www.html5rocks.com/en/tutorials/canvas/hidpi/?redirect_from_locale=fr
const devicePixelRatio = window.devicePixelRatio || 1
const backingStoreRatio = context.webkitBackingStorePixelRatio
|| context.mozBackingStorePixelRatio
|| context.msBackingStorePixelRatio
|| context.oBackingStorePixelRatio
|| context.backingStorePixelRatio
|| 1
const ratio = devicePixelRatio / backingStoreRatio
export default ratio
import insertionQ from 'insertion-query'
export const addResizeListener = function (element, onResize) {
const resizeEvent = new CustomEvent('resize', {bubbles: true})
const resizeHandler = () => element.dispatchEvent(resizeEvent)
const objID = `fnx-resizelistener-${Date.now()}-${randomInt(1000)}`
const iframe = document.createElement('iframe')
iframe.setAttribute('type', 'text/html')
iframe.setAttribute('id', objID)
iframe.setAttribute('style', `\
display: block;\
position: absolute;\
top: 0;\
left: 0;\
width: 100%;\
height: 100%;\
overflow: hidden;\
pointer-events: none;\
z-index: -1;\
opacity: 0;\
`)
insertionQ.config({strictlyNew: false, timeout: 0})
insertionQ('#' + objID).every(onInsertion)
function onInsertion () {
const {position, display} = getComputedStyle(element)
if (position === 'static') { element.style.position = 'relative' }
if (display === 'inline') { element.style.display = 'block' }
const contentDocument = iframe.contentDocument
? iframe.contentDocument
: iframe.contentWindow.document
contentDocument.defaultView.addEventListener('resize', resizeHandler)
element.addEventListener('resize', onResize)
resizeHandler()
}
setImmediate(() => element.appendChild(iframe))
return function dispose () {
const contentDocument = iframe.contentDocument
? iframe.contentDocument
: iframe.contentWindow.document
contentDocument.defaultView.removeEventListener('resize', resizeHandler)
element.removeEventListener('resize', onResize)
element.removeChild(iframe)
}
}
function randomInt (max) {
return Math.round(Math.random() * max)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment