Using clicking on canvas to get coordinates to draw lines and anchor circles

Code below is from  http://fabricjs.com/stickman and it is using fabrics.js library. (try to drag circle by pressing on mouse and moving)

Now coordinates for lines and circles are set by code. My goal is to set coordinates by clicking on canvas.

First click will be start and to determinate the end of polyline I need to use double click. I did try some options until now but i hope this one will be okay, as it has option to move lines by anchor circle. once the polyline has already been created for editing purposes.

Am sure i will have to use on click event and on double click event.  So when i will click on fist point i will get circle. Next click will give me the second  circle and the line between them and so on until double click. For now i have only one restriction and that is not to generate another circle, if i am clicking on existing  circle.

What would be the logic to get coordinates by clicking on canvas and to draw while clicking ?





 var line1,line2,line3,line4 ; 
function createObject(){  

fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

function makeCircle(left, top, line1, line2, line3, line4) {
    var c = new fabric.Circle({
      left: left,
      top: top,
      strokeWidth: 5,
      radius: 12,
      fill: '#fff',
      stroke: '#666'
    });
    c.hasControls = c.hasBorders = false;

    c.line1 = line1;
    c.line2 = line2;
    c.line3 = line3;
    c.line4 = line4;

    return c;
  }
 
 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
      selectable: false
    });
  }

  var line1 = makeLine([ 250, 125, 300, 175 ]),
      line2 = makeLine([ 300, 175, 350, 225 ]),
      line3 = makeLine([ 350, 225, 400, 275]),
      line4 = makeLine([ 400, 275, 450, 325]);

  canvas.add(line1, line2, line3, line4);
  
   canvas.add(
    makeCircle(line1.get('x1'), line1.get('y1'), null,line1),
    makeCircle(line1.get('x2'), line1.get('y2'), line1,line2),
    makeCircle(line2.get('x2'), line2.get('y2'), line2,line3),
    makeCircle(line3.get('x2'), line3.get('y2'), line3,line4),
    makeCircle(line4.get('x2'), line4.get('y2'), line4)
  );

    }               
document.getElementById("clickMe").onclick = createObject;


var moveHandler = function (evt) {
    var obj = evt.target;

    obj.line1 && obj.line1.set({ 'x2': obj.left, 'y2': obj.top });
    obj.line2 && obj.line2.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line3 && obj.line3.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line4 && obj.line4.set({ 'x1': obj.left, 'y1': obj.top });
    canvas.renderAll();
/}
canvas.on('object:moving', moveHandler);

Open in new window

Ivan GolubarAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ivan GolubarAuthor Commented:
I want as first to draw line, then i will add also circles.
So, next code should not do anything at first click and then on second click draw line from first click point to second one.

To get there I have as first resolve next:
why var posX1=0;
is then undefined  inside canvas on mouse down function?
(pleas check attached picture)


var line1=[ ];

 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
     //selectable: false
    });
 }
 
var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;
canvas.on('mouse:down', function(e) {
  posX1 = posX2;
  posY1 = posY2;
  var pointer = canvas.getPointer(e.e);
  var posX2 = pointer.x;
  var posY2 = pointer.y;
  
  if (lineCount!=0){
  line1[lineCount] = makeLine([posX1, posY1, posX2, posY2 ]);
  canvas.add(line1[lineCount]);
  } 
     lineCount=lineCount+1;
 }

Open in new window

linecor.png
0
Leonidas DosasCommented:
Could you post all the code (html+js) in a attached file?
0
Ivan GolubarAuthor Commented:
I can't find link to online fabric library.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">


<script src="https://can't find /fabric.min.js" ></script
 
<style>



</style>

<script>
var canvas = new fabric.Canvas('c');
 
  
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';



var line1=[ ];

 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
     //selectable: false
    });
 }


var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;
canvas.on('mouse:down', function(e) {
  posX1 = posX2;
  posY1 = posY2;
  var pointer = canvas.getPointer(e.e);
  var posX2 = pointer.x;
  var posY2 = pointer.y;
  
  if (lineCount!=0){
  line1[lineCount] = makeLine([posX1, posY1, posX2, posY2 ]);
  canvas5.add(line1[lineCount]);
  }
  
 });
