Pattern not applying on line object fabricjs - 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>

Related

Fabric.js: dashed line with clipping looks different on large canvas size

I use a clipping area with fabric.js to create a graph. However, the grid lines look different on a canvas size bigger than about 1000px. It only occurs with imageSmoothingEnabled: false. See the image. Note: the size of the frames have nothing to do with the size of the canvas.
To create the grid lines, I create one original that is wider than the area, and then clone them. The cloned lines are added to the clipArea object. Here is the relevant code.
HTML:
<canvas id="canvas" width="966" height="520"></canvas>
Javascript:
var canvas = new fabric.StaticCanvas('canvas', {
imageSmoothingEnabled: false
});
var rect = new fabric.Rect({
originX: 'left',
originY: 'top',
fill: 'transparent',
width: x1-x0,
height: y1-y0
});
var clipArea = new fabric.Group([rect], {
originX: 'left',
originY: 'top',
width: canvas.width*2,
height: canvas.height*2,
left: -canvas.width,
top: -canvas.height
});
rect=clipArea.item(0)
rect.set({left: x0,top: y0});
clipArea.clipPath = rect;
canvas.add(clipArea);
var yline = new fabric.Line([0, 0, 1200, 0], {
originX: 'left',
originY: 'center',
stroke: myFrameColor,
strokeWidth: 2,
strokeDashArray: [1, 3.4]
});
// clipArea.add(yline)
Of course I could draw the gridlines in a different way without using clipping, but I need a clipping area anyway. And I'd like to understand why this is happening.

Create a clipping mask using an object in Fabric.js

I'm trying to create a T-Shirt editor using Fabric. I set a shirt as a background image on the canvas. Now I'm trying to get an area in the middle of the T-shirt that will act as a clipping mask. I only want objects that are inside this area to be visible.
Here's my code: http://jsfiddle.net/mtb2p3Lx/4/
var canvas = new fabric.Canvas('c');
// set background
fabric.Image.fromURL('https://qstomizr.s3.amazonaws.com/11102-9LDAQLKA1585254870.5083.jpg', (img) => {
canvas.setBackgroundImage(img, null, {
originX: 'center',
originY: 'center',
top: canvas.getCenter().top,
left: canvas.getCenter().left,
stroke: 'black',
strokeWidth: 1,
});
canvas.renderAll();
});
// set masking area
var area = new fabric.Rect({
originX: 'center',
originY: 'center',
top: this.canvas.getCenter().top,
left: this.canvas.getCenter().left + 10,
width: 250,
height: 300,
selectable: false,
fill: 'transparent',
stroke: 'black',
strokeWidth: 2,
});
canvas.add(area)
// set example rect
var rect = new fabric.Rect({
originX: 'center',
originY: 'center',
top: this.canvas.getCenter().top + 50,
left: this.canvas.getCenter().left + 150,
height: 100,
width: 100,
fill: 'pink',
});
canvas.add(rect)
I tried adding a clip path to the area rect, also tried playing around with globalCompositeOperation, but I couldn't get anything to work without having to sacrifice the background image.
Is there a way to get the transparent area rect to act as a clipping mask for the other objects in the canvas?
As you can see on this site https://printio.ru/tees/new_v2. For implementing background image was used img tag without setBackgroundImage. And I make an example for you here
https://jsfiddle.net/RamanNikitsenka/4suna7yo/1/

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();
}

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
});

kinetic js zindex

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

Resources