Adding object to an array beyond the standard array elements

With next code snippet I am creating circles and lines, but once i save them to Json and retrieve back i lose all functions.
  var line1=[];
 function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'green',
      stroke: 'green',
      strokeWidth: 4,
      selectable: false,
      name:objectname,
      selectable:false,
      id:"polyline"+lineCount
    });
 }
var circle1=[];
  function makeCircle(left, top, line1, line2) {
    var c = new fabric.Circle({
      left: left,
      top: top,
      strokeWidth: 1,
      radius: 6,
      fill: '#fff',
      stroke: '#666',
      name:objectname,
      id:"polycircle"+lineCount
    });
    c.hasControls = c.hasBorders = false;
    c.line1 = line1;
    c.line2 = line2;
    return c;
  }

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

function  getJsonF2(){ 
    canvas.loadFromJSON( jsonToPHP, function() {    
    canvas.renderAll();
      });
}
document.getElementById("saveJsonID").onclick = saveJsonF2;
document.getElementById("getJsonID").onclick = getJsonF2;

Open in new window


And i can not use  "set" in next move handler therefore.
 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 solution would be next example, but I can't adapt it to my code.


Can you help me?


var myObject = {
    myFunction : 'set'
};

var serializedObject = JSON.stringify(myObject);
var myDecodedObject = JSON.parse(serializedObject);

if (typeof window[myDecodedObject.myFunction] === 'function') {
    window[myDecodedObject.myFunction]();
}
 

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.

ste5anSenior DeveloperCommented:
JSON (JavaScript Object Notation) is a lightweight data-interchange format. See json.org. The key is data.

You cannot use JSON to directly create a typed object. The most common approach is to create a deserialize function, which takes the JSON and is basically a factory method. But you need to know the destination type.

E.g.

<!DOCTYPE html>
<html>
    <head>
        <script>
            function Car(manufacturer, model, color) {
                this.manufacturer = manufacturer;
                this.model = model;
                this.color = color;
            };

            Car.prototype.toString = function () {
                return "A " + this.color + " " + this.model + " from " + this.manufacturer + ".";
            };

            Car.prototype.serialize = function () {
                return JSON.stringify(this, null, 0);
            };

            Car.deserialize = function (json) {
                var obj = JSON.parse(json);
                return new Car(obj.manufacturer, obj.model, obj.color);
            };

            var car = new Car("BMW", "Z1", "green");
            console.log(car.toString());

            var json = car.serialize();
            console.log(json);

            var deserialized = Car.deserialize(json);
            console.log(deserialized.toString());
        </script>
    </head>
    <body>
    </body>
</html>

Open in new window


But in your canvas scenario, you need a pretty complex factory method.
0
Ivan GolubarAuthor Commented:
Thank you.

I don't have theoretical knowledge about JS and no experience,  to be capable to do where you are pointing to. So  I was thinking about an shortcut, which could be a bad idea also, but let me expose it here now.
As json is anarray of objects in this case. Why not loop through this array, take only propreties which are needed (see my first code snippet) and not create new objects from Json?
0
ste5anSenior DeveloperCommented:
Well, this is exactly what I wrote: You need a complex deserialize method which depends on your used objects. Just write it..

I'm not using fabric.js, which is I guess you unnamed used framework. So you should look into their documentation first. Maybe the offer already build-in solutions.

In any other case you need to implement it yourself. Or take a look at https://www.npmjs.com/package/automapper-ts, but this seems like adding additional complexity to your project. Which reminds me: Can you rephrase your question? What are you trying to do exactly? What is your use-case?
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
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.

Ivan GolubarAuthor Commented:
I will try latter in the evening.
Next code is my adaptation to my needs of: http://fabricjs.com/stickman  which is part of larger code where i have also other objects which have nothing to do with this case. But i have a good filing that i will finally  get out of situation which was blocking me for to long time now.


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

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

<script>
var canvas = new fabric.Canvas('c5');
  
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');
  
    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;

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="c5" width="1060" height="550"   style="border: 1px solid black" > 
      

</body></html>

Open in new window

0
ste5anSenior DeveloperCommented:
What an odd framework, can get the sample run... and the doc is pretty poor.. but it's pretty simple: abstraction.

Change the function to accept a data transfer object (DTO), Something like

<!DOCTYPE html>
<html>

<head>
    <script href="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js" type="JavaScript"></script>
    <script>
        (function () {
            function drawStickmann(config) {
                var canvas = this.__canvas = new fabric.Canvas('c', { selection: false });
                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
                    });
                }

                // Iterate over config.lines and create an array of lines instead of:
                // var line = makeLine([250, 125, 250, 175]),
                //     line2 = makeLine([250, 175, 250, 250]),
                //     line3 = makeLine([250, 250, 300, 350]),
                //     line4 = makeLine([250, 250, 200, 350]),
                //     line5 = makeLine([250, 175, 175, 225]),
                //     line6 = makeLine([250, 175, 325, 225]);
                canvas.add(lines[1], lines[2], lines[3], lines[4], lines[5], lines[6]);

                // Iterate over config.circles instead of:
                // var circle1 = makeCircle(line.get('x1'), line.get('y1'), null, line),
                //     circle2 = makeCircle(line.get('x2'), line.get('y2'), line, line2, line5, line6),
                //     circle3 = makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, line4),
                //     circle4 = makeCircle(line3.get('x2'), line3.get('y2'), line3),
                //     circle5 = makeCircle(line4.get('x2'), line4.get('y2'), line4),
                //     circle6 = makeCircle(line5.get('x2'), line5.get('y2'), line5),
                //     circle7 = makeCircle(line6.get('x2'), line6.get('y2'), line6);
                canvas.add(circle1, circle2, circle3, circle4, circle5, circle6, circle7);

                canvas.on('object:moving', function (e) {
                    var p = e.target;
                    p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
                    p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
                    p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top });
                    p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top });
                    canvas.renderAll();
                });
            };

            var config = {};
            config.lines = [
                [250, 125, 250, 175],
                [250, 175, 250, 250],
                [250, 250, 300, 350],
                [250, 250, 200, 350],
                [250, 175, 175, 225],
                [250, 175, 325, 225]
            ];
            
            config.circles = [
                [ 250, 125, [ null, 1 ] ],
                [ 250, 175, [ 1, 2, 5, 6 ] ],
                [ 250, 250, [ 2, 3, 4 ] ],
                [ 300, 350, [ 3 ] ],
                [ 200, 350, [ 4 ] ],
                [ 175, 225, [ 5 ] ],
                [ 325, 225, [ 6 ] ]
            ];

            drawStickmann(config)
        })();
    </script>
</head>

<body>
</body>

</html>

Open in new window


Off-by-one and some todos. But now you can simply (de-)serialize your config object and use it with your draw function. Or make your own class from it like in my first sample.
0
Ivan GolubarAuthor Commented:
I will work on it later in the evening.  If you could pleas try more to implement it in my code (and not on internet demo), it would be much more of value for me and easier to understand.

I am afraid that I will not be able to pull out good result from what you gave me.  Or lets wait what I can do. I have yoga class for two hours now.
then i will start the work.
0
ste5anSenior DeveloperCommented:
[..] try more to implement it in my code [..]
This requires a concise and complete exmple from you..
0
Ivan GolubarAuthor Commented:
Now.
Can You run my code.
If not there must be problem with library. I did download fabri.min.js on my server and i am using it from there.
Next  
<script src="http://fabricjs.com/lib/fabric.js"></script>

Open in new window

I am not sure if it is working.

But as my code is adding dynamically by clicking on canvas lines and circles do draw a path as polyline is absolutely necessary to work on it.

If not I am obligated to go on, by doing code to select  properties from json and draw shapes  from them.
0
Ivan GolubarAuthor Commented:
My code is not much different from demo example. I have on click event where i get coordinates and I am using them to locate circles and shapes.

Can you make work for you on some testing online page?
0
ste5anSenior DeveloperCommented:
My code is not much different from demo example

Well, then post it. As single, concise and completee exmple.
0
Ivan GolubarAuthor Commented:
Look back to ID: 42535937 pleas.
0
Ivan GolubarAuthor Commented:
I forgot to add next to my code: canvas.on({'object:moving' : moveHandler});  I apologize.
From next Json i have to add  on canvas three circles and two lines  to create a polyline.

{"objects":
[
{"type":"line","fill":"green","stroke":"green","strokeWidth":4, "id":"polyline1","name":"1”,"x1":-69,"x2":69,"y1":-96.5,"y2":96.5}},

{"type":"line","fill":"green","stroke":"green","strokeWidth":4, "id":"polyline2","name":"1”,""x1":-29.5,"x2":29.5,"y1":61.5,"y2":-61.5},

{"type":"circle","left":42,"top":53.91,"fill":"#fff","stroke":"#666","strokeWidth":1,"radius":6,"id":"polycircle0","name":"1","line1":null,"line2":{"type":"line","fill":"green","stroke":"green","strokeWidth":4, "id":"polyline1","name":"1”,"x1":-69,"x2":69,"y1":-96.5,"y2":96.5}},

{"type":"circle", left":180,"top":246.91, fill":"#fff","stroke":"#666","strokeWidth":1,"radius":6,"id":"polycircle2","name":"1","line1":{"type":"line”,"fill":"green","stroke":"green","strokeWidth":4, "id":"polyline1","name":"1”,"x1":-69,"x2":69,"y1":-96.5,"y2":96.5},"line2":{"type":"line","fill":"green","stroke":"green","strokeWidth":4, "id":"polyline2","name":"1”,""x1":-29.5,"x2":29.5,"y1":61.5,"y2":-61.5}},

{"type":"circle","left":239,"top":123.91,"fill":"#fff","stroke":"#666","strokeWidth":1,"id":"polycircle3","name":"1","line1":{"type":"line","left":209.5,"top":185.41,"fill":"green","stroke":"green","strokeWidth":4, "id":"polyline2","name":"1”,""x1":-29.5,"x2":29.5,"y1":61.5,"y2":-61.5},"line2":null}}
]
}
0
Ivan GolubarAuthor Commented:
Select Fabric.js library  to make next code fiddle work:

https://jsfiddle.net/3f5vk65v/


Click two points inside canvas to to draw polyline.  Test the movement of line by pressing and dragging of circle anchor point. Then test again after clicking on saveJson and getJson  buttons.
0
ste5anSenior DeveloperCommented:
hmm, you should have written what you're trying to do in the first post.. you want to draw (open) polygons. Thus you need a different, simpler strategy. Just manage the points. The lines could be derived from it.

Simplified:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js" type="text/javascript"></script>
        <script>
            function drawCircle(left, top) {
                console.log('drawCircle(' + JSON.stringify(arguments, null, 0) + ')');
                var c=  new fabric.Circle({
                    left: left,
                    top: top,
                    strokeWidth: 2,
                    radius: 6,
                    fill: '#fff',
                    stroke: '#666',
                    name: 'polyline'
                });

                c.hasControls = c.hasBorders = false;
                canvas.add(c);
                return c;
            }

            function drawLine(pointFrom, pointTo) {
                console.log('drawLine(' + JSON.stringify(arguments, null, 0) + ')');
                var line = new fabric.Line([ pointFrom.x, pointFrom.y, pointTo.x, pointTo.y ], {
                    fill: 'red',
                    stroke: 'red',
                    strokeWidth: 5,
                    selectable: false,
                    name: 'polyline'
                });

                canvas.add(line);
                return line;
            }

            function drawClosedPolygon(points) {
                console.log('drawClosedPolygon');
                var lastPoint;
                points.forEach(function (point) {
                    drawCircle(point.x, point.y);
                    if (!(lastPoint == undefined)) {
                        drawLine(lastPoint, point);
                    }

                    lastPoint = point;
                });

                if (!(lastPoint == undefined)) {
                    drawLine(lastPoint, points[0]);
                }
            };

            function drawOpenPolygon(points) {
                console.log('drawOpenPolygon');
                var lastPoint;
                points.forEach(function (point) {
                    drawCircle(point.x, point.y);
                    if (!(lastPoint == undefined)) {
                        drawLine(lastPoint, point);
                    }

                    lastPoint = point;
                });
            };
        </script>
    </head>
    <body>
        <canvas id="c5" width="1060" height="550" style="border: 1px solid black"></canvas>
        <script>
            var canvas = new fabric.Canvas('c5');
            fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

            var points = [
                { x:100.0, y:100.0 } ,
                { x:200.0, y:100.0 } ,
                { x:200.0, y:200.0 } ,
                { x:100.0, y:200.0 }
                ];
            drawOpenPolygon(points);

            points = [
                { x:100.0, y:300.0 } ,
                { x:200.0, y:300.0 } ,
                { x:150.0, y:400.0 }
                ];
            drawClosedPolygon(points);
        </script>
    </body>
</html>

Open in new window


Thus you only need to manage the add point scenario:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js" type="text/javascript"></script>
        <script>
            function drawCircle(left, top) {
                console.log('drawCircle(' + JSON.stringify(arguments, null, 0) + ')');
                var c=  new fabric.Circle({
                    left: left,
                    top: top,
                    strokeWidth: 2,
                    radius: 6,
                    fill: '#fff',
                    stroke: '#666',
                    name: 'polyline'
                });

                c.hasControls = c.hasBorders = false;
                canvas.add(c);
                return c;
            }

            function drawLine(pointFrom, pointTo) {
                console.log('drawLine(' + JSON.stringify(arguments, null, 0) + ')');
                var line = new fabric.Line([ pointFrom.x, pointFrom.y, pointTo.x, pointTo.y ], {
                    fill: 'red',
                    stroke: 'red',
                    strokeWidth: 5,
                    selectable: false,
                    name: 'polyline'
                });

                canvas.add(line);
                return line;
            }

            function drawOpenPolygon(points) {
                console.log('drawOpenPolygon');
                var lastPoint;
                points.forEach(function (point) {
                    drawCircle(point.x, point.y);
                    if (!(lastPoint == undefined)) {
                        drawLine(lastPoint, point);
                    }

                    lastPoint = point;
                });
            };

            var points = [];
            var lastPoint;
            function addPoint(point) {
                points.push(point);
                drawCircle(point.x, point.y);
                if (!(lastPoint == undefined)) {
                    drawLine(lastPoint, point);
                }

                lastPoint = point;
            }

            function load() {
                canvas.clear();
                var json = document.getElementById("points").textContent;
                points = JSON.parse(json);
                drawOpenPolygon(points);
                lastPoint = points[points.length - 1];
            }

            function saveAndClear() {
                document.getElementById("points").textContent = JSON.stringify(points, null, 1);
                points = [];
                lastPoint = undefined;
                canvas.clear();
            }
        </script>
    </head>
    <body>
        <canvas id="c5" width="1060" height="550" style="border: 1px solid black"></canvas>
        <script>
            var canvas = new fabric.Canvas('c5');
            fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

            canvas.on('mouse:down', function (e) {
                var pointer = canvas.getPointer(e.e);
                addPoint({ x:pointer.x, y:pointer.y });
            });
        </script>
        <input type="button" value="save & clear" onclick="saveAndClear()"/>
        <input type="button" value="load" onclick="load()"/>
        <pre id="points">[
{
 "x": 185.6497175141243,
 "y": 441.3949275362319
},
{
 "x": 319.3973634651601,
 "y": 429.43840579710144
},
{
 "x": 198.62523540489641,
 "y": 314.8550724637681
},
{
 "x": 323.3898305084746,
 "y": 308.8768115942029
},
{
 "x": 269.49152542372883,
 "y": 222.19202898550725
},
{
 "x": 196.62900188323917,
 "y": 310.8695652173913
},
{
 "x": 180.65913370998118,
 "y": 439.4021739130435
},
{
 "x": 322.39171374764595,
 "y": 306.8840579710145
},
{
 "x": 318.39924670433146,
 "y": 422.463768115942
}
]</pre>
    </body>
</html>

Open in new window

0
Ivan GolubarAuthor Commented:
I do not see any move handler in Your code.  Can Your code move lines attached to circles when you press on circle and drag it on the canvas?

Did you manage to do it in my testing fiddle  from my last post?
0
Ivan GolubarAuthor Commented:
hmm, you should have written what you're trying to do in the first post.. you want to draw (open) polygons.

I am not trying to draw open polygons. I can do that with my code.
And I can also move my polygon  by moving  of anchor points (circles).


But i can not do moving of existing open polygon after i save it to json and then retrieve it back.
Here i need Your help.
0
ste5anSenior DeveloperCommented:
It should be now obvious, that you simply need to filter the result of the toObject() call.

function saveAndClear() {
	actualPoints = canvas
		.toObject().objects
		.filter(function (obj) { return obj.type === "circle"; })
		.map(function (obj) { return { x:obj.left, y:obj.top }; });
	document.getElementById("points").textContent = JSON.stringify(actualPoints, null, 1);
	// clear associate arrays and variables.
	canvas.clear();
}

Open in new window


and just add the points when loading it.
0
Ivan GolubarAuthor Commented:
Next is your code on jsfidle can you test it? Is it working right for You?


https://jsfiddle.net/cu9qa9ku/3/
0
ste5anSenior DeveloperCommented:
Nope. JS Fiddle is neither working on IE11, Chrome nor FF here..

That's the reason why I posted concise and complete examples. And just for your curiosity: I took my half an hour to make it work the first time. That's the reason for complete sample. You make it easier for us to help you.
0
Ivan GolubarAuthor Commented:
I need to test your code before use all or part of it in my app.
I can test my code on JS Fiddle. And also yours. And Your code does not do what I am requiring. The test I am doing with your code does not move lines behind circles.

So I need then feedback from you. Is it your code moving lines behind circles if you press on circle and drag it around when you do it on your computer?
0
ste5anSenior DeveloperCommented:
You didn't get the concepts I tried to show you, did you?

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js" type="text/javascript"></script>
    </head>
    <body>
        <canvas id="c5" width="1060" height="550" style="border: 1px solid black"></canvas>
        <script>
            var canvas = new fabric.Canvas('c5');
            var circle1 = [];
            var lineCount = 0;
            var posX1 = 0;
            var posY1 = 0;
            var posX2 = 0;
            var posY2 = 0;
            var line1 = [];
            fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

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

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

            function drawPoly() {
                if (lineCount != 0) {
                    line1[lineCount] = makeLine([posX1, posY1, posX2, posY2]);
                    canvas.add(line1[lineCount]);
                }

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

            function addPoint(x, y) {
                posX1 = posX2;
                posY1 = posY2;
                posX2 = x;
                posY2 = y;
                drawPoly();
            };

            canvas.on('mouse:down', function (evt) {
                var obj = evt.target;
                if (obj == null) {
                    var pointer = canvas.getPointer(evt.e);
                    addPoint(pointer.x, pointer.y);
                }
                else
                {
                     lineCount = 0; // ????
                }
            });

            canvas.on('object:moving', 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 });
            });

            function load() {
                canvas.clear();
                var json = document.getElementById("points").textContent;
                points = JSON.parse(json);
                points.forEach(function (point) {
                    addPoint(point.x, point.y);
                });
            }

            function saveAndClear() {
                actualPoints = canvas
                    .toObject().objects
                    .filter(function (obj) { return obj.type === "circle"; })
                    .map(function (obj) { return { x:obj.left, y:obj.top }; });
                document.getElementById("points").textContent = JSON.stringify(actualPoints, null, 1);
                canvas.clear();
                circle1 = [];
                lineCount = 0;
                posX1 = 0;
                posY1 = 0;
                posX2 = 0;
                posY2 = 0;
                line1 = [];
            }
        </script>
        <input type="button" value="saveJson" onclick="saveAndClear()" />
        <input type="button" value="getJson" onclick="load()" />
        <pre id="points"></pre>
    </body>
</html>

Open in new window

0
Ivan GolubarAuthor Commented:
lineCount = 0; // ????

Open in new window


Because if you click on  circle again, you are finishing one polyline and next click will be start  of new one.

No, i did not.

Let me make you last code to run in JSFidle.
0
ste5anSenior DeveloperCommented:
You shouldn't use fiddler. E.g. your canvas element is incorrectly declared, it requires a closing tag. Using a local file and the debugger of your browser would tell you that..
0
ste5anSenior DeveloperCommented:
Just for fun, a complete solution (like I would do it):

<!DOCTYPE html>
<html>
    <head>
        <style>
            canvas  { border: 1px solid black; }
            pre     { font: 8px; }
        </style>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js" type="text/javascript"></script>
        <script>
            // Using simple namespace to avoid poluting global.
            var sample = sample || {};
            sample.canvas = undefined;
            sample.lastCircle = undefined;
            sample.lastPoint = undefined;

            // Canvas methods.
            sample.canvasClear = function() {
                sample.canvas.clear();
                sample.lastCircle = undefined;
                sample.lastPoint = undefined;
            }

            sample.canvasLoad = function() {
                polygonalLines = JSON.parse(document.getElementById("data").textContent);
                sample.drawPolygonalLines(polygonalLines);
            }

            sample.canvasSave = function() {
                var polygonalLine = [];
                var polygonalLines = [];
                var objects = sample.canvas.toObject(["lineIn", "lineOut"]).objects;
                objects
                    .filter(function (obj) { return obj.type === "circle"; })
                    .map(function (obj) { return { x:obj.left, y:obj.top, hasLineIn:!(obj.lineIn == undefined) }; })
                    .forEach(function (circle) {
                        if (!circle.hasLineIn && polygonalLine.length > 0) {
                            polygonalLines.push(polygonalLine);
                            polygonalLine = [];
                        }

                        polygonalLine.push({ x:circle.x, y:circle.y });
                    });

                if (polygonalLine.length > 0){
                    polygonalLines.push(polygonalLine);
                }

                document.getElementById("data").textContent = JSON.stringify(polygonalLines, null, 1);
            }

            sample.canvasSetup = function () {
                sample.canvas = new fabric.Canvas('canvas');
                fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
                sample.canvas.on('mouse:down', function (eventArgs) {
                    if (eventArgs.target === null) {
                        var pointer = sample.canvas.getPointer(eventArgs.e);
                        sample.polygonalLineAddPoint({ x:pointer.x, y:pointer.y });
                    } else {
                        sample.polygonalLineNewLine();
                    }
                });

                sample.canvas.on('object:moving', function (eventArgs) {
                    var target = eventArgs.target;
                    if (target.type = "circle") {
                        target.lineIn && target.lineIn.set({ 'x2': target.left, 'y2': target.top });
                        target.lineOut && target.lineOut.set({ 'x1': target.left, 'y1': target.top });
                    }
                });
            }

            // Drawing "primitives".
            sample.drawCircle = function (point) {
                var circle = new fabric.Circle({
                    left: point.x,
                    top: point.y,
                    radius: 6,
                    strokeWidth: 2,
                    fill: '#fff',
                    stroke: '#666'
                });

                circle.hasControls = circle.hasBorders = false;
                sample.canvas.add(circle);
                return circle;
            }

            sample.drawLine = function (pointFrom, pointTo) {
                var line = new fabric.Line(
                    [ pointFrom.x, pointFrom.y, pointTo.x, pointTo.y ],
                    {
                        fill: 'red',
                        stroke: 'red',
                        strokeWidth: 5,
                        selectable: false
                    }
                );

                sample.canvas.add(line);
                return line;
            }

            // "Higher order" drawing.
            sample.drawPolygonalLine = function (polygonalLine) {
                var lastCircle;
                var lastPoint;
                polygonalLine.forEach(function (point) {
                    var circle = sample.drawCircle(point);
                    if (!(lastPoint == undefined)) {
                        var line = sample.drawLine(lastPoint, point);
                        circle.lineIn = line;
                        if (!(lastCircle == undefined)) {
                            lastCircle.lineOut = line;
                        }
                    }

                    lastCircle = circle;
                    lastPoint = point;
                });
            }

            sample.drawPolygonalLines = function (polygonalLines) {
                polygonalLines.forEach(function (polygonalLine) { sample.drawPolygonalLine(polygonalLine); });
            }

            // Polygonal line construction.
            sample.polygonalLineAddPoint = function (point) {
                var circle = sample.drawCircle(point);
                if (!(sample.lastPoint == undefined)) {
                    var line = sample.drawLine(sample.lastPoint, point);
                    circle.lineIn = line;
                    if (!(sample.lastCircle == undefined)) {
                        sample.lastCircle.lineOut = line;
                    }
                }

                sample.lastCircle = circle;
                sample.lastPoint = point;
            }

            sample.polygonalLineNewLine = function () {
                sample.lastCircle = undefined;
                sample.lastPoint = undefined;
            }
        </script>
        <script>
            // DOM - Start "app".
            window.onload = function () {
                sample.canvasSetup();
                // Just a convenient "minimal" data representation of polyigonal lines.
                // ToDo: implemement as own type.
                var  polygonalLines  = [
                    [ { x:100.0, y:100.0 } , { x:200.0, y:100.0 } , { x:200.0, y:200.0 } , { x:100.0, y:200.0 } ],
                    [ { x:100.0, y:300.0 } , { x:200.0, y:300.0 } , { x:150.0, y:400.0 } ]
                ];

                sample.drawPolygonalLines(polygonalLines);
            }
        </script>
    </head>
    <body>
        <div>
            <canvas id="canvas" width="640" height="480"></canvas>
        </div>
        <div>
            <input type="button" value="Save" onclick="sample.canvasSave()"/>
            <input type="button" value="Clear" onclick="sample.canvasClear()"/>
            <input type="button" value="Load" onclick="sample.canvasLoad()"/>
        </div>
        <div>
            <pre id="data">[]</pre>
        </div>
    </body>
</html>

Open in new window

0
Ivan GolubarAuthor Commented:
Thank you


In Your code from previous post number ID: 42537201
After reloading of canvas   lines are connected. Check attached picture.
 before and after saveCheck ID: 42537237 about this meter pleas.

Your last code from ID: 42537445 is much more complex so my first try to integrate it in my exiting  app fail. My code i did show you is made just to solve this problem. But is Your "complex" code it also connecting  all lines after reloading?
0
ste5anSenior DeveloperCommented:
Just a comment:

But is Your "complex" code it also connecting  all lines after reloading?
hmm, graph handling and drawing is not simple.

Yours:

function makeLine(coords) 
function makeCircle(left, top, line1, line2)
function drawPoly()
function getJsonF()
function LoadOnStart2() 

Open in new window

vs mine:

sample.canvasClear = function()
sample.canvasLoad = function()
sample.canvasSave = function()
sample.canvasSetup = function ()
sample.drawCircle = function (point)
sample.drawLine = function (pointFrom, pointTo) 
sample.drawPolygonalLine = function (polygonalLine)
sample.drawPolygonalLines = function (polygonalLines)
sample.polygonalLineAddPoint = function (point)
sample.polygonalLineNewLine = function ()

Open in new window


It is more code, but it is lesser complex than yours. Especially at is little lesser coupled (dependencies). The key is to produce code, which says what it does. Thus having more methods, but precisely named, doing what their name implies is good.
0
Ivan GolubarAuthor Commented:
Pleas check the attached picture in my last post.

After reloading from json all elements  are connected. Code is generating lines which were not existing before reloading of json.

This behavior has to be prevented.
0
Ivan GolubarAuthor Commented:
On base of my second post in this  question (ID: 42535771)
As json is anarray of objects in this case. Why not loop through this array, take only propreties which are needed (see my first code snippet) and not create new objects from Json?


I did add  id:"polycircle"+lineCount; to makeCircle function and  I have changed  load from json function in my code and everything works fine now.

function  getJsonF2(){
 //console.log(jsonToPHP);
 
   /* canvas.loadFromJSON( jsonToPHP, function() {    
    canvas.renderAll();
      });*/
      
    var jsonParse=JSON.parse(jsonToPHP);
    for (var i = 0; i < jsonParse.objects.length; i++) {
        var justIDC =jsonParse.objects[i].id;
           if (justIDC.includes('polycircle')){
           justIDC = justIDC.replace('polycircle','');console.log(justIDC);
           if (justIDC=="0"){lineCount =0;}
          posX1=posX2;
          posX2 =jsonParse.objects[i].left;
          posY1=posY2;
          posY2 =jsonParse.objects[i].top;
          drawPoly();
         }
    }
}

Open in new window


Thank you
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.