</script>
</head>
<body>
       <canvas  id="c" width="1060" height="550"  > 

 
</div>
</body></html>

Open in new window

0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

Leonidas DosasCommented:
Check this script:
<script>
var canvas = new fabric.Canvas('c');
 
  
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';



var line1=[ ];

 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
     //selectable: false
    });
 }


var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;

 canvas.on('mouse:down', function(e) {
 if(lineCount===0){
  var pointer = canvas.getPointer(e.e);
   posX2 = pointer.x;
   posY2 = pointer.y;
  lineCount++
  return;
  }else{
   var pointer = canvas.getPointer(e.e);
   posX1=pointer.x;
   posY1 = pointer.y;
   line1 = makeLine([posX1, posY1, posX2, posY2 ]);
   canvas.add(line1);
   lineCount=0;
  } 

  
  
 });
 
</script>

Open in new window

0
Ivan GolubarAuthor Commented:
I have got the mistake. Sorry.

var posX2 = pointer.x;
  var posY2 = pointer.y;


I get lines now.
0
Leonidas DosasCommented:
Is it works now?
0
Ivan GolubarAuthor Commented:
Yes. I will now go on with drawing of circles.
0
Ivan GolubarAuthor Commented:
I had to get back to my previous code, because your code is doing, separate lines, but i need polyline which continues until i make a double click (check the begging of this question). I did add also circles between lines to have the anchor point for move handler.
Check the second attached code. When circles are pressed and moved lines should follow them. Under point 1 is original code from first post of this question. under point 2 is my try, but unsuccessful and under 3  the same as 2. With next  error:
Uncaught TypeError: Cannot read property '0' of undefined for line 19 of second code snippet.

To recapitulate:
 Now i am missing
1 double click to end the polyline.
2 move handler
3 check the attached picture: I don't want to ses line in circle  


var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;
canvas.on('mouse:down', function(e) {
 posX1 = posX2;
  posY1 = posY2;
  var pointer = canvas.getPointer(e.e);
   posX2 = pointer.x;
   posY2 = pointer.y;
  
     var RP = document.getElementById("RadioPol").checked;
  
  if (RP) {
      
       if (lineCount!=0){
       line1[lineCount] = makeLine([posX1, posY1, posX2, posY2 ]);
       canvas.add(line1[lineCount]);
       } 
 
      if (lineCount==0){canvas.add(makeCircle( posX2, posY2, null));}
      if (lineCount>0){canvas.add( makeCircle(line1[lineCount].get('x2'), line1[lineCount].get('y2'), line1[lineCount-1],line1[lineCount]));}
      }
      
     lineCount=lineCount+1;
     

Open in new window


 var leftx2,topy2;
var moveHandler = function (evt) {
    var obj = evt.target;
  leftx2 = obj.get('left');
  topy2 = obj.get('top');
  /*
     1.
    obj.line1 && obj.line1.set({ 'x2': obj.left, 'y2': obj.top });
    obj.line2 && obj.line2.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line3 && obj.line3.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line4 && obj.line4.set({ 'x1': obj.left, 'y1': obj.top });
    canvas.renderAll();

    2.
       for (var i = 0, len = lineCount; i < len; i++) {
           obj.line1[i] && obj.line1[i].set({ 'x2': obj.left, 'y2': obj.top });
       }
         3.  */
    obj.line1[0] && obj.line1[0].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[1] && obj.line1[1].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[2] && obj.line1[2].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[3] && obj.line1[4].set({ 'x2': obj.left, 'y2': obj.top });
    

Open in new window

7.png
0
Leonidas DosasCommented:
Could you post all the code please because they are missing elements like "RadioPol"?
0
Ivan GolubarAuthor Commented:
Consider point 1 (from my last post) double click to end the polyline done.
No need to use double click. I will just  check, if i am clicking on any object to end the polyline.

But i still need help with:
2 move handler
3 check the attached picture(previous post): I don't want to see line in circle.  


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

 <script src=".................../fabric.min.js"></script>
 
 
<style>



</style>

<script>

var line1=[];

 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
    selectable: false
    });
 }
  function makeCircle(left, top, line1, line2) {
    var c = new fabric.Circle({
      left: left,
      top: top,
      strokeWidth: 2,
      radius: 6,
      fill: '#fff',
      stroke: '#666'
    });
    c.hasControls = c.hasBorders = false;

    c.line1 = line1;
    c.line2 = line2;

    return c;
  }
  
 
var clickonobject ;
var objectIndex;
var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;
function drawPoly(){
  
     var RP = document.getElementById("RadioPol").checked;
  
  if (RP) {
      
       if (lineCount!=0){
       line1[lineCount] = makeLine([posX1, posY1, posX2, posY2 ]);
       canvas.add(line1[lineCount]);
       } 
 
      if (lineCount==0){canvas.add(makeCircle( posX2, posY2, null));}
      if (lineCount>0){canvas.add( makeCircle(line1[lineCount].get('x2'), line1[lineCount].get('y2'), line1[lineCount-1],line1[lineCount]));}
      }
      
     lineCount=lineCount+1;    
}
canvas.on('mouse:down', function(e) {
    var obj2 = e.target;
    if (obj2!= null){console.log(obj2.type);}
   
  if (obj2==null){
       //if (obj2.type== Circle){lineCount=0;}
      // else{
         posX1 = posX2;
         posY1 = posY2;
         var pointer = canvas.getPointer(e.e);
         posX2 = pointer.x;
         posY2 = pointer.y;
         drawPoly();//}
      }else{lineCount=0;}

  });


var leftx2,topy2;
var moveHandler = function (evt) {
    var obj = evt.target;
  leftx2 = obj.get('left');
  topy2 = obj.get('top');
   //console.log(leftx2);
  //console.log(topy2);

  /*
    obj.line1 && obj.line1.set({ 'x2': obj.left, 'y2': obj.top });
    obj.line2 && obj.line2.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line3 && obj.line3.set({ 'x1': obj.left, 'y1': obj.top });
    obj.line4 && obj.line4.set({ 'x1': obj.left, 'y1': obj.top });
    canvas.renderAll();

    
       for (var i = 0, len = lineCount; i < len; i++) {
           obj.line1[i] && obj.line1[i].set({ 'x2': obj.left, 'y2': obj.top });
       }
           
    obj.line1[0] && obj.line1[0].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[1] && obj.line1[1].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[2] && obj.line1[2].set({ 'x2': obj.left, 'y2': obj.top });
    obj.line1[3] && obj.line1[4].set({ 'x2': obj.left, 'y2': obj.top });
    */
</script>
</head>
<body>
       <canvas  id="c" width="1060" height="550"  > 

 
</div>
</body></html>

Open in new window

0
Ivan GolubarAuthor Commented:
Next code is moving only line before the circle and not the other one.


var leftx2,topy2;
var moveHandler = function (evt) {
    var obj = evt.target;
  leftx2 = obj.get('left');
  topy2 = obj.get('top');
 

    obj.line1 && obj.line1.set({ 'x2': obj.left, 'y2': obj.top });
    obj.line2 && obj.line2.set({ 'x1': obj.left, 'y1': obj.top });
}

Open in new window


The problem is in next line:
if (lineCount>0){canvas.add( makeCircle(line1[lineCount].get('x2'), line1[lineCount].get('y2'), line1[lineCount],line1[lineCount+1]));}

When i am making circles as anchor point i don't have  yet the next line (i have the line before circle and not yet the line after circle)

So i must each time i make new line find the previouse circle and add to him  line which was just been made. How to do that?
0
Ivan GolubarAuthor Commented:
With next code also the problem number 2 is resolved.
Now when I press on circle i may drag both lines which are attached to specific circle as circle is moving.

     
if (lineCount==0){
          circle1[lineCount]=makeCircle( posX2, posY2, null,null);
          canvas.add(circle1[lineCount]); 
      }
      if (lineCount>0){
         circle1[lineCount]= makeCircle(line1[lineCount].get('x2'), line1[lineCount].get('y2'), line1[lineCount],null);
         canvas.add(circle1[lineCount]); 
         circle1[lineCount-1].line2 =line1[lineCount];
      } 

Open in new window


Now about problem from point 3.  ( small part of line is in the circle ( Check attached picture))
I am not sure  if i could leave it as it is, as it gives me the direction of line creation. So consider this question closed.


How to assign points?
Untitled8.png
0
Leonidas DosasCommented:
Ivan I used your previous code ID 42519818 but unfortunately I haven't any output in my browser.Could you check again and repost your code?
0
Ivan GolubarAuthor Commented:
Can you run next one.
I have upgrade it with Json variable. I need to store Json to DB and to retrieve it back. But this is not point of this topic.

You do just test making of polyline by clicking on canvas until you click on one circle twice  which means end of polyline.
But as i was saying before (previous post) I have code now which is working. What would You like to do with it?


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">


 <script src="http://fabricjs.com/lib/fabric.js"></script>
 
<style>



</style>

<script>
var canvas = new fabric.Canvas('c');
 
  
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';



var line1=[];

 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
    selectable: false,
     name:'polyline'
    });
 }
 var circle1=[];
  function makeCircle(left, top, line1, line2) {
    var c = new fabric.Circle({
      left: left,
      top: top,
      strokeWidth: 2,
      radius: 6,
      fill: '#fff',
      stroke: '#666',
      name:'polyline'
    });
    c.hasControls = c.hasBorders = false;

    c.line1 = line1;
    c.line2 = line2;

    return c;
  }
 
 
