简体   繁体   中英

async sort for kineticjs line points?

The problem I've been fighting for the last 2 days is a bit strange, so I was not really sure how specify it in the title.

I have a KineticJs Line, which has an array of points (line.attrs.points) in the form of objects with x and y values. While dragging a certain Kinetic element, I want to dynamically add points to the line and re-draw it. (Example: the line looks like that: \\ _ _ _ / and under certain conditions while dragging another shape I want to dynamically add a point and make it look like that: \\ _ / \\ _ /) So, when that condition is met in the dragmove event of the other shape, I use the following code:

line.attrs.points.push({x:xValue, y:yValue});
line.attrs.points.sort(function(a,b){
    return a.x > b.x; // I tried with a.x - b.x and with short if-s which return only -1, 0 or 1, still nothing happened
});
line.setPoints(line.attrs.points);
layer.draw();

but the points are not sorted so the line goes to some x, then returns to a less x and then again goes forward which is not the behavior I expected after a sort of the points!

The strange thing is that when I use console.log(line.attrs.points); for three consecutive point additions (+2 points in each addition) I get the following output:

[Object, Object, Object, Object, Object, Object]
[Object, Object, Object, Object, Object, Object, Object, Object]
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]

but when I open the arrays, there are 10 objects in each array. How is it even possible to open an array of 6 objects and see 10 objects inside (I'm using Google Chrome's default console)? Can it be that the console.log is asynchronous and logs them after all the additions have taken place?

The main problem is that the sort of the points isn't working, but still I'll be glad to understand why the console acts so strange.

Thanks in advance and sorry for the long explanations!

You need too keep your points in drawing order (not “x” order)

To do that, add a sortBy field to each point object

{ x:10, y:10, sortBy:”1” }
{ x:30, y:10, sortBy:”2” }

To add a point between these 2 points, just add a suffix letter to the sortBy field:

{ x:10, y:10, sortBy:”1” }
{ x:20, y:10, sortBy:”1A” }
{ x:30, y:10, sortBy:”2” }

And then sort your objects by the sortBy field using a compare function like this:

function myCompare(a,b){
    if(a.sortBy<b.sortBy){ return -1; }
    if(a.sortBy>b.sortBy){ return 1; }
    return(0);
}

myPoints.sort(myCompare);

You can create an appendPoint function for inserting point objects in sequential order

var points=[];
var index=0;

appendPoint(100,150);
appendPoint(200,150);

function appendPoint(x,y){
    points.push({x:x,y:y,sortBy:index.toString()});
    index++;
}

And create an insertPoint function that inserts a point object after any sortBy index:

insertPoint(150,100,0);

function insertPoint(x,y,afterIndex){
    points.push({x:x,y:y,sortBy:afterIndex.toString()+"Z"});
    points.sort(pointsCompare);
}

function pointsCompare(a,b){
    if(a.sortBy<b.sortBy){ return -1; }
    if(a.sortBy>b.sortBy){ return 1; }
    return(0);
}

Here's example code:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    .cf:before, .cf:after { content: " "; /* 1 */ display: table; /* 2 */ }
    .cf:after { clear: both; }
</style>

<script>
    $(function(){

    var points=[];
    var index=0;

    appendPoint(100,150);
    appendPoint(200,150);
    showPoints();
    insertPoint(150,100,0);
    showPoints();


    function appendPoint(x,y){
        points.push({x:x,y:y,sortBy:index.toString()});
        index++;
    }

    function insertPoint(x,y,afterIndex){
        points.push({x:x,y:y,sortBy:afterIndex.toString()+"Z"});
        points.sort(pointsCompare);
    }

    function pointsCompare(a,b){
        if(a.sortBy<b.sortBy){ return -1; }
        if(a.sortBy>b.sortBy){ return 1; }
        return(0);
    }

    function showPoints(){
        for(var i=0;i<points.length;i++){
            var pt=points[i];
            console.log(pt.sortBy+": "+pt.x+"/"+pt.y);
        }
    }

    }); // end $(function(){});
</script>

</head>

<body>

</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM