kinetic js zindex - z-index

Can't quite figure out how to layer these objects with kenetic js, I want circle to be on top of circle2. Am I writing 'circle.setZIndex();' improperly? This is breaking the script.
jsfiddle with .setZIndex lines commented out: http://jsfiddle.net/ZfuDs/
function writeMessage(messageLayer, message) {
var context = messageLayer.getContext();
messageLayer.clear();
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var shapesLayer = new Kinetic.Layer();
var messageLayer = new Kinetic.Layer();
var circle2 = new Kinetic.Circle({
x: 360,
y: stage.getHeight() / 2,
radius: 90,
fill: 'orange',
stroke: 'black',
strokeWidth: 4
});
circle2.setZIndex(3);
var circle = new Kinetic.Circle({
x: 380,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
circle.setZIndex(2);
shapesLayer.add(circle);
shapesLayer.add(circle2);
stage.add(shapesLayer);
stage.add(messageLayer);

You can try to add circle2 shape first and then add circle shape second
shapesLayer.add(circle2);
shapesLayer.add(circle);
instead of
shapesLayer.add(circle);
shapesLayer.add(circle2);
Try this one http://jsfiddle.net/ZfuDs/1/

it appears that you can't call the z-index functions before the object is added to a layer I get:
TypeError: this.parent is undefined
this.parent.children.splice(index, 1);
I don't get an error anymore, but the setZIndex() method doesn't seem to work even so, but
circle.moveToTop() does work, check http://jsfiddle.net/ZfuDs/3

Related

How to get top left of an object inside group fabricjs

How can I get canvas-relative position (top, left) of triangle inside an group as bellow image?
I followed this topic: How to get the canvas-relative position of an object that is in a group? but it only right when group is not rotated.
Working example you may find here: http://jsfiddle.net/mmalex/2rsevdLa/
Fabricjs provides a comprehensive explanation of how transformations are applied to the objects: http://fabricjs.com/using-transformations
Quick answer: the coordinates of an object inside the group is a point [0,0] transformed exactly how the object in the group was transformed.
Follow my comments in code to get the idea.
// 1. arrange canvas layout with group of two rectangles
var canvas = new fabric.Canvas(document.getElementById('c'));
var rect = new fabric.Rect({
width: 100,
height: 100,
left: 50,
top: 50,
fill: 'rgba(255,0,0,0.25)'
});
var smallRect = new fabric.Rect({
width: 12,
height: 12,
left: 150 - 12,
top: 50 + 50 - 12 / 2 - 10,
fill: 'rgba(250,250,0,0.5)'
});
// 2. add a position marker (red dot) for visibility and debug reasons
var refRect = new fabric.Rect({
width: 3,
height: 3,
left: 100,
top: 100,
fill: 'rgba(255,0,0,0.75)'
});
var group = new fabric.Group([rect, smallRect], {
originX: 'center',
originY: 'center'
});
canvas.add(group);
canvas.add(refRect);
canvas.renderAll();
// 3. calculate coordinates of child object in canvas space coords
function getCoords() {
// get transformation matrixes for object and group individually
var mGroup = group.calcTransformMatrix(true);
// flag true means that we need local transformation for the object,
// i.e. how object is positioned INSIDE the group
var mObject = smallRect.calcTransformMatrix(true);
console.log("group: ", fabric.util.qrDecompose(mGroup));
console.log("rect: ", fabric.util.qrDecompose(mObject));
// get total transformattions that were applied to the child object,
// the child is transformed in following order:
// canvas zoom and pan => group transformation => nested object => nested object => etc...
// for simplicity, ignore canvas zoom and pan
var mTotal = fabric.util.multiplyTransformMatrices(mGroup, mObject);
console.log("total: ", fabric.util.qrDecompose(mTotal));
// just apply transforms to origin to get what we want
var c = new fabric.Point(0, 0);
var p = fabric.util.transformPoint(c, mTotal);
console.log("coords: ", p);
document.getElementById("output").innerHTML = "Coords: " + JSON.stringify(p);
// do some chores, place red point
refRect.left = p.x - 3 / 2;
refRect.top = p.y - 3 / 2;
canvas.bringToFront(refRect);
canvas.renderAll();
}
a very simple way to get topleft is
var cords = object._getLeftTopCoords();
cords.x and cord.y will give you the result

Pattern not applying on line object fabricjs

I am facing as issue using fabricjs as pattern is not applying on line object. It fills the object property with pattern images but is not showing pattern on line. jsfiddle ins attached.
var line = new fabric.Line([10, 25, 300, 25], {
stroke: 'red',
strokeWidth: 5,
selectable: true,
left: 0,
top: 0
});
canvas.add(line);
fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function (img) {
line.setPatternFill({
source: img,
repeat: 'repeat'
});
canvas.renderAll();
});
console.log(line);
Because Fabric js setPatternFill only apply pattern to the fill property of object.But line object not have a fill property,only have a stroke so we apply pattern differently like new fabric.Pattern
var canvas = new fabric.Canvas("c")
var line = new fabric.Line([10, 25, 300, 25], {
stroke: 'red',
fill:"red",
strokeWidth: 10,
selectable: true,
left: 0,
top: 0
});
canvas.add(line);
fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function (img) {
line.stroke = new fabric.Pattern({
source: img,
repeat: 'repeat'
});
canvas.renderAll();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="c"></canvas>

Fabric.js accessing to group in a function

Hello guy and thanks so much for your help.
I am a newbie in fabric.js and I have a basic question.
I create a group of 3 objects in a function.
I want to change property of an object of this group in another function.
And more generally it will be really useful if someone can explain to me how to access to another object of a group?
I don't know how to do that.
function groupit() //Works {
var circle1 = new fabric.Circle({
radius: 50,
fill: 'red',
left: 0
});
var circle2 = new fabric.Circle({
radius: 50,
fill: 'green',
left: 100
});
var circle3 = new fabric.Circle({
radius: 50,
fill: 'blue',
left: 200
});
var group = new fabric.Group([ circle1, circle2, circle3 ], {
left: 200,
top: 100
});
canvas.add(group);
}
function groupchg() //Does not work {
canvas.setActiveGroup(group);
group.add(new fabric.Rect({
left: 100,
top: 100,
originX: 'center',
originY: 'center'
}));
}
Because you call canvas.setActiveGroup(group); in your function groupchg(), and property group is probably null. Can fix if define group property out of function groupit().
Ok found solution.
To access to specific object of a group i use this code :
function groupchg() {
//console.log(canvas.getActiveGroup());
canvas.setActiveObject(canvas._objects[0]._objects[1]);
var activeObj = canvas.getActiveObject();
activeObj.setFill('red');
activeObj.set({left: 30,top:150});
canvas.renderAll();
}

Put text Inside Kinetic.Circle

I'm trying to put text inside a circle from Kinetic.Circle but i can't find the right answer. I have the following code:
var circle = new Kinetic.Circle({
x: 30,
y: stage.getHeight() / 2,
radius: 20,
fill: 'red',
stroke: 'black',
strokeWidth: 2,
});
var text = new Kinetic.Text({
text: 'A',
fontSize: 10,
fontFamily: 'Calibri',
width: 5,
fill: '#000'
});
layer.add(circle);
layer.add(texto);
stage.add(layer);
Any ideas how to accomplish this please?
You can position the text like this so that you dont have to provide the x & y coordinates.
text.setX( circle.getX() - text.getWidth()/2 );
text.setY( circle.getY() - text.getHeight()/2 );

Moving three circles to another position slowing down movement (KineticJS)

I am trying to move three circles, after they gradually fade in, to the top left of the page so that they overlap on a box. At the moment, I set a timeout, but it only works for the first circle and the movement is really fast. How can I move them all as a group and slow down the movement?
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
background-color: #CCCCCC;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head>
<body>
<div id="container"></div>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.1-beta2.js">
</script>
<script>
var fadeIn = function(shape) {
var o = shape.getOpacity();
o = o + 0.05 >=0.5 ? 0.5 : o + 0.05;
shape.setOpacity(o);
shape.getLayer().draw();
if(o !== 0.4) {
setTimeout(function() {
fadeIn(shape).delay(3000*3);
}, 720);
}
};
var stage = new Kinetic.Stage({
container: 'container',
width: 800,
height: 700
//width: 578,
//height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: '#CCCCCC',
stroke: 'yellow',
strokeWidth: 8,
opacity: 0.1
});
circle.hide();
setTimeout(function() {
circle.show();
fadeIn(circle).delay(3000*3);
}, 1720);
layer.add(circle);
var circle2 = new Kinetic.Circle({
x: stage.getWidth() / 2.1,
y: stage.getHeight() / 2.1,
radius: 70,
fill: '#CCCCCC',
stroke: 'yellow',
strokeWidth: 8,
opacity: 0.1
});
circle2.hide();
setTimeout(function() {
circle2.show();
fadeIn(circle2).delay(3000*3);
}, 5600);
// add the shape to the layer
layer.add(circle2);
var circle3 = new Kinetic.Circle({
x: stage.getWidth() / 2.2,
y: stage.getHeight() / 2.2,
radius: 70,
fill: '#CCCCCC',
stroke: 'yellow',
strokeWidth: 8,
opacity: 0.1
});
circle3.hide();
setTimeout(function() {
circle3.show();
fadeIn(circle3).delay(3000*3);
}, 12000);
// add the shape to the layer
layer.add(circle3);
// var boxGroup = new Kinetic.Group({
//x: 10,
//y: 10,
//draggable: true
//});
var boxGroup = new Kinetic.Group({
x: -250,
y: -250,
draggable: true
});
var box = new Kinetic.Rect({
x: 10,
y: 10,
width: 100,
height: 100,
fill: '#CCCCCC',
stroke: 'black'
});
boxGroup.add(box);
layer.add(box);
layer.add(boxGroup);
// add the layer to the stage
stage.add(layer);
setTimeout(function() {
circle.moveTo(boxGroup).delay(5000*3);
circle2.moveTo(boxGroup).delay(5000*3);
circle3.moveTo(boxGroup).delay(5000*3);
}, 24000);
</script>
</body>
http://jsfiddle.net/SAnFM/9/
KineticJS has a great transitionTo() function which you can call. It can animate any numerical property, like position or opacity. I created a fiddle to show this, as setTimeout is a bit of an ancient function compared to what is built into the browsers nowadays with RequestAnimationFrame (all major browsers implement this nowadays and KineticJS has a built in fallback like most other libraries do)
I cleaned up your code a little, removing comments and added an extra circle, for fun.
but really all you need is:
myShape.transitionTo({shape configuration, duration});
For example:
circle.transitionTo({
x: box.getX(), //coordinates to transition to
y: box.getY(),
opacity: 1,
duration: 1 // length of time for this animation in seconds, REQUIRED for animation to work
});

Resources