How to increase quality on a PixiJS canvas? - javascript

I made horizontal scroll website with PIXI JS and it has a ripple effect.
it worked fine till now but the only issue is it's showing a very low quality when I open up the website and from what I figured out that PIXI JS renderer get width and height to 800 x 600 resolution.
any ideas how to change the quality ?
here's the PIXI JS code snippet:
// Set up the variables needed and loads the images to create the effect.
// Once the images are loaded the ‘setup’ function will be called.
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
resolution: 1,
antialias : true
});
document.body.appendChild(app.view);
app.stage.interactive = true;
var posX, displacementSprite, displacementFilter, bg, vx;
var container = new PIXI.Container();
app.stage.addChild(container);
PIXI.loader.add("depth.png").add("polygonexample.jpg").load(setup);
// In the ‘setup’ function the displacement sprite is created
// that will create the effect and this is added to a displacement filter.
// It’s then set to move its anchor point to the centre of the image and positioned on the screen.
function setup() {
posX = app.renderer.width / 2;
displacementSprite = new PIXI.Sprite(PIXI.loader.resources["depth.png"].texture);
displacementFilter = new PIXI.filters.DisplacementFilter(displacementSprite);
displacementSprite.anchor.set(0.5);
displacementSprite.x = app.renderer.width / 2;
displacementSprite.y = app.renderer.height / 2;
vx = displacementSprite.x;
// To finish off the ‘setup’ function, the displacement filter scale is set and the background positioned.
// Notice the scale is ‘0’ for the displacement, that’s because it will be set to a height as soon as the mouse moves.
app.stage.addChild(displacementSprite);
container.filters = [displacementFilter];
displacementFilter.scale.x = 0;
displacementFilter.scale.y = 0;
bg = new PIXI.Sprite(PIXI.loader.resources["polygonexample.jpg"].texture);
bg.width = app.renderer.width;
bg.height = app.renderer.height;
container.addChild(bg);
app.stage.on('mousemove', onPointerMove).on('touchmove', onPointerMove);
loop();
}
// grab the position of the mouse on the x-axis whenever the mouse moves.
function onPointerMove(eventData) {
posX = eventData.data.global.x;
}
// create a function that continually updates the screen. A velocity for the x-axis is worked out using the position of the mouse and the ripple.
function loop() {
requestAnimationFrame(loop);
vx += (posX - displacementSprite.x) * 0.045;
displacementSprite.x = vx;
var disp = Math.floor(posX - displacementSprite.x);
if (disp < 0) disp = -disp;
var fs = map(disp, 0, 500, 0, 120);
disp = map(disp, 0, 500, 0.1, 0.6);
displacementSprite.scale.x = disp;
displacementFilter.scale.x = fs;
}
// Finally, the map function is declared that maps value ranges to new values.
map = function(n, start1, stop1, start2, stop2) {
var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
return newval;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.7/pixi.min.js"></script>

Try creating renderer using this code
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
resolution: 1,
});
But if you resize window after creating renderer, it won't be automatically resized to window size. To solve that you can listen to resize event
EDIT: Removing margins also might help.
body {
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
display: block;
}

just found the answer and it was very silly thing actually.
the issue was with the width and the height they were set to window.innerWidth and window.innerHeight. my image quality was quite high so basically multiplying the width and the height inside PIXI.Application by 3 or 4 increases the qualit.
const app = new PIXI.Application({
width: window.innerWidth*3,
height: window.innerHeight*3,
resolution: 1,
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.7/pixi.min.js"></script>

Related

Zero-scaled displacement image distorts Sprite on container rotation: Pixi.js

I have a simple Pixi.js scene where there are 4 Sprites vertically placed. All of them have a displacement image assigned. To begin the sketch, I have set the displacement image to scale 0 so the Sprite doesn't appear distorted by default. The Sprites are perfect rectangles when parent container is not rotated, but when the parent container is rotated, the Sprite gets some displacement/cropping applied on corners. How do I remove this displacement at sketch start?
I have attached the screenshot and encircled the croppy parts.
And this is the code:
let width = window.innerWidth;
let height = window.innerHeight;
const app = new PIXI.Application({
width: width,
height: height,
transparent: false,
antialias: true
});
app.renderer.backgroundColor = 0x404040;
// making the canvas responsive
window.onresize = () => {
let width = window.innerWidth;
let height = window.innerHeight;
app.renderer.resize(width, height);
}
app.renderer.view.style.position = 'absolute';
document.body.appendChild(app.view);
let pContainer= new PIXI.Container();
pContainer.pivot.set(-width/2, -350);
pContainer.rotation = -0.3; // This rotation distorts the Sprites
app.stage.addChild(pContainer);
for (let i = 0; i < 4; i++) {
let container = new PIXI.Container();
container.pivot.y = -i * 210;
let image = new PIXI.Sprite.from('image.jpg');
image.width = 100;
image.height = 200;
image.anchor.set(0.5, 0.5);
let dispImage = new PIXI.Sprite.from('disp.jpg');
let dispFilter = new PIXI.filters.DisplacementFilter(dispImage);
dispImage.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;
container.filters = [dispFilter];
// Turn disp scale to zero so it doesnt show distorted image by default
dispImage.scale.set(0);
container.addChild(image);
container.addChild(dispImage);
pContainer.addChild(container);
}
Thank you.
disp.jpg:
image.jpg
The Sprites' corners getting distorted. Encircled in yellow
I had the same problem, the simpler fix is to use a rect behind that is bigger than the photo, it can be the screen size too

Pixi.js - Re-positioning element after window resize

I'm quite a noob with Pixi.js so here comes the noob question.
I'm trying to display a square in the middle of the screen. When I resize the window, the square should stay in the middle.
When drawing the square I'm using
const square = new PIXI.Graphics();
square.beginFill(0xff0000, 1);
square.drawRect(app.renderer.width /2, app.renderer.height / 2, 50, 50);
square.endFill();
app.stage.addChild(square);
Then, I understand that the x and y properties of square are relative to the initial drawing position. So square.x = 0 will keep the square in the middle.
But then, how do I reset the center of the window (and so the position of the square) when I resize it?
This can be your solution. This is diametric resize response.
I use something like :
getWidthByPer : function (per) {
return window.innerWidth / 100 * per
}
console.log = function(){};
var app = new PIXI.Application({
autoResize: true,
resolution: 1.77
});
document.querySelector("#MYAPP").appendChild(app.view);
const rect = new PIXI.Graphics()
.beginFill(0x55faaf)
.drawRect(-50, -50, 100, 100);
app.stage.addChild(rect);
window.addEventListener('resize', resize);
function resize() {
const parent = app.view.parentNode;
app.renderer.resize(parent.clientWidth, parent.clientHeight);
rect.position.set(
app.screen.width / 2 ,
app.screen.height / 2
);
}
window.onload = function(){
resize();
};
canvas {
display:block;
}
#MYAPP {
position: absolute;
overflow: hidden;
top:0%;
left:0%;
width: 100%;
height: 100%;
}
<script src="https://pixijs.download/v4.7.0/pixi.min.js"></script>
<div id="MYAPP"></div>
I made adaptive-scale to reuse common resizing needs for multiple projects

Is there a way to avoid letterboxing with canvas scaling?

I'm working on a small project in Javascript, using Pixi.js as the rendering engine. However, I've only found a few methods of scaling the canvas to full window that seem to work best for the current version. It does have a caveat, however, in that it produces letterboxes on the sides based on the orientation.
Is it possible to avoid the letterboxing at all with Pixi?
This is the code that I have so far, as it relates to the scaling:
var application = null;
var GAME_WIDTH = 1060;
var GAME_HEIGHT = 840;
var ratio = 0;
var stage = null;
application = new PIXI.Application(
{
width: GAME_WIDTH,
height: GAME_HEIGHT,
backgroundColor: 0x00b4f7,
view: document.getElementById("gwin")
});
stage = new PIXI.Container(true);
window.addEventListener("resize", rescaleClient);
function rescaleClient()
{
ratio = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight /
GAME_HEIGHT);
stage.scale.x = stage.scale.y = ratio;
application.renderer.resize(Math.ceil(GAME_WIDTH * ratio), Math.ceil(GAME_HEIGHT * ratio));
}
My goal with this is to achieve a similar full screen/window effect to Agar.io/Slither.io, however I have not discovered a satisfactory method that allows it easily. There do seem to be examples that use Pixi to achieve this, but the code is more then often closed source, and they seem to use external tools such as Ionic and Phonegap.
I finally found the answer. I was close to the right track, but a few more things needed to be applied.
application.renderer.view.style.position = "absolute";
application.renderer.view.style.display = "block";
application.renderer.autoResize = true;
application.renderer.resize(window.innerWidth, window.innerHeight);
This sets some additional things internally, while a minor modification to the resize script...
ratio = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight / GAME_HEIGHT);
stage.scale.x = stage.scale.y = ratio;
renderer.resize(window.innerWidth, window.innerHeight);
configures things correctly, so that the related Renderer window now fills the screen without squashing the content.
This was not easy to discover. So many tutorials just leave it at the first half, and assume that is what people wish to do.
var application;
//var GAME_WIDTH = window.screen.width-20;
var GAME_WIDTH = window.innerWidth;
//var GAME_WIDTH = document.body.clientWidth;
var GAME_HEIGHT = window.innerHeight;
var ratiox = 0;
var ratioy = 0;
var container;
application = new PIXI.Application(
{
width: GAME_WIDTH,
height: GAME_HEIGHT,
backgroundColor: 0x00b4f7,
view: document.getElementById("gwin")
});
//document.body.appendChild(application.view);
container = new PIXI.Container(true);
application.stage.addChild(container);
window.addEventListener("resize", rescaleClient);
function rescaleClient()
{
//ratiox = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight / GAME_HEIGHT);
application.stage.scale.x = ratiox = window.innerWidth / GAME_WIDTH
application.stage.scale.y = ratioy = window.innerHeight / GAME_HEIGHT;
application.renderer.resize(Math.ceil(GAME_WIDTH * ratiox), Math.ceil(GAME_HEIGHT * ratioy));
}
#viewport{
width:device-width
}
body {
padding :0px;
margin:0px
}
<script src="https://pixijs.download/v4.6.2/pixi.min.js"></script>
<canvas id="gwin"></canvas>

Fabric JS getContext('2d') not matching getImageData color

Website: http://minimedit.com/
Currently implementing an eye dropper. It works fine in my normal resolution of 1080p, but when testing on a higher or lower resolution it doesn't work.
This is the basics of the code:
var ctx = canvas.getContext("2d");
canvas.on('mouse:down', function(e) {
var newColor = dropColor(e, ctx);
}
function dropColor(e, ctx) {
var mouse = canvas.getPointer(e.e),
x = parseInt(mouse.x),
y = parseInt(mouse.y),
px = ctx.getImageData(x, y, 1, 1).data;
return rgb2hex('rgba('+px+')');
}
When I first initiate the canvas I have it resize to fit resolution:
setResolution(16/9);
function setResolution(ratio) {
var conWidth = ($(".c-container").css('width')).replace(/\D/g,'');
var conHeight = ($(".c-container").css('height')).replace(/\D/g,'');
var tempWidth = 0;
var tempHeight = 0;
tempHeight = conWidth / ratio;
tempWidth = conHeight * ratio;
if (tempHeight > conHeight) {
canvas.setWidth(tempWidth);
canvas.setHeight(conHeight);
} else {
canvas.setWidth(conWidth);
canvas.setHeight(tempHeight);
}
}
The x and y mouse coordinates work fine when zoomed in, but they don't line up with the returned image data. It seems as though the ctx isn't changing it's width and height and scaling along with the actual canvas size.
The canvas element is showing the correct width and height before using getContext as well.
Any ideas on a solution?
Feel free to check out the full scripts on the live website at: http://minimedit.com/
Try "fabric.devicePixelRatio" for calculating actual position, for example:
x = parseInt(mouse.x) * fabric.devicePixelRatio

Why are the rectangles I am creating on this canvas not getting put in the right spot?

I am trying to create a simple page where you click and can create rectangles on a canvas. It takes the user's mouse clicks as input, and then creates a rectangle from the x and y of the click. However, it places the rectangle off to the side by some amount, and I am not sure why.
Fiddle: https://jsfiddle.net/2717s53h/
HTML
<canvas id="cnv"></canvas>
CSS
#cnv{
width:99vw;
height:98vh;
background-color:#faefbd;
}
JAVASCRIPT
$(function () {
var canvas = $('#cnv');
var canvObj = document.getElementById('cnv');
var ctx = canvObj.getContext('2d');
var point1 = {};
var point2 = {};
canvas.click(function (e) {
console.log(e);
var x = e.pageX;
var y = e.pageY;
console.log(x);
console.log(y);
if (Object.keys(point1).length == 0)
{
point1.x = x;
point1.y = y;
}
else if (Object.keys(point2).length == 0)
{
point2.x = x;
point2.y = y;
console.log(point1);
console.log(point2);
var width = point2.x - point1.x;
var height = point2.y - point1.y;
width = width < 0 ? width * -1 : width;
height = height < 0 ? height * -1 : height;
ctx.fillRect(x, y, 10, 10);
point1 = {};
point2 = {};
}
});
});
There is a difference between the CSS height/ width and the HTML canvas attributes height and width: the former defines the space the canvas occupies in the page; the latter defines the rendering surface. In concreto, suppose you have the following canvas:
<canvas height="400" width="600"></canvas>
with a viewport of a 1200x800 size and the canvas' CSS is set to width: 100%; height: 100%;, then your canvas will be rendered as stretched out twice as big and blurry in both height and width (like in your fiddle; clearly those rectangles are bigger than 10px). As a consequence, the page coordinates are not in sync with the canvas' coordinates.
As per the specification, your fiddle's canvas rendering surface is 300x150 because you didn't specify the width/height attributes:
The width attribute defaults to 300, and the height attribute defaults to 150.
See a slightly 'corrected' version of your fiddle.
As a result my advice (as a non-expert on HTML-canvas) would be to always specify those 2 attributes and not to mess with different rendering surface vs. display dimensions (certainly not relative ones like vw, vh, %, em, ...) if you don't want unpredictable results; although some SO users have been looking for a solution.

Categories

Resources