1 pv.SvgScene.area = function(scenes) { 2 var e = scenes.$g.firstChild; 3 if (!scenes.length) return e; 4 var s = scenes[0]; 5 6 /* segmented */ 7 if (s.segmented) return this.areaSegment(scenes); 8 9 /* visible */ 10 if (!s.visible) return e; 11 var fill = s.fillStyle, stroke = s.strokeStyle; 12 if (!fill.opacity && !stroke.opacity) return e; 13 14 /** @private Computes the straight path for the range [i, j]. */ 15 function path(i, j) { 16 var p1 = [], p2 = []; 17 for (var k = j; i <= k; i++, j--) { 18 var si = scenes[i], 19 sj = scenes[j], 20 pi = si.left + "," + si.top, 21 pj = (sj.left + sj.width) + "," + (sj.top + sj.height); 22 23 /* interpolate */ 24 if (i < k) { 25 var sk = scenes[i + 1], sl = scenes[j - 1]; 26 switch (s.interpolate) { 27 case "step-before": { 28 pi += "V" + sk.top; 29 pj += "H" + (sl.left + sl.width); 30 break; 31 } 32 case "step-after": { 33 pi += "H" + sk.left; 34 pj += "V" + (sl.top + sl.height); 35 break; 36 } 37 } 38 } 39 40 p1.push(pi); 41 p2.push(pj); 42 } 43 return p1.concat(p2).join("L"); 44 } 45 46 /** @private Computes the curved path for the range [i, j]. */ 47 function pathCurve(i, j) { 48 var pointsT = [], pointsB = [], pathT, pathB; 49 50 for (var k = j; i <= k; i++, j--) { 51 var sj = scenes[j]; 52 pointsT.push(scenes[i]); 53 pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); 54 } 55 56 if (s.interpolate == "basis") { 57 pathT = pv.SvgScene.curveBasis(pointsT); 58 pathB = pv.SvgScene.curveBasis(pointsB); 59 } else if (s.interpolate == "cardinal") { 60 pathT = pv.SvgScene.curveCardinal(pointsT, s.tension); 61 pathB = pv.SvgScene.curveCardinal(pointsB, s.tension); 62 } else { // monotone 63 pathT = pv.SvgScene.curveMonotone(pointsT); 64 pathB = pv.SvgScene.curveMonotone(pointsB); 65 } 66 67 return pointsT[0].left + "," + pointsT[0].top + pathT 68 + "L" + pointsB[0].left + "," + pointsB[0].top + pathB; 69 } 70 71 /* points */ 72 var d = [], si, sj; 73 for (var i = 0; i < scenes.length; i++) { 74 si = scenes[i]; if (!si.width && !si.height) continue; 75 for (var j = i + 1; j < scenes.length; j++) { 76 sj = scenes[j]; if (!sj.width && !sj.height) break; 77 } 78 if (i && (s.interpolate != "step-after")) i--; 79 if ((j < scenes.length) && (s.interpolate != "step-before")) j++; 80 d.push(((j - i > 2 81 && (s.interpolate == "basis" 82 || s.interpolate == "cardinal" 83 || s.interpolate == "monotone")) 84 ? pathCurve : path)(i, j - 1)); 85 i = j - 1; 86 } 87 if (!d.length) return e; 88 89 e = this.expect(e, "path", { 90 "shape-rendering": s.antialias ? null : "crispEdges", 91 "pointer-events": s.events, 92 "cursor": s.cursor, 93 "d": "M" + d.join("ZM") + "Z", 94 "fill": fill.color, 95 "fill-opacity": fill.opacity || null, 96 "stroke": stroke.color, 97 "stroke-opacity": stroke.opacity || null, 98 "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null 99 }); 100 return this.append(e, scenes, 0); 101 }; 102 103 pv.SvgScene.areaSegment = function(scenes) { 104 var e = scenes.$g.firstChild, s = scenes[0], pathsT, pathsB; 105 if (s.interpolate == "basis" 106 || s.interpolate == "cardinal" 107 || s.interpolate == "monotone") { 108 var pointsT = [], pointsB = []; 109 110 for (var i = 0, n = scenes.length; i < n; i++) { 111 var sj = scenes[n - i - 1]; 112 pointsT.push(scenes[i]); 113 pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); 114 } 115 116 if (s.interpolate == "basis") { 117 pathsT = this.curveBasisSegments(pointsT); 118 pathsB = this.curveBasisSegments(pointsB); 119 } else if (s.interpolate == "cardinal") { 120 pathsT = this.curveCardinalSegments(pointsT, s.tension); 121 pathsB = this.curveCardinalSegments(pointsB, s.tension); 122 } else { // monotone 123 pathsT = this.curveMonotoneSegments(pointsT); 124 pathsB = this.curveMonotoneSegments(pointsB); 125 } 126 } 127 128 for (var i = 0, n = scenes.length - 1; i < n; i++) { 129 var s1 = scenes[i], s2 = scenes[i + 1]; 130 131 /* visible */ 132 if (!s1.visible || !s2.visible) continue; 133 var fill = s1.fillStyle, stroke = s1.strokeStyle; 134 if (!fill.opacity && !stroke.opacity) continue; 135 136 var d; 137 if (pathsT) { 138 var pathT = pathsT[i], 139 pathB = "L" + pathsB[n - i - 1].substr(1); 140 141 d = pathT + pathB + "Z"; 142 } else { 143 /* interpolate */ 144 var si = s1, sj = s2; 145 switch (s1.interpolate) { 146 case "step-before": si = s2; break; 147 case "step-after": sj = s1; break; 148 } 149 150 /* path */ 151 d = "M" + s1.left + "," + si.top 152 + "L" + s2.left + "," + sj.top 153 + "L" + (s2.left + s2.width) + "," + (sj.top + sj.height) 154 + "L" + (s1.left + s1.width) + "," + (si.top + si.height) 155 + "Z"; 156 } 157 158 e = this.expect(e, "path", { 159 "shape-rendering": s1.antialias ? null : "crispEdges", 160 "pointer-events": s1.events, 161 "cursor": s1.cursor, 162 "d": d, 163 "fill": fill.color, 164 "fill-opacity": fill.opacity || null, 165 "stroke": stroke.color, 166 "stroke-opacity": stroke.opacity || null, 167 "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null 168 }); 169 e = this.append(e, scenes, i); 170 } 171 return e; 172 }; 173