p5.prototype.scaler = undefined; p5.prototype.createAdaptiveCanvas = function (width, height, fitScreen) { let c = createCanvas(width, height); scaler = new Scaler( width, height, fitScreen === undefined ? true : fitScreen ); return c; }; function createAdaptiveGraphics(width, height, bufferRenderer) { let newBuffer = new AdaptiveBuffer( createGraphics(width, height), bufferRenderer ); scaler.addBuffer(newBuffer); scaler.adjust(); return newBuffer; } function addAdaptiveGraphics(graphics, bufferRenderer) { let newBuffer = new AdaptiveBuffer(graphics, bufferRenderer); scaler.addBuffer(newBuffer); scaler.adjust(); } p5.prototype.updateAdaptiveCanvas = function () { if (scaler !== undefined) scale(scaler.scale()); }; window.addEventListener( "resize", function (event) { scaler.scaleCanvas(); }, true ); p5.prototype.registerMethod("pre", p5.prototype.updateAdaptiveCanvas); class AdaptiveBuffer { #graphics; #renderer; constructor(graphics, renderer) { this.#graphics = graphics; this.#renderer = renderer; } reRender() { this.#renderer(this.#graphics); } graphics() { return this.#graphics; } } class Scaler { #width; #height; #ratio; #scale; #fitScreen; #container; #buffers; constructor(w, h, fitScreen) { this.#width = w; this.#height = h; this.#ratio = this.#width / this.#height; this.#fitScreen = fitScreen; this.#buffers = []; if (!this.#fitScreen) return; this.scaleCanvas(); } scaleCanvas() { if (this.#fitScreen) { let scaleToWidth, scaleToHeight; if (this.#container !== undefined) { let cs = getComputedStyle(this.#container); let paddingX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight); let paddingY = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom); let borderX = parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth); let borderY = parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth); scaleToWidth = this.#container.offsetWidth - paddingX - borderX; scaleToHeight = this.#container.offsetHeight - paddingY - borderY; } else { scaleToWidth = window.innerWidth; scaleToHeight = window.innerHeight; } this._doScale(scaleToWidth, scaleToHeight); } } scaleCanvasTo(s) { this._doScale(this.#width * s, this.#height * s); } scaleCanvasToWidth(newWidth) { this._doScale(newWidth, this.#height * (newWidth/this.#width)); } scaleCanvasToHeight(newHeight) { this._doScale(this.#width * (newHeight/this.#height), newHeight); } _doScale(w, h) { let scaledWidth, scaledHeight; let diffWidth = Math.abs(this.#width - w); let diffHeight = Math.abs(this.#height - h); if (Math.min(diffWidth, diffHeight) == diffWidth) { scaledWidth = w; scaledHeight = w / this.#ratio; if (scaledHeight > h) { scaledHeight = h; scaledWidth = h * this.#ratio; } } else { scaledHeight = h; scaledWidth = h * this.#ratio; if (scaledWidth > w) { scaledWidth = w; scaledHeight = w / this.#ratio; } } this.#scale = scaledWidth / this.#width; resizeCanvas(scaledWidth, scaledHeight); this.adjust(); } width() { return this.#width; } height() { return this.#height; } scale() { return this.#scale; } adjust() { for (let b = 0; b < this.#buffers.length; b++) { this.#buffers[b] .graphics() .pixelDensity( max(Math.ceil(this.#scale) * displayDensity() * 1.2, displayDensity()) ); this.#buffers[b].reRender(); } } addBuffer(pg) { this.#buffers.push(pg); } setCanvasContainer(container) { this.#container = container; this.scaleCanvas(); } mouseX() { return mouseX / this.#scale; } mouseY() { return mouseY / this.#scale; } pmouseX() { return pmouseX / this.#scale; } pmouseY() { return pmouseY / this.#scale; } }