I am trying to draw lines around polygon, It should draw different colour of line from one point to the next, I am stuck on attaching line to the last point of polygon, There are also red circles which are being created successfully on polygon corners, Lines are being drawn when box is moved with mouse, using 'modified' event
JSFiddle here
The issue is here:
var lastPoint = (i=>polygon.points.length)?0:i+1;
var fromX = transformedPoints[lastPoint].x;
var fromY = transformedPoints[lastPoint].y;
return new fabric.Line([p.x, p.y, 25, fromX],{
JS code
var canvas = new fabric.Canvas("c", {
selection: false
});
var polygon = new fabric.Polygon([
new fabric.Point(150, 50),
new fabric.Point(250, 50),
new fabric.Point(250, 150),
new fabric.Point(150, 150)
]);
polygon.on("modified", function() {
document.getElementById("p").innerHTML = JSON.stringify(this);
var matrix = this.calcTransformMatrix();
var transformedPoints = this.get("points")
.map(function(p) {
return new fabric.Point(
p.x - polygon.pathOffset.x,
p.y - polygon.pathOffset.y);
})
.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
var circles = transformedPoints.map(function(p) {
return new fabric.Circle({
left: p.x,
top: p.y,
radius: 3,
fill: "red",
originX: "center",
originY: "center",
hasControls: false,
hasBorders: false,
selectable: false
});
});
document.getElementById("l").innerHTML = JSON.stringify(transformedPoints);
var colors = ['#E5097F', '#00A0E3', '#009846', '#FECC00', '#000', '#000', '#000'];
var lines = transformedPoints.map(function(p, i) {
document.getElementById("r").innerHTML = JSON.stringify(p);
var lastPoint = (i => polygon.points.length) ? 0 : i + 1;
var fromX = transformedPoints[lastPoint].x;
var fromY = transformedPoints[lastPoint].y;
document.getElementById("r").innerHTML = fromX + ' - > ' + fromY;
return new fabric.Line([p.x, p.y, 25, fromX], {
stroke: colors[i],
strokeWidth: 10,
hasBorders: false,
strokeDashArray: [8, 13]
});
});
side_a = new fabric.Line([150, 0, 50, 0], {
stroke: "red",
strokeWidth: 10,
hasBorders: false
});
this.canvas.clear().add(this).add(side_a).add.apply(this.canvas, lines).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
});
canvas.add(polygon).renderAll();
UPDATE:
I am able to generate those lines by providing static values, for demo. before 'modified' event happens I have included some lines where it should go:
side_a = new fabric.Line([250, 50, 150, 50], {
stroke: "red",
strokeWidth: 10,
hasBorders: false
});
side_b = new fabric.Line([150, 150, 150, 50], {
stroke: "green",
strokeWidth: 10,
hasBorders: false
});
side_c = new fabric.Line([250, 150, 250, 50], {
stroke: "blue",
strokeWidth: 10,
hasBorders: false
});
side_d = new fabric.Line([150, 150, 260, 150], {
stroke: "green",
strokeWidth: 10,
hasBorders: false
});
canvas.add(polygon).add(side_a).add(side_b).add(side_c).add(side_d).renderAll();
Now just need to figure out how to create those dynamically. new JSFIDDLE HERE
UPDATE:
finally I was able to solve it by running in loop.
I was able to solve it using looping through the points and than generating lines:
var fromX = transformedPoints[i].x;
var fromY = transformedPoints[i].y;
return new fabric.Line([p.x, p.y , fromX, fromY], {
stroke: colors[i],
strokeWidth: 10,
hasBorders: true,
strokeDashArray: [20, 5]
});
Related
i am using fabricjs with reactjs and when the useEffect call i have initialize the canvas.
and draw a line with two circles top and bottom. when i pick image from computer and select over the lines the background image is removed.
`const refrenceLine = () => {
const canvas = canvasRef.current;
let isDraw = false;
const refrenceLineCircle1 = new fabric.Circle({
left: 50,
top: 50,
stroke: "black",
radius: 10,
fill: "",
transparentCorners: true,
});
refrenceLineCircle1.hasControls = false;
const refrenceCircle2 = new fabric.Circle({
left: 50,
top: 250,
stroke: "black",
radius: 10,
fill: "",
transparentCorners: true,
});
refrenceCircle2.hasControls = false;
const box1point = refrenceLineCircle1.getPointByOrigin("center", "bottom");
const box2point = refrenceCircle2.getPointByOrigin("center", "top");
// console.log("box1point.x1", box1point.x);
// console.log("box1point.y1", box1point.y);
// console.log("box2point.x2", box2point.x);
// console.log("box2point.y2", box2point.y);
const refrenceLineconnector = new fabric.Line(
[box1point.x, box1point.y, box2point.x, box2point.y],
{
stroke: "black",
strokeWidth: 2,
lockScalingX: true,
lockScalingY: true,
lockRotation: true,
hasControls: true,
hasBorders: true,
lockMovementX: true,
lockMovementY: true,
hasRotatingPoint: true,
}
);
refrenceLineconnector.hasControls = false;
refrenceLineCircle1.on("moving", function () {
console.log("here");
const connectPoint = this.getPointByOrigin("center", "bottom");
refrenceLineconnector.set({
x1: connectPoint.x,
y1: connectPoint.y,
});
});
refrenceCircle2.on("moving", function () {
const connectPoint = this.getPointByOrigin("center", "top");
refrenceLineconnector.set({
x2: connectPoint.x,
y2: connectPoint.y,
});
});
canvas.add(refrenceLineCircle1, refrenceCircle2, refrenceLineconnector);
canvas.on("mouse:down", function (e) {
isDraw = true;
console.log("at start", e.target?.fill);
// if (e.target.fill == "green") {
// alert("green circle is clecked");
// } else alert("red cirecle is cleiked");
});
canvas.on("mouse:up", function (e) {
if (!isDraw) return;
// console.log("after end", e.e);
console.log("refrenceLineconnector", refrenceLineconnector);
});
};`
Here is my code to add the pattern to the stroke of the moveable line.
when I try to move the line, the pattern remains in the same position. It should move inside the stroke according to the stroke's angle. Is there any way to adjust the stroke pattern?
When the color is applied to the normal stroke it works fine. Kindly someone suggests how can I rectify this problem. And if there is any other method to make a zigzag line on canvas that can move to and fro, can be resized, and can be rotated according to the requirement just like a normal line.
image used for pattern is attached with the file
window.canvas = canvas;
let pic = 'http://127.0.0.1:5500/sin-small.png'
function loadPattern(url) {
fabric.util.loadImage(url, function(img) {
let pattern = new fabric.Pattern({
source: img,
repeat: 'repeat-x'
});
console.log(pattern)
line.set('stroke', pattern)
canvas.renderAll();
});
}
var canvas = new fabric.Canvas('c', {
selection: true
});
var line = new fabric.Line([50, 50, 100, 100], {
fill: 'red',
stroke: 'red',
strokeWidth: 10,
selectable: true,
hasControls: false,
hasBorders: false,
centeredRotation: false,
centeredScaling: false,
//originX: 'center',
//originY: 'center'
});
var circle1 = new fabric.Circle({
radius: 5,
fill: 'green',
left: 45,
top: 45,
hasControls: false,
hasBorders: false,
name: 'circle1'
});
var circle2 = new fabric.Circle({
radius: 5,
fill: 'green',
left: 95,
top: 95,
hasControls: false,
hasBorders: false,
name: 'circle2'
});
canvas.on('object:moving', function (options) {
var objType = options.target.get('type');
var p = options.target;
if (objType == 'line') {
var _l = line.left;
var _t = line.top;
circle1.set({
'left': (line.calcLinePoints().x1 + _l),
'top': (line.calcLinePoints().y1 + _t)
});
circle1.line.set({
'x1': circle1.left,
'y1': circle1.top
});
circle1.line.setCoords();
circle2.set({
'left': (line.calcLinePoints().x2 + _l),
'top': (line.calcLinePoints().y2 + _t)
});
circle2.line.set({
'x2': circle2.left,
'y2': circle2.top
});
circle2.line.setCoords();
canvas.renderAll();
}
if (objType == 'circle') {
if (p.name == 'circle1') {
line.set({
x1: circle1.getCenterPoint().x, y1: circle1.getCenterPoint().y, selectable: true
});
} else {
if (p.name == 'circle2') {
line.set({
x2: circle2.getCenterPoint().x, y2: circle2.getCenterPoint().y, selectable: true
});
}
}
}
line.setCoords();
circle1.setCoords();
circle2.setCoords();
canvas.renderAll();
});
canvas.add(line);
loadPattern(pic);
circle1.line=line;
circle2.line=line;
canvas.add(circle1);
canvas.add(circle2);
canvas.renderAll();
i need an input type range in canvas for some purposes, i need to use that to change my fontsize. I already make the shape and also drag able, but the circle controller go beyond the line.
Just preview the bin to see what i mean. Jsbin
i want to limit the draging area to the line only like the input range works.
This is the documentation of KonvaJs library.
this is working, coded by Lavrton
Source
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var Track = new Konva.Line({
x: 44,
y: 55,
points: [60, 0, 0, 0, 0, 0, 0, 0],
stroke: '#BDC3C7',
strokeWidth: 6,
visible: true,
name: 'TrackLine',
lineCap: 'sqare',
lineJoin: 'sqare'
});
var TrackBall = new Konva.Circle({
x: 44,
y: 55,
stroke: '#D35400',
fill: '#ddd',
strokeWidth: 2,
name: 'TrackControl',
radius: 8,
draggable: true,
dragOnTop: false,
visible: true,
dragBoundFunc: function(pos) {
console.log(pos.x, Math.min(44, pos.x))
return {
x: Math.min(104, Math.max(44, pos.x)),
y: this.getAbsolutePosition().y
};
}
});
layer.add(Track);
layer.add(TrackBall);
stage.add(layer);
<script src="https://cdn.rawgit.com/konvajs/konva/0.10.0/konva.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container" class="CanCont"></div>
In kintic JS of HTML5 I am trying to vanish lines on mouse over it works fine when I am doing it with variables:
http://jsfiddle.net/Vbwta/
var layer = new Kinetic.Layer();
lines0= new Kinetic.Line({
points: [73+10, 70+10, 340+10, 23+10],
stroke: 'red',
strokeWidth: 7,
});
lines0.on('mouseover', function() {
lines0.hide();
layer.draw();;
});
lines1= new Kinetic.Line({
points: [53, 50, 320, 03],
stroke: 'red',
strokeWidth: 7,
});
lines1.on('mouseover', function() {
//document.body.style.cursor = 'pointer';
lines1.hide();
layer.draw();;
});
But the same thing does not work properly when I am using array:
http://jsfiddle.net/uNak5/
var lines= new Array();
lines[0]= new Kinetic.Line({
points: [73+10, 70+10, 340+10, 23+10],
stroke: 'red',
strokeWidth: 7,
});
lines[0].on('mouseover', function() {
lines[a].hide();
layer.draw();;
});
lines[1]= new Kinetic.Line({
points: [53, 50, 320, 03],
stroke: 'red',
strokeWidth: 7,
});
lines[1].on('mouseover', function() {
//document.body.style.cursor = 'pointer';
lines[1].hide();
layer.draw();;
});
layer.add(lines[0]);
layer.add(lines[1]);
http://jsfiddle.net/uNak5/1/
I updated the code, you had the reference to your array item set to
lines[a]
rather that
lines[0]
in your listener
.on('mouseover', function());
As in example http://openlayers.org/dev/examples/graphic-name.html ...
I tried drawing my feature geometry as a flag but I realized that OpenLayers always uses the centroid of the geometry to place the feature at the specified point(latitude/longitude), whereas I wish the base of the flag to be placed at the specified point. Changing the value of Renderer.symbol did not make any effect neither did the graphicXOffset/graphicYOffset.
//my flag geometry
OpenLayers.Renderer.symbol.flag = [0, 0, 0, 140, 120, 140, 120, 60, 4, 60, 4, 0, 0, 0];
//create vector layer with default and select styles
myVectorLayer = new OpenLayers.Layer.Vector("Flag Geometry", {
renderers: renderer,
isBaseLayer: true,
graphicName: flag,
rotation: 180,
pointRadius: 15,
projection: new OpenLayers.Projection("EPSG:900913"),
styleMap: new OpenLayers.StyleMap({
"default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
fillColor: "red",
strokeColor: "gray",
label: "${label}",
fontColor: "${favColor}",
fontSize: "12px",
fontFamily: "Courier New, monospace",
fontWeight: "bold",
labelYOffset: 2 //for flag
}, OpenLayers.Feature.Vector.style["default"])),
"select": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
}, OpenLayers.Feature.Vector.style["select"]))
})
});
var flag = new OpenLayers.Geometry.Point(latitude, longitude);
var flagFeature = new OpenLayers.Feature.Vector(flag);
myVectorLayer.addFeatures([flagFeature]);
To overcome this base point problem I changed the drawing method as follows:
myVectorLayer = new OpenLayers.Layer.Vector("Flag Geometry", {
renderers: renderer,
isBaseLayer: true,
projection: new OpenLayers.Projection("EPSG:900913"),
styleMap: new OpenLayers.StyleMap({
"default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
fillColor: "red",
strokeColor: "gray",
label: "${label}",
fontColor: "${favColor}",
fontSize: "12px",
fontFamily: "Courier New, monospace",
fontWeight: "bold",
labelYOffset: 2 //for flag
}, OpenLayers.Feature.Vector.style["default"])),
"select": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
}, OpenLayers.Feature.Vector.style["select"]))
})
});
var pointList = [];
var xs = [0, 0, 240, 240, 8, 8, 0];
var ys = [0, 280, 280, 120, 120, 0, 0];
for(var p=0; p<6; ++p) {
var newPoint = new OpenLayers.Geometry.Point(camera.get('latitude') + xs[p],
camera.get('longitude') + ys[p]);
pointList.push(newPoint);
}
pointList.push(pointList[0]);
var linearRing = new OpenLayers.Geometry.LinearRing(pointList);
var flagVector = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon([linearRing]));
flagVector.attributes= {
label: 'label',
favColor: 'blue', //favorite color
align: "cm"
};
myVectorLayer.addFeatures([flagVector]);
This though will make the geometry zoom with map zoom not as the previous way.