define(function (require) {

    var arrayDiff = require('zrender/core/arrayDiff');

    function sign(val) {
        return val >= 0 ? 1 : -1;
    }

    function getStackedOnPoint(coordSys, data, idx) {
        var baseAxis = coordSys.getBaseAxis();
        var valueAxis = coordSys.getOtherAxis(baseAxis);
        var valueStart = baseAxis.onZero
            ? 0 : valueAxis.scale.getExtent()[0];

        var valueDim = valueAxis.dim;
        var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0;

        var stackedOnSameSign;
        var stackedOn = data.stackedOn;
        var val = data.get(valueDim, idx);
        // Find first stacked value with same sign
        while (stackedOn &&
            sign(stackedOn.get(valueDim, idx)) === sign(val)
        ) {
            stackedOnSameSign = stackedOn;
            break;
        }
        var stackedData = [];
        stackedData[baseDataOffset] = data.get(baseAxis.dim, idx);
        stackedData[1 - baseDataOffset] = stackedOnSameSign
            ? stackedOnSameSign.get(valueDim, idx, true) : valueStart;

        return coordSys.dataToPoint(stackedData);
    }

    return function (
        oldData, newData,
        oldStackedOnPoints, newStackedOnPoints,
        oldCoordSys, newCoordSys
    ) {

        var newIdList = newData.mapArray(newData.getId);
        var oldIdList = oldData.mapArray(oldData.getId);

        var currPoints = [];
        var nextPoints = [];
        // Points for stacking base line
        var currStackedPoints = [];
        var nextStackedPoints = [];

        var status = [];
        var sortedIndices = [];
        var rawIndices = [];

        // FIXME One data ?
        var diff = arrayDiff(oldIdList, newIdList);

        var dims = newCoordSys.dimensions;
        for (var i = 0; i < diff.length; i++) {
            var diffItem = diff[i];
            var pointAdded = true;

            // FIXME, animation is not so perfect when dataZoom window moves fast
            // Which is in case remvoing or add more than one data in the tail or head
            switch (diffItem.cmd) {
                case '=':
                    currPoints.push(oldData.getItemLayout(diffItem.idx));
                    nextPoints.push(newData.getItemLayout(diffItem.idx1));

                    currStackedPoints.push(oldStackedOnPoints[diffItem.idx]);
                    nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]);

                    rawIndices.push(newData.getRawIndex(diffItem.idx1));
                    break;
                case '+':
                    var idx = diffItem.idx;
                    currPoints.push(
                        oldCoordSys.dataToPoint([
                            newData.get(dims[0], idx, true), newData.get(dims[1], idx, true)
                        ])
                    );

                    nextPoints.push(newData.getItemLayout(idx).slice());

                    currStackedPoints.push(
                        getStackedOnPoint(oldCoordSys, newData, idx)
                    );
                    nextStackedPoints.push(newStackedOnPoints[idx]);

                    rawIndices.push(newData.getRawIndex(idx));
                    break;
                case '-':
                    var idx = diffItem.idx;
                    var rawIndex = oldData.getRawIndex(idx);
                    // Data is replaced. In the case of dynamic data queue
                    // FIXME FIXME FIXME
                    if (rawIndex !== idx) {
                        currPoints.push(oldData.getItemLayout(idx));
                        nextPoints.push(newCoordSys.dataToPoint([
                            oldData.get(dims[0], idx, true), oldData.get(dims[1], idx, true)
                        ]));

                        currStackedPoints.push(oldStackedOnPoints[idx]);
                        nextStackedPoints.push(
                            getStackedOnPoint(
                                newCoordSys, oldData, idx
                            )
                        );

                        rawIndices.push(rawIndex);
                    }
                    else {
                        pointAdded = false;
                    }
            }

            // Original indices
            if (pointAdded) {
                status.push(diffItem);
                sortedIndices.push(sortedIndices.length);
            }
        }

        // Diff result may be crossed if all items are changed
        // Sort by data index
        sortedIndices.sort(function (a, b) {
            return rawIndices[a] - rawIndices[b];
        });

        var sortedCurrPoints = [];
        var sortedNextPoints = [];

        var sortedCurrStackedPoints = [];
        var sortedNextStackedPoints = [];

        var sortedStatus = [];
        for (var i = 0; i < sortedIndices.length; i++) {
            var idx = sortedIndices[i];
            sortedCurrPoints[i] = currPoints[idx];
            sortedNextPoints[i] = nextPoints[idx];

            sortedCurrStackedPoints[i] = currStackedPoints[idx];
            sortedNextStackedPoints[i] = nextStackedPoints[idx];

            sortedStatus[i] = status[idx];
        }

        return {
            current: sortedCurrPoints,
            next: sortedNextPoints,

            stackedOnCurrent: sortedCurrStackedPoints,
            stackedOnNext: sortedNextStackedPoints,

            status: sortedStatus
        };
    };
});
@@ -2144,32 +2144,32 @@
         
-currPoints.push(
+var currentPt = 
 oldData.
@@ -2191,25 +2191,24 @@
 iffItem.idx)
-)
 ;%0A          
@@ -2217,32 +2217,29 @@
         
+var 
 nextP
-oints.push(
+t = 
 newData.
@@ -2266,16 +2266,324 @@
 em.idx1)
+;%0A                    // If previous data is NaN, use next point directly%0A                    if (isNaN(currentPt%5B0%5D) %7C%7C isNaN(currentPt%5B1%5D)) %7B%0A                        currentPt = nextPt.slice();%0A                    %7D%0A                    currPoints.push(currentPt);%0A                    nextPoints.push(nextPt
 );%0A%0A    

Fix line animation from empty data to number data