Calculating line coordinates in Fabric.js - javascript

I am developing a self graphing program which draws a binary tree using Fabric.js. So far I have added draw node functions and now I am working on drawing links between the nodes, however the coordinates isn't getting calculated properly. Can anybody help me to point out what the error is? The function(node1,node2,angle) draws a node2 at 200pixels away from node1 at angle passed. I found the start points of line by following the same method I founded Circle center but just by adding circle's radius which is 20 in my case instead of 200 pixels. The end points were calculated by subtracting 20 from 200 and Hence using value 180.
This is the code that I wrote:
Code:
function addNode(node1,node2,angle)
{
var intialx=parseInt(node1.get('left'));
var initialy=parseInt(node1.get('top'));
if(angle<180)
{
var pointx =Math.abs(Math.cos(angle*Math.PI/180)*200+intialx);
var pointy=Math.abs(Math.sin(angle*Math.PI/180)*200-initialy);
var initiallinex=Math.abs(Math.cos(angle*Math.PI/180)*20+intialx);
var initialliney=Math.abs(Math.sin(angle*Math.PI/180)*20-initialy);
var finallinex=Math.abs(Math.cos(angle*Math.PI/180)*180+intialx);
var finalliney=Math.abs(Math.sin(angle*Math.PI/180)*180-initialy);
}
else
{
var pointx =Math.abs(Math.cos(angle*Math.PI/180)*200+intialx);
var pointy=Math.abs(Math.sin(angle*Math.PI/180)*200+initialy);
var initiallinex=Math.abs(Math.cos(angle*Math.PI/180)*20+intialx);
var initialliney=Math.abs(Math.sin(angle*Math.PI/180)*20+initialy);
var finallinex=Math.abs(Math.cos(angle*Math.PI/180)*180+intialx);
var finalliney=Math.abs(Math.sin(angle*Math.PI/180)*180+initialy);
}
var x=new fabric.Circle({ radius:20,originX: 'center', originY: 'center',fill:'red'});
var value1=String(node2);
var text= new fabric.Text(value1, {fontSize: 10, originX: 'center', originY: 'center'});
var group = new fabric.Group([ x, text ], {left:pointx, top: pointy, angle:0});
canvas.add(group);
canvas.add(new fabric.Line([initiallinex, initialliney, finallinex, finalliney], {
stroke: 'red'
}));
return group;
}
Output:
enter image description here

Related

SVG.js line marker-mid

im trying to put the marker-mid on the line element, im using SVG.js. For example im using this code:
var draw = SVG('yourdivid');
var line = draw.line( 100, 100, 0, 0).move(20, 20);
line.stroke({ color: '#000', width: 2};
now how can i put the marker at the mid of this line using the marker-mid?
i read the doc of svg.js and also this" https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/marker-mid#Examples"
they say that you can use the marker-mid element also with the line, i know that this marker works with the path element, but i need to use it with a line, can you help me please?
thank you for your help
You could just work out the mid point of the line yourself and draw a circle at that point.
var start = [100, 100];
var end = [0, 0];
function midPoint(start, end) {
return [
(start[0] + end[0]) / 2,
(start[1] + end[1]) / 2
];
}
var lineGroup = svg.group();
lineGroup.line(start[0][0], start[0][1], end[0][0], end[0][1]);
var dot = lineGroup.circle(3);
var mid = midPoint(start, end);
dot.cx(mid[0]);
dot.cy(mid[1]);
marker-mid does not work on lines. To have start and end markers, this code would do it:
var draw = SVG('yourdivid');
draw.line( 100, 100, 0, 0)
.move(20, 20)
.stroke({ color: '#000', width: 2})
.marker('start', 10, 10, function(add){
add.circle(10).center(5,5)
})
However, to have markers at the mid of a line see p0wdr.com's answer

Paper.js - Clipping opacity for paths outside of area

I have a simple rectangle that forms the clipping area for all shapes added to the canvas, which is working great:
var area = new paper.Rectangle(
100, 100, 300, 120
);
var path = new paper.Path.Rectangle(area);
group.addChild(path);
group.clipped = true;
What I'm trying to achieve is instead of hiding the paths that fall outside of this area, they are shown with a slight opacity, something like:
Thanks in advance for any help and suggestions.
This is not a simple way as clipped, you might do it by using method intersect.
Please try this code.
// SET INITIAL
var area = new paper.Path.Rectangle(100, 100, 300, 220);
area.fillColor = 'yellow'
area.opacity = 0.2
var circle1 = new paper.Path.Circle({
center:[150, 150],
radius: 100,
fillColor: 'red'
})
// OPACITY CLIPPING
var circle2 = circle1.intersect(area)
circle1.opacity = 0.2

Kinetic.js draw text inside wedge (with rotation)

Just started using Kinetic.js yesterday. I want to draw some text (a label) inside a wedge so that it's placed inside the wedge with a rotation relative to the wedges' angle.
Like so:
Here's my code:
var numSegments = 5; // Number of wedges in circle
var endPos = 0;
//Center of the div container
var center = document.getElementById('canvas_container').offsetWidth * 0.5;
var centerY = document.getElementById('canvas_container').offsetHeight * 0.5;
for (var i = 0; i < numSegments; ++i) {
//Wedge + corresponding label stored in their own group
var group = new Kinetic.Group();
var wedge = new Kinetic.Wedge({
radius: center,
x: center,
y: centerY,
fill: colors[i],
stroke: '#aaaaff',
strokeWidth: 2,
angleDeg: 360 / numSegments,
rotationDeg: endPos,
});
var label = new Kinetic.Label({
x : wedge.getX(),
y : wedge.getY(),
//The rotation value is where I assume I'm going wrong, this
//Is one of many values i've tried.
rotation : (endPos == 0) ? (360 / numSegments) * 0.5 : endPos
});
label.add(new Kinetic.Text({
text : titles[i],
fontFamily: 'Calibri',
fontSize: 26,
fill : 'white',
align: 'center',
listening: false
}));
group.add(wedge);
group.add(label);
WedgeLayer.add(group);
endPos += 360 / numSegments;
}
I've hit a brick wall with this and am looking for anyone to share any insight into how to achieve the desired outcome..
So far the above results are producing this:
Any help would be greatly appreciated, cheers.
A Demo: http://jsfiddle.net/m1erickson/fu5LP/
You calculate the text offset and rotation angle like this:
Calculating the text rotation angle
Track the accumulated angle for each new wedge you add and use that accum. angle to set the text angle.
Adjusting the angle for various accumulated angles helps keep the text from appearing upside down.
If the accumulated angle is between 90 & 270 degrees then set the text angle as the accumulated angle minus 180.
If the accumulated angle is <90 or >270 then set the text angle as the accumulated angle.
Setting the text offset
The offset depends on the radius of the wedge.
But again the offset is adjusted based on the accumulated angle
If the accumulated angle is between 90 & 270 degrees then set the text offsetX to approximately the wedge radius minus 10.
If the accumulated angle is <90 or >270 then set the text offset to approximately negative half of the wedge radius.
Example code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var cx=175;
var cy=175;
var wedgeRadius=140;
var accumAngle=0;
var center = new Kinetic.Circle({
x:cx,
y:cy,
radius:5,
fill: 'red'
});
layer.add(center);
for(var i=0;i<12;i++){
newTextWedge(30,"Element # "+i);
}
function newTextWedge(angle,text){
var wedge = new Kinetic.Wedge({
x: cx,
y: cy,
radius: wedgeRadius,
angleDeg: angle,
stroke: 'gray',
strokeWidth: 1,
rotationDeg:-accumAngle+angle/2
});
layer.add(wedge);
wedge.moveToBottom();
if(accumAngle>90 && accumAngle<270){
var offset={x:wedgeRadius-10,y:7};
var textAngle=accumAngle-180;
}else{
var offset={x:-50,y:7};
var textAngle=accumAngle;
}
var text = new Kinetic.Text({
x:cx,
y:cy,
text:text,
fill: 'red',
offset:offset,
rotationDeg:textAngle
});
layer.add(text);
layer.draw();
accumAngle+=angle;
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Fabric.js: Find the center of an object (rect) in a group

I need to find the center point of an object that has been placed into a group. Things l have tried:
• getCenterPoint(): returns the center point as if the object were at 0,0.
• Calculating the center point using getTop() and getLeft() of both the group and the object. Unfortunately while the group values work find the object returns negative values.
• Calculated the values using heights/widths of objects. This gets close in the case listed below, but that’s only because of the very specific properties of my example, and would not generalize.
The object below is what I’m currently working with, specifically I’m looking to find the center of rect2:
// create a rectangle object
var rect = new fabric.Rect({
top: 10,
fill: 'white',
stroke: 'black',
width: 20,
height: 20
});
// create a rectangle object
var rect2 = new fabric.Rect({
top: 10,
left: 20,
fill: 'white',
stroke: 'black',
width: 20,
height: 20
});
var line = new fabric.Line([ 20, 20, 40, 20],
{
top: 0,
left: 0,
stroke: 'black'
});
var group = new fabric.Group([ rect, rect2, line ],{
top: 100,
left: 100,
hasRotatingPoint: false
});
You can still use obj.getCenterPoint() on objects that have been added to a group; however, adding an object to a group removes the getCenterPoint method from the original obj reference.
If you reassign the obj references like below, you can then use getCenterPoint on each of them.
var allObjs = group.getObjects(),
rect1 = allObjs[0],
rect2 = allObjs[1],
line = allObjs[2];
return rect2.getCenterPoint();
Here is a working example: https://jsfiddle.net/ns9zLxeu/25/
Use something like
items = group._objects;
Run a loop in items of group, find your object, and get the co-ordinates of object inside a group.
eg : items[i].oCoords.tr.x
the rest is mathematics , mid point of tr.x and br.x = center x
similarly find y.
if you want to find the center to canvas : add group.top, group.left to these values.
Here is the math that I used to get the center of a given Rect
var x1 = e.target.oCoords.oCoords.mt.x;
var y1 = e.target.oCoords.oCoords.mt.y;
var x2 = e.target.oCoords.oCoords.mb.x;
var y2 = e.target.oCoords.oCoords.mb.y;
var centerX = (x1 + x2) / 2;
var centerY = (y1 + y2) / 2;
Then in my case I used the center coor to create a Line using:
var line = makeLine([centerx, centery, 250, 175]);
canvas.add(line);

Drawing in particular area of HTML5 canvas

If a lot of my drawings are going to be within a particular area of my larger canvas (in this case, in the center), is there a way to just say that you're working within that particular 'sub-canvas' instead of having to add/subtract the margins every time you want to draw? It just makes my code look a lot more complicated every time I'm specifying coordinates.
You can change the coordinates' origin using translate().
First, save the original origin using save(). Then, find the origin that suits the centre of your screen's drawing area and call translate(x, y). Do your drawing, and then use restore() to get your previous origin back.
jsFiddle.
Kinetic.js, a popular library for Canvas allows you to create a Group layer. You can specify the x, y coordinates, height and width of this Group. You can also add shapes and draw other things within this group.
Here's and example:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var shapesLayer = new Kinetic.Layer();
/*
* create a group which will be used to combine
* multiple simple shapes. Transforming the group will
* transform all of the simple shapes together as
* one unit
*/
var group = new Kinetic.Group({
x: 220,
y: 40,
rotationDeg: 20
});
var colors = ['red', 'orange', 'yellow'];
for(var n = 0; n < 3; n++) {
// anonymous function to induce scope
(function() {
var i = n;
var box = new Kinetic.Rect({
x: i * 30,
y: i * 18,
width: 100,
height: 50,
name: colors[i],
fill: colors[i],
stroke: 'black',
strokeWidth: 4
});
group.add(box);
})();
}
shapesLayer.add(group);
stage.add(shapesLayer);
Here's a tutorial on how to add Groups
You can use drawimage to draw an offscreen canvas to a certain part of another canvas.
Create a new canvas object and draw all your stuff to that. In the end draw that canvas to your onscreen canvas with drawimage at some coordinates.

Categories

Resources