poly.js 7.7 KB
Newer Older
L
lang 已提交
1 2 3 4
// Poly path support NaN point
define(function (require) {

    var Path = require('zrender/graphic/Path');
L
lang 已提交
5 6
    var vec2 = require('zrender/core/vector');

7 8
    var vec2Min = vec2.min;
    var vec2Max = vec2.max;
L
lang 已提交
9 10 11 12 13 14 15 16 17

    var scaleAndAdd = vec2.scaleAndAdd;
    var v2Copy = vec2.copy;

    // Temporary variable
    var v = [];
    var cp0 = [];
    var cp1 = [];

L
lang 已提交
18 19 20 21
    function isPointNull(p) {
        return isNaN(p[0]) || isNaN(p[1]);
    }

22
    function drawSegment(
L
lang 已提交
23 24
        ctx, points, start, segLen, allLen,
        dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
25
    ) {
L
lang 已提交
26
        var prevIdx = 0;
L
lang 已提交
27
        var idx = start;
L
lang 已提交
28
        for (var k = 0; k < segLen; k++) {
L
lang 已提交
29
            var p = points[idx];
L
lang 已提交
30 31 32 33 34 35 36 37
            if (idx >= allLen || idx < 0) {
                break;
            }
            if (isPointNull(p)) {
                if (connectNulls) {
                    idx += dir;
                    continue;
                }
L
lang 已提交
38 39 40 41 42 43 44 45 46 47
                break;
            }

            if (idx === start) {
                ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
                v2Copy(cp0, p);
            }
            else {
                if (smooth > 0) {
                    var nextIdx = idx + dir;
L
lang 已提交
48 49 50 51 52 53 54 55
                    var nextP = points[nextIdx];
                    if (connectNulls) {
                        // Find next point not null
                        while (nextP && isPointNull(points[nextIdx])) {
                            nextIdx += dir;
                            nextP = points[nextIdx];
                        }
                    }
56 57 58 59

                    var ratioNextSeg = 0.5;
                    var prevP = points[prevIdx];
                    var nextP = points[nextIdx];
L
lang 已提交
60
                    // Last point
L
lang 已提交
61
                    if (!nextP || isPointNull(nextP)) {
L
lang 已提交
62
                        v2Copy(cp1, p);
L
lang 已提交
63 64
                    }
                    else {
L
lang 已提交
65 66
                        // If next data is null in not connect case
                        if (isPointNull(nextP) && !connectNulls) {
L
lang 已提交
67 68
                            nextP = p;
                        }
L
lang 已提交
69

L
lang 已提交
70
                        vec2.sub(v, nextP, prevP);
L
lang 已提交
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
                        var lenPrevSeg;
                        var lenNextSeg;
                        if (smoothMonotone === 'x' || smoothMonotone === 'y') {
                            var dim = smoothMonotone === 'x' ? 0 : 1;
                            lenPrevSeg = Math.abs(p[dim] - prevP[dim]);
                            lenNextSeg = Math.abs(p[dim] - nextP[dim]);
                        }
                        else {
                            lenPrevSeg = vec2.dist(p, prevP);
                            lenNextSeg = vec2.dist(p, nextP);
                        }

                        // Use ratio of seg length
                        ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);

                        scaleAndAdd(cp1, p, v, -smooth * (1 - ratioNextSeg));
L
lang 已提交
88
                    }
L
lang 已提交
89 90 91 92 93 94
                    // Smooth constraint
                    vec2Min(cp0, cp0, smoothMax);
                    vec2Max(cp0, cp0, smoothMin);
                    vec2Min(cp1, cp1, smoothMax);
                    vec2Max(cp1, cp1, smoothMin);

L
lang 已提交
95 96 97 98 99 100
                    ctx.bezierCurveTo(
                        cp0[0], cp0[1],
                        cp1[0], cp1[1],
                        p[0], p[1]
                    );
                    // cp0 of next segment
101
                    scaleAndAdd(cp0, p, v, smooth * ratioNextSeg);
L
lang 已提交
102 103 104 105 106 107
                }
                else {
                    ctx.lineTo(p[0], p[1]);
                }
            }

L
lang 已提交
108
            prevIdx = idx;
L
lang 已提交
109 110 111 112 113
            idx += dir;
        }

        return k;
    }
L
lang 已提交
114

L
lang 已提交
115
    function getBoundingBox(points, smoothConstraint) {
116 117
        var ptMin = [Infinity, Infinity];
        var ptMax = [-Infinity, -Infinity];
L
lang 已提交
118 119 120 121 122 123 124 125
        if (smoothConstraint) {
            for (var i = 0; i < points.length; i++) {
                var pt = points[i];
                if (pt[0] < ptMin[0]) { ptMin[0] = pt[0]; }
                if (pt[1] < ptMin[1]) { ptMin[1] = pt[1]; }
                if (pt[0] > ptMax[0]) { ptMax[0] = pt[0]; }
                if (pt[1] > ptMax[1]) { ptMax[1] = pt[1]; }
            }
126 127
        }
        return {
L
lang 已提交
128 129
            min: smoothConstraint ? ptMin : ptMax,
            max: smoothConstraint ? ptMax : ptMin
130 131 132
        };
    }

L
lang 已提交
133 134 135 136 137 138 139
    return {

        Polyline: Path.extend({

            type: 'ec-polyline',

            shape: {
L
lang 已提交
140 141
                points: [],

L
lang 已提交
142 143
                smooth: 0,

144 145
                smoothConstraint: true,

L
lang 已提交
146 147 148
                smoothMonotone: null,

                connectNulls: false
L
lang 已提交
149 150 151 152 153
            },

            style: {
                fill: null,

L
lang 已提交
154
                stroke: '#000'
L
lang 已提交
155 156 157 158 159 160 161 162
            },

            buildPath: function (ctx, shape) {
                var points = shape.points;

                var i = 0;
                var len = points.length;

L
lang 已提交
163
                var result = getBoundingBox(points, shape.smoothConstraint);
164

L
lang 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177
                if (shape.connectNulls) {
                    // Must remove first and last null values avoid draw error in polygon
                    for (; len > 0; len--) {
                        if (!isPointNull(points[len - 1])) {
                            break;
                        }
                    }
                    for (; i < len; i++) {
                        if (!isPointNull(points[i])) {
                            break;
                        }
                    }
                }
L
lang 已提交
178
                while (i < len) {
179 180
                    i += drawSegment(
                        ctx, points, i, len, len,
181
                        1, result.min, result.max, shape.smooth,
L
lang 已提交
182
                        shape.smoothMonotone, shape.connectNulls
183
                    ) + 1;
L
lang 已提交
184 185 186 187 188 189 190 191 192 193
                }
            }
        }),

        Polygon: Path.extend({

            type: 'ec-polygon',

            shape: {
                points: [],
194

L
lang 已提交
195
                // Offset between stacked base points and points
L
lang 已提交
196
                stackedOnPoints: [],
197

L
lang 已提交
198
                smooth: 0,
199

L
lang 已提交
200
                stackedOnSmooth: 0,
201 202 203

                smoothConstraint: true,

L
lang 已提交
204 205 206
                smoothMonotone: null,

                connectNulls: false
L
lang 已提交
207 208 209 210 211 212 213 214
            },

            buildPath: function (ctx, shape) {
                var points = shape.points;
                var stackedOnPoints = shape.stackedOnPoints;

                var i = 0;
                var len = points.length;
215
                var smoothMonotone = shape.smoothMonotone;
L
lang 已提交
216 217
                var bbox = getBoundingBox(points, shape.smoothConstraint);
                var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint);
L
lang 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231

                if (shape.connectNulls) {
                    // Must remove first and last null values avoid draw error in polygon
                    for (; len > 0; len--) {
                        if (!isPointNull(points[len - 1])) {
                            break;
                        }
                    }
                    for (; i < len; i++) {
                        if (!isPointNull(points[i])) {
                            break;
                        }
                    }
                }
L
lang 已提交
232
                while (i < len) {
L
lang 已提交
233
                    var k = drawSegment(
234
                        ctx, points, i, len, len,
235
                        1, bbox.min, bbox.max, shape.smooth,
L
lang 已提交
236
                        smoothMonotone, shape.connectNulls
L
lang 已提交
237 238
                    );
                    drawSegment(
L
lang 已提交
239
                        ctx, stackedOnPoints, i + k - 1, k, len,
240
                        -1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth,
L
lang 已提交
241
                        smoothMonotone, shape.connectNulls
L
lang 已提交
242 243 244 245
                    );
                    i += k + 1;

                    ctx.closePath();
L
lang 已提交
246 247 248 249 250
                }
            }
        })
    };
});