var clickonobject ;
var objectIndex;
var lineCount=0;
var posX1=0;
var posY1=0;
var posX2=0;
var posY2=0;
function drawPoly(){
  
 
      
       if (lineCount!=0){
       line1[lineCount] = makeLine([posX1, posY1, posX2, posY2 ]);
       canvas.add(line1[lineCount]);
        console.log(line1[lineCount].type,line1[lineCount].name);
       } 

     if (lineCount==0){
          circle1[lineCount]=makeCircle( posX2, posY2, null,null);
          canvas.add(circle1[lineCount]); 
      }
      if (lineCount>0){
         circle1[lineCount]= makeCircle(line1[lineCount].get('x2'), line1[lineCount].get('y2'), line1[lineCount],null);
         canvas.add(circle1[lineCount]); 
         circle1[lineCount-1].line2 =line1[lineCount];
      } 
      
     lineCount=lineCount+1;    
}

canvas.on('mouse:down', function(e) {
    var obj2 = e.target;
    if (obj2!= null){console.log(obj2.type);}
   
  if (obj2==null){
         posX1 = posX2;
         posY1 = posY2;
         var pointer = canvas.getPointer(e.e);
         posX2 = pointer.x;
         posY2 = pointer.y;
         drawPoly();
      }else{lineCount=0;}
});

 var leftx2,topy2;
var moveHandler = function (evt) {
    var obj = evt.target;
  leftx2 = obj.get('left');
  topy2 = obj.get('top');
   //console.log(leftx2);
  //console.log(topy2);
    obj.line1 && obj.line1.set({ 'x2': obj.left, 'y2': obj.top });
    obj.line2 && obj.line2.set({ 'x1': obj.left, 'y1': obj.top });
}


var jsonToPHP;
function  saveJsonF(){
jsonToPHP= JSON.stringify(canvas.toObject(['id','name','line1','line2']));
canvas.clear();

}
function  getJsonF(){
    canvas.loadFromJSON(jsonToPHP, function() {    
    canvas.renderAll();
      });
}


var interval4;

var projectDumieTrue=false;
function LoadOnStart2() {
    clearInterval(interval4);
  document.getElementById("saveJsonID").onclick = saveJsonF;
document.getElementById("getJsonID").onclick = getJsonF;   
}
 interval4 = setInterval(LoadOnStart2, 1000);


</script>
</head>
<body>
      <input type="button"  id="saveJsonID" value=" saveJson"/> 
        <input type="button"   id="getJsonID" value=" getJson"/>
       <canvas  id="c" width="1060" height="550"  > 
      

 
</div>
</body></html>

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ivan GolubarAuthor Commented:
In the last post is my complete working code.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.