Modify polyline - fabricjs

If I want to add an extra line to an existing polyline, should I remove this existing polyline from the canvas first, modify the points matrix, and add the new polyline? Or is it possible to change the existing polyline, like changing the text of a text object?

You may remove whole polyline and add a new one or else you need to calculate the dimensions(left,top and pathoffset) and set it to polyline.
DEMO
var canvas = new fabric.Canvas('c');
var points = [];
var random = fabric.util.getRandomInt;
points.push(new fabric.Point(random(100,200),random(200,300)));
points.push(new fabric.Point(random(200,300),random(100,200)));
points.push(new fabric.Point(random(200,250),random(150,200)));
var polyLine = new fabric.Polyline(points, {
stroke: 'black',
fill: ''
});
canvas.add(polyLine);
setPolyCoords();
function addPoint(){
polyLine.points.push(new fabric.Point(random(100,400),random(100,400)));
setPolyCoords();
}
function setPolyCoords(){
polyLine._calcDimensions();
polyLine.set({
top : polyLine.minY,
left : polyLine.minX,
pathOffset : {
x: polyLine.minX + polyLine.width / 2,
y: polyLine.minY + polyLine.height / 2
}
});
polyLine.dirty = true;
polyLine.setCoords();
canvas.renderAll();
}
canvas {
border: 1px solid #f00;
margin: 0px;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.js"></script>
<button onclick='addPoint()'>Add Point</button>
<canvas id="c" width="400" height="400"></canvas>

With Fabric version 2.7.0 this is become easier then in #Durga his answer.
See the new code in the demo below.
You can also skip setting the dirty flag manually by passing objectCaching: false to your polyline during construction:
var polyLine = new fabric.Polyline(points, {
stroke: 'black',
fill: '',
objectCaching: false
});
DEMO
var canvas = new fabric.Canvas('c');
var points = [];
var random = fabric.util.getRandomInt;
points.push(new fabric.Point(random(100,200),random(200,300)));
points.push(new fabric.Point(random(200,300),random(100,200)));
points.push(new fabric.Point(random(200,250),random(150,200)));
var polyLine = new fabric.Polyline(points, {
stroke: 'black',
fill: ''
});
canvas.add(polyLine);
function addPoint(){
polyLine.points.push(new fabric.Point(random(100,400),random(100,400)));
polyLine.dirty = true;
canvas.renderAll();
}
canvas {
border: 1px solid #f00;
margin: 0px;
display: block;
}
<script src="https://rawgit.com/fabricjs/fabric.js/master/dist/fabric.min.js"></script>
<button onclick='addPoint()'>Add Point</button>
<canvas id="c" width="400" height="400"></canvas>

Related

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>

FabricJS. How to add dimensions displaying in controls?

How to add dimensions displaying in controls like on screenshot?
Create a text object and set it hidden. And when you are scalling object set the scale width and height to hidden text and make visible. On object modified set visible false to the text.
DEMO
var canvas = new fabric.Canvas("c");
canvas.setHeight(200);
canvas.setWidth(300);
var dimText = new fabric.Text("demo", {
fontSize: 15,
visible: false
});
canvas.add(dimText);
var circle = new fabric.Circle({
left: 15,
top: 15,
radius: 20,
fill:'',
stroke: 'red'
});
canvas.add(circle);
var text = new fabric.Text("2018", {
padding: 30,
lineHeight: 30
});
canvas.add(text);
canvas.centerObject(text);
text.setCoords();
canvas.on('object:scaling', function(option) {
var object = option.target;
var pointer = canvas.getPointer(option.e);
dimText.set({
left: pointer.x - 20,
top: pointer.y - 20,
text: parseInt(object.width * object.scaleX) + 'x' + parseInt(object.height * object.scaleY),
visible: true
})
});
canvas.on('object:modified', function(option) {
dimText.set('visible', false);
});
canvas {
border: 1px solid #dddddd;
margin-top: 10px;
border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.7/fabric.min.js"></script>
<canvas id="c"></canvas>

fabric js object manage with another object

My canvas has two objects. The first one is selectable true and the second one is selectable false. I am looking to manage the second object through the first object's action.
If the first object moves, then the second objects need to move in the same direction. If the first one rotates, then the second one rotates at the same angle in the second one's position.
I have tried adding events (moving,rotating) to the first selectable object, and then getting the required values from the first object and setting it to second object, but rotating is not working properly. My code is as follows:
imageOne.on('rotating', function (evt) { imageThree.angle = imageOne.getAngle(); });
var canvas = new fabric.Canvas('c');
var evented = false;
var rect1 = new fabric.Rect({
left: 50,
top: 60,
fill: 'blue',
width: 150,
height: 150,
});
var rect2 = new fabric.Rect({
left: 210,
top: 60,
fill: 'magenta',
width: 150,
height: 150,
selectable: false
});
canvas.add(rect1,rect2);
function rect1MouseDown(option){
this.mousesDownLeft = this.left;
this.mousesDownTop = this.top;
this.rect2Left = rect2.left;
this.rect2Top = rect2.top;
}
function rect1Move(option){
rect2.left = this.rect2Left+ this.left - this.mousesDownLeft ;
rect2.top = this.rect2Top+ this.top- this.mousesDownTop;
rect2.setCoords();
}
function rect1Rotating(options){
rect2.setAngle(this.angle);
}
register();
function register(){
if(evented) return;
rect1.on('moving', rect1Move);
rect1.on('mousedown', rect1MouseDown);
rect1.on('rotating', rect1Rotating);
evented = true;
}
function unRegister(){
rect1.off('moving');
rect1.off('mousedown');
rect2.on('rotating');
evented = false;
}
canvas {
border: blue dotted 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<button onclick='register()'>Register Event</button>
<button onclick='unRegister()'>Unregister Event</button><br>
<canvas id="c" width="400" height="400"></canvas>
You can use obj.setAngle() for version <1.7.19 and obj.rotate() for version 2 , to set angle to an object.

How to use keyboards event while editing text in fabricjs

Is there a way to listen to key events while you are editing a text? (in itext or textbox or whatever). Our goal is to be able to hit cmd-b or cmd-i to set the selected part of your text in bold or italic.
Thanks for your help!
DEMO
window.addEventListener("keydown",onKeyDown);
function onKeyDown(e){
if (event.which == 73 && event.ctrlKey ) {
//ctrl+i
makeItalic();
}
if (event.which == 66 && event.ctrlKey ) {
//ctrl+b
makeBold();
}
}
var canvas = new fabric.Canvas('canvas');
var text = 'FabricJS Is Awsome';
var itext = new fabric.IText(text, {
left: 100,
top: 100,
fontSize: 40,
fill: '#000'
})
canvas.add(itext);
canvas.setActiveObject(itext);
function makeItalic(){
itext.setSelectionStyles({fontStyle:'italic'});// set your property
canvas.renderAll();
}
function makeBold(){
itext.setSelectionStyles({fontWeight:'bold'});
canvas.renderAll();
}
.canvas-wrappter {
position: relative;
}
canvas {
border: 1px solid #000;
}
.itext {
width: 300px;
background: transparent;
position: absolute;
z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.16/fabric.min.js"></script>
<div class="canvas-wrapper">
<canvas id="canvas" width="500" height="500"></canvas>
</div>
setSelectionStyles(style) use this function to set your style.

Resources