Fabricjs background with transparent parts - fabricjs

I have a Fabric.js canvas with a background image that has some transparent parts. I want the transparent parts to show the color of the div behind the canvas (e.g. red). So this works:
canvas.setBackgroundColor(null);
canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas), {
opacity: 1.0
});
Now say I want to to change the opacity of the image to 0.3. In this case the non-transparent parts of the image show the red underneath. But I would like the transparent parts to show red, and the non-transparent parts to be faded against a white background. Is this possible?

I'm not sure if I'm understanding you correctly, but you can just load in a .png with transparency in it and it'll show the canvas background in the transparent parts.
For example:
var canvas = new fabric.Canvas('fabric');
canvas.backgroundColor = 'green';
canvas.renderAll();
fabric.Image.fromURL("https://i.imgur.com/aSEcfuz.png", function(img){
img.left = 0;
img.top = 0;
img.width = 200;
img.height = 200;
canvas.add(img);
});
<canvas id="fabric" width="500" height="500"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.2/fabric.min.js"></script>
Workaround which places a white background behind the image and moves it along with the image:
var canvas = new fabric.Canvas('fabric');
canvas.backgroundColor = 'green';
canvas.renderAll();
var sharedProperties = {
left: 0,
top: 0,
width: 200,
height: 200
};
var image;
var rect = new fabric.Rect({
left: sharedProperties.left,
top: sharedProperties.top,
fill: 'white',
width: sharedProperties.width,
height: sharedProperties.height
});
canvas.add(rect);
fabric.Image.fromURL("https://i.imgur.com/aSEcfuz.png", function(img) {
image = img;
img.left = sharedProperties.left;
img.top = sharedProperties.top;
img.width = sharedProperties.width;
img.height = sharedProperties.height;
canvas.add(img);
image.on('moving', function(event) {
rect.set({
left: image.left,
top: image.top
});
rect.setCoords();
});
});
<canvas id="fabric" width="500" height="500"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.2/fabric.min.js"></script>

Related

How can I vertically orient my text using SVG.js?

I have a vertical rectangle and I want to place a text inside it.
let draw = SVG('drawing').size('100%', '100%');
let rect;
let text;
rect = draw.rect(50, '100%').attr({
fill: color,
stroke: '#d9d9d9',
'stroke-width': 1,
});
rect.move(50, 0);
text = draw.text('Some important text').font({ fill: '#ffffff' });
text.move(50, 0);
I tried to use .rotate(90) but it didn't work. Can anyone help me?
Set the text-orientation style to upright and the writing-mode style to vertical-lr to get vertical text.
In version 3 of svg.js the .style method becomes .css instead
let draw = SVG('drawing').size('100%', '100%');
let rect;
let text;
rect = draw.rect(50, '100%').attr({
fill: 'red',
stroke: '#d9d9d9',
'stroke-width': 1,
});
rect.move(50, 0);
text = draw.text('Some important text').font({ fill: '#ffffff' });
text.move(70, 0);
text.style({'text-orientation': 'upright', 'writing-mode': 'vertical-lr'})
html, body, div {
width: 100%;
height: 100%;
}
<script src=" https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.7.1/svg.min.js"></script>
<div id="drawing"></div>

How to make canvas responsive using Phaser 3?

Previously I was working on Phaser 2 but now I need to switch to Phaser 3.
I tried to make the canvas responsive with ScaleManager but it is not working.
I think some of the methods changed but I didn't find any help to rescale the stage full screen.
var bSize = {
bWidth: window.innerWidth ||
root.clientWidth ||
body.clientWidth,
bHeight: window.innerHeight ||
root.clientHeight ||
body.clientHeight,
};
var game;
var canvas = document.getElementById("canvas");
function create() {
// Scaling options
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
// Have the game centered horizontally
game.scale.pageAlignHorizontally = true;
// And vertically
game.scale.pageAlignVertically = true;
// Screen size will be set automatically
game.scale.setScreenSize(true);
}
window.onload = function() {
// Create game canvas and run some blocks
game = new Phaser.Game(
bSize.bWidth, //is the width of your canvas i guess
bSize.bHeight, //is the height of your canvas i guess
Phaser.AUTO,
'frame', { create: create });
canvas.style.position = "fixed";
canvas.style.left = 0;
canvas.style.top = 0;
}
Since v3.16.0, use the Scale Manager. For short:
var config = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.FIT,
parent: 'phaser-example',
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 800,
height: 600
},
//... other settings
scene: GameScene
};
var game = new Phaser.Game(config);
Here is the full code and here are some useful examples using the Scale Manager.
There isn't a scale manager for Phaser 3 yet but it's in development. For now I suggest following this tutorial. It basically centres the canvas with some CSS, then calls a resize function that handles maintaining the game ratio when the resize event is emitted by the window.
Here is the code used in the tutorial linked above:
The css:
canvas {
display: block;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
The resize function:
function resize() {
var canvas = document.querySelector("canvas");
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var windowRatio = windowWidth / windowHeight;
var gameRatio = game.config.width / game.config.height;
if(windowRatio < gameRatio){
canvas.style.width = windowWidth + "px";
canvas.style.height = (windowWidth / gameRatio) + "px";
}
else {
canvas.style.width = (windowHeight * gameRatio) + "px";
canvas.style.height = windowHeight + "px";
}
}
Then:
window.onload = function() {
//Game config here
var config = {...};
var game = new Phaser.Game(config);
resize();
window.addEventListener("resize", resize, false);
}
Try adding max-width to canvas css and then max-height based on aspect ratio. E.g:
canvas {
display: block;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 100%;
max-height: 50vw;
}
Scale manager will handle assets(Images,Sprites,..,...) positions and size sometime?

How do I scale the scene to fullscreen?

I'm currently learning Phaser 3. However, all the documentation I can find is about Phaser2.
When you create a game you have to set the width and height in the config:
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
};
How can I scale the scene to fullscreen?
UPDATE
Phaser 3.16 is released on now (Feb, 2019), which has inbuilt Scale Manager. It provide various methods to scale your game. Check it out before trying the code below.
Phaser.Scale Docs
Notes on Scale Manager
Old Answer
You can resize the canvas element using resize function mentioned in code snippet and execute that function before starting game and whenever screen is resized. This way you can maintain the aspect ratio of 800:600(4:3) and fit the canvas element to full-screen according to screen ratio.
Run code snippet in Full Page Mode and resize your browser to see how canvas element is resized. Size of blue rectangle is the size of your canvas(game).
var game;
var gameWidth = 800;
var gameHeight = 600;
window.onload = function() {
var config = {
type: Phaser.CANVAS,
width: gameWidth,
height: gameHeight,
scene: [intro]
};
game = new Phaser.Game(config);
resize();
window.addEventListener("resize", resize, false);
};
function resize() {
var canvas = document.querySelector("canvas");
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var windowRatio = windowWidth / windowHeight;
var gameRatio = game.config.width / game.config.height;
if (windowRatio < gameRatio) {
canvas.style.width = windowWidth + "px";
canvas.style.height = (windowWidth / gameRatio) + "px";
} else {
canvas.style.width = (windowHeight * gameRatio) + "px";
canvas.style.height = windowHeight + "px";
}
}
var intro = new Phaser.Scene('intro');
intro.create = function() {
var rect = new Phaser.Geom.Rectangle(0, 0, 800, 600);
var graphics = this.add.graphics({
fillStyle: {
color: 0x0000ff
}
});
graphics.fillRectShape(rect);
};
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
background: #000000;
padding: 0px;
margin: 0px;
}
canvas {
display: block;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
<script src="https://cdn.jsdelivr.net/npm/phaser#3.6.0/dist/phaser.min.js"></script>
</head>
<body>
</body>
</html>
You should check out this post. It explains this code in detail.
css style (in index.html) should be as simple as
body { margin:0; padding:0; overflow:hidden }
body>canvas { width:100%!important; height:100%!important;
position:fixed; top:0; left:0 }
!important suffix is needed to override the dynamic html style
for example
<canvas width="800" height="600"
style="width: 681.778px; height: 511.333px;
margin-left: 0px; margin-top: 0px;"></canvas>
phaser config in index.js
const config = {
parent: "phaser-example",
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create
},
// https://rexrainbow.github.io/phaser3-rex-notes/docs/site/scalemanager/
scale: {
// ignore aspect ratio:
mode: Phaser.Scale.RESIZE,
// keep aspect ratio:
//mode: Phaser.Scale.FIT,
//mode: Phaser.Scale.ENVELOP, // larger than Scale.FIT
//mode: Phaser.Scale.HEIGHT_CONTROLS_WIDTH, // auto width
//mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT, // auto height
autoCenter: Phaser.Scale.NO_CENTER,
//autoCenter: Phaser.Scale.CENTER_BOTH,
//autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
//autoCenter: Phaser.Scale.CENTER_VERTICALLY,
},
autoRound: false,
};

Fabric.js: How to remove padding and format selection box? (padding still exists after zoom)

I am trying to format selection border style to look like in inkscape(image left side).
I have tried to set the object padding to zero with this:
fabric.Object.prototype.set({
padding: 0,
});
If I zoom in this is more apparent and padding grows.
Example: Left side inkscape selection box style, right side actual fabric.js selection box
How can i remove the padding?
Here is jsFiddle.
That's because of stroke width, set strokeWidth:0 to object.
DEMO
var canvas = window.__canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({left: 10, top: 10,strokeWidth:0, width: 60, height: 60, fill: 'blue'});
rect.editable = true;
rect.customType = 'shape';
rect.describtion = 'fabric.js rect object';
rect.cornerColor = 'red';
rect.borderColor = 'red';
rect.cornerSize = 8;
rect.padding = 0;
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.setZoom(20);
canvas{
border:2px solid #000;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>

How to keep scaling always at 1 on FabricJS [Edited]

I need in my application made in fabricJS, that when I modify an object with the scaling handlers, the scaling stays in 1, and that the size of the object takes the value of the height multiplied by scaleX. I can apply the same for the width. But I can not apply this in the images. How can I fix this?
I leave an example fiddle for a square, and an image, so that you can see the result.
The result in the image is similar to a crop, and I can not avoid this, because apparently, when I modify the container of the image, the _element property that also contains scaleX and scaleY does not change, so the image is not resized inside the container.
Here is jsFiddle.
var canvas = new fabric.Canvas('canvas');
var rect1 = new fabric.Rect({
width: 100,
height: 100,
left: 200,
top: 200,
angle: 0,
fill: 'rgba(0,0,255,1)',
originX: 'center',
originY: 'center'
});
canvas.add(rect1);
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(myImg) {
//i create an extra var for to change some image properties
var img1 = myImg.set({
left: 0,
top: 0,
width: 150,
height: 150
});
canvas.add(img1);
});
canvas.on('mouse:up', function(e) {
/*if(e.target != null){
//alert(e.target.width*e.target.scaleX);
}*/
//console.log(e.target);
canvas.getActiveObjects().forEach(function(obj) {
//if(obj.get('type')!='image'){
obj.set('width', obj.width * obj.scaleX, obj);
obj.set('height', obj.height * obj.scaleY, obj);
//if(obj.get('type')!='image'){
obj.scaleX = 1;
obj.scaleY = 1;
//}else{
// obj.scaleX = 1;
// obj.scaleY = 1;
// obj._element.scaleX = 1;
// obj._element.scaleY = 1;
// console.log("Width Contenedor Imagen: "+obj.width+" Width Imagen: "+obj._element.width);
// console.log("Scale Contenedor Imagen: "+obj.scaleX+" Scale Imagen: "+obj._element.scaleX);
//}
obj.setCoords();
//}
});
});
EDIT: New Discovery
Speaking of text, rect, images and polylines, it seems that I am modifying an external container, because the inner content remains intact. How can I modify the size of that let's say, inner container?

Resources