Comparing version 0.6.10 to 0.6.11
@@ -47,4 +47,22 @@ 'use strict'; | ||
/** | ||
* Check if the supplied value is an array. | ||
* | ||
* @param {*} value | ||
* | ||
* @return {bool} | ||
*/ | ||
/** | ||
* Remove the funnel and its events from the DOM. | ||
* | ||
* @return {void} | ||
*/ | ||
_createClass(D3Funnel, [{ | ||
key: 'draw', | ||
key: 'destroy', | ||
value: function destroy() { | ||
// D3's remove method appears to be sufficient for removing the events | ||
d3.select(this.selector).selectAll('svg').remove(); | ||
} | ||
@@ -63,13 +81,17 @@ /** | ||
*/ | ||
value: function draw(data, options) { | ||
}, { | ||
key: 'draw', | ||
value: function draw(data) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
// Remove any previous drawings | ||
this.destroy(); | ||
// Initialize chart options | ||
this._initialize(data, options); | ||
// Remove any previous drawings | ||
d3.select(this.selector).selectAll('svg').remove(); | ||
// Add the SVG | ||
this.svg = d3.select(this.selector).append('svg').attr('width', this.width).attr('height', this.height); | ||
this.sectionPaths = this._makePaths(); | ||
this.blockPaths = this._makePaths(); | ||
@@ -83,10 +105,8 @@ // Define color gradients | ||
if (this.isCurved) { | ||
this._drawTopOval(this.svg, this.sectionPaths); | ||
this._drawTopOval(this.svg, this.blockPaths); | ||
} | ||
// Add each block section | ||
this._drawSection(0); | ||
// Add each block | ||
this._drawBlock(0); | ||
} | ||
}, { | ||
key: '_initialize', | ||
@@ -101,17 +121,13 @@ /** | ||
*/ | ||
}, { | ||
key: '_initialize', | ||
value: function _initialize(data, options) { | ||
if (!isArray(data) || data.length === 0 || !isArray(data[0]) || data[0].length < 2) { | ||
throw { | ||
name: 'D3 Funnel Data Error', | ||
message: 'Funnel data is not valid.' | ||
}; | ||
throw new Error('Funnel data is not valid.'); | ||
} | ||
// Initialize options if not set | ||
options = typeof options !== 'undefined' ? options : {}; | ||
this.data = data; | ||
// Counter | ||
var i; | ||
var i = undefined; | ||
@@ -134,9 +150,11 @@ // Prepare the configuration settings based on the defaults | ||
if (options.hasOwnProperty('label')) { | ||
var validLabelOptions = /fontSize|fill/; | ||
var labelOption; | ||
for (labelOption in options.label) { | ||
if (labelOption.match(validLabelOptions)) { | ||
settings.label[labelOption] = options.label[labelOption]; | ||
} | ||
} | ||
(function () { | ||
var validLabelOptions = /fontSize|fill/; | ||
Object.keys(options.label).forEach(function (labelOption) { | ||
if (labelOption.match(validLabelOptions)) { | ||
settings.label[labelOption] = options.label[labelOption]; | ||
} | ||
}); | ||
})(); | ||
} | ||
@@ -154,3 +172,3 @@ this.label = settings.label; | ||
// Initialize the colors for each block section | ||
// Initialize the colors for each block | ||
var colorScale = d3.scale.category10(); | ||
@@ -193,7 +211,5 @@ for (i = 0; i < this.data.length; i++) { | ||
} | ||
}, { | ||
key: '_makePaths', | ||
/** | ||
* Create the paths to be used to define the discrete funnel sections and | ||
* Create the paths to be used to define the discrete funnel blocks and | ||
* returns the results in an array. | ||
@@ -203,2 +219,4 @@ * | ||
*/ | ||
}, { | ||
key: '_makePaths', | ||
value: function _makePaths() { | ||
@@ -240,5 +258,5 @@ var paths = []; | ||
// This is greedy in that the section will have a guranteed height and | ||
// the remaining is shared among the ratio, instead of being shared | ||
// according to the remaining minus the guranteed | ||
// This is greedy in that the block will have a guaranteed height | ||
// and the remaining is shared among the ratio, instead of being | ||
// shared according to the remaining minus the guaranteed | ||
if (this.minHeight !== false) { | ||
@@ -257,5 +275,5 @@ var height = this.height - this.minHeight * this.data.length; | ||
// Create the path definition for each funnel section | ||
// Create the path definition for each funnel block | ||
// Remember to loop back to the beginning point for a closed path | ||
for (i = 0; i < this.data.length; i++) { | ||
for (var i = 0; i < this.data.length; i++) { | ||
count = isArray(this.data[i][1]) ? this.data[i][1][0] : this.data[i][1]; | ||
@@ -283,3 +301,3 @@ | ||
// Stop velocity for pinched sections | ||
// Stop velocity for pinched blocks | ||
if (this.bottomPinch > 0) { | ||
@@ -292,17 +310,18 @@ // Check if we've reached the bottom of the pinch | ||
} | ||
// Pinch at the first sections relating to the bottom pinch | ||
// Pinch at the first blocks relating to the bottom pinch | ||
// Revert back to normal velocity after pinch | ||
} else { | ||
// Revert velocity back to the intial if we are using | ||
// static area's (prevents zero velocity if isInverted | ||
// and bottomPinch are non trivial and dynamicArea is false) | ||
if (!this.dynamicArea) { | ||
dx = this.dx; | ||
// Revert velocity back to the initial if we are using | ||
// static area's (prevents zero velocity if isInverted | ||
// and bottomPinch are non trivial and dynamicArea is | ||
// false) | ||
if (!this.dynamicArea) { | ||
dx = this.dx; | ||
} | ||
dx = i < this.bottomPinch ? 0 : dx; | ||
} | ||
dx = i < this.bottomPinch ? 0 : dx; | ||
} | ||
} | ||
// Calculate the position of next section | ||
// Calculate the position of next block | ||
nextLeftX = prevLeftX + dx; | ||
@@ -331,16 +350,16 @@ nextRightX = prevRightX - dx; | ||
} else { | ||
paths.push([ | ||
// Start position | ||
[prevLeftX, prevHeight, 'M'], | ||
// Move to right | ||
[prevRightX, prevHeight, 'L'], | ||
// Move down | ||
[nextRightX, nextHeight, 'L'], | ||
// Move to left | ||
[nextLeftX, nextHeight, 'L'], | ||
// Wrap back to top | ||
[prevLeftX, prevHeight, 'L']]); | ||
} | ||
paths.push([ | ||
// Start position | ||
[prevLeftX, prevHeight, 'M'], | ||
// Move to right | ||
[prevRightX, prevHeight, 'L'], | ||
// Move down | ||
[nextRightX, nextHeight, 'L'], | ||
// Move to left | ||
[nextLeftX, nextHeight, 'L'], | ||
// Wrap back to top | ||
[prevLeftX, prevHeight, 'L']]); | ||
} | ||
// Set the next section's previous position | ||
// Set the next block's previous position | ||
prevLeftX = nextLeftX; | ||
@@ -353,4 +372,2 @@ prevRightX = nextRightX; | ||
} | ||
}, { | ||
key: '_defineColorGradients', | ||
@@ -364,6 +381,8 @@ /** | ||
*/ | ||
}, { | ||
key: '_defineColorGradients', | ||
value: function _defineColorGradients(svg) { | ||
var defs = svg.append('defs'); | ||
// Create a gradient for each section | ||
// Create a gradient for each block | ||
for (var i = 0; i < this.data.length; i++) { | ||
@@ -383,6 +402,6 @@ var color = this.data[i][2]; | ||
for (var j = 0; j < stops.length; j++) { | ||
var stop = stops[j]; | ||
var _stop = stops[j]; | ||
gradient.append('stop').attr({ | ||
offset: stop[0] + '%', | ||
style: 'stop-color:' + stop[1] | ||
offset: _stop[0] + '%', | ||
style: 'stop-color:' + _stop[1] | ||
}); | ||
@@ -392,4 +411,2 @@ } | ||
} | ||
}, { | ||
key: '_drawTopOval', | ||
@@ -400,7 +417,9 @@ /** | ||
* @param {Object} svg | ||
* @param {Array} sectionPaths | ||
* @param {Array} blockPaths | ||
* | ||
* @return {void} | ||
*/ | ||
value: function _drawTopOval(svg, sectionPaths) { | ||
}, { | ||
key: '_drawTopOval', | ||
value: function _drawTopOval(svg, blockPaths) { | ||
var leftX = 0; | ||
@@ -415,4 +434,4 @@ var rightX = this.width; | ||
// Create path form top-most section | ||
var paths = sectionPaths[0]; | ||
// Create path from top-most block | ||
var paths = blockPaths[0]; | ||
var path = 'M' + leftX + ',' + paths[0][1] + ' Q' + centerX + ',' + (paths[1][1] + this.curveHeight - 10) + ' ' + rightX + ',' + paths[2][1] + ' M' + rightX + ',10' + ' Q' + centerX + ',0' + ' ' + leftX + ',10'; | ||
@@ -423,7 +442,5 @@ | ||
} | ||
}, { | ||
key: '_drawSection', | ||
/** | ||
* Draw the next section in the iteration. | ||
* Draw the next block in the iteration. | ||
* | ||
@@ -434,3 +451,7 @@ * @param {int} index | ||
*/ | ||
value: function _drawSection(index) { | ||
}, { | ||
key: '_drawBlock', | ||
value: function _drawBlock(index) { | ||
var _this = this; | ||
if (index === this.data.length) { | ||
@@ -444,14 +465,13 @@ return; | ||
// Fetch path element | ||
var path = this._getSectionPath(group, index); | ||
path.data(this._getSectionData(index)); | ||
var path = this._getBlockPath(group, index); | ||
path.data(this._getBlockData(index)); | ||
// Add animation components | ||
if (this.animation !== false) { | ||
var self = this; | ||
path.transition().duration(this.animation).ease('linear').attr('fill', this._getColor(index)).attr('d', this._getPathDefinition(index)).each('end', function () { | ||
self._drawSection(index + 1); | ||
_this._drawBlock(index + 1); | ||
}); | ||
} else { | ||
path.attr('fill', this._getColor(index)).attr('d', this._getPathDefinition(index)); | ||
this._drawSection(index + 1); | ||
this._drawBlock(index + 1); | ||
} | ||
@@ -469,6 +489,4 @@ | ||
this._addSectionLabel(group, index); | ||
this._addBlockLabel(group, index); | ||
} | ||
}, { | ||
key: '_getSectionPath', | ||
@@ -481,3 +499,5 @@ /** | ||
*/ | ||
value: function _getSectionPath(group, index) { | ||
}, { | ||
key: '_getBlockPath', | ||
value: function _getBlockPath(group, index) { | ||
var path = group.append('path'); | ||
@@ -491,4 +511,2 @@ | ||
} | ||
}, { | ||
key: '_addBeforeTransition', | ||
@@ -503,4 +521,6 @@ /** | ||
*/ | ||
}, { | ||
key: '_addBeforeTransition', | ||
value: function _addBeforeTransition(path, index) { | ||
var paths = this.sectionPaths[index]; | ||
var paths = this.blockPaths[index]; | ||
@@ -523,9 +543,7 @@ var beforePath = ''; | ||
} else { | ||
beforeFill = this._getColor(index); | ||
} | ||
beforeFill = this._getColor(index); | ||
} | ||
path.attr('d', beforePath).attr('fill', beforeFill); | ||
} | ||
}, { | ||
key: '_getSectionData', | ||
@@ -537,7 +555,10 @@ /** | ||
*/ | ||
value: function _getSectionData(index) { | ||
}, { | ||
key: '_getBlockData', | ||
value: function _getBlockData(index) { | ||
return [{ | ||
index: index, | ||
label: this.data[index][0], | ||
value: isArray(this.data[index][1]) ? this.data[index][1][0] : this.data[index][1], formattedValue: isArray(this.data[index][1]) ? this.data[index][1][1] : this.data[index][1].toLocaleString(), | ||
value: isArray(this.data[index][1]) ? this.data[index][1][0] : this.data[index][1], | ||
formattedValue: isArray(this.data[index][1]) ? this.data[index][1][1] : this.data[index][1].toLocaleString(), | ||
baseColor: this.data[index][2], | ||
@@ -547,4 +568,2 @@ fill: this._getColor(index) | ||
} | ||
}, { | ||
key: '_getColor', | ||
@@ -558,2 +577,4 @@ /** | ||
*/ | ||
}, { | ||
key: '_getColor', | ||
value: function _getColor(index) { | ||
@@ -566,4 +587,2 @@ if (this.fillType === 'solid') { | ||
} | ||
}, { | ||
key: '_getPathDefinition', | ||
@@ -575,6 +594,8 @@ /** | ||
*/ | ||
}, { | ||
key: '_getPathDefinition', | ||
value: function _getPathDefinition(index) { | ||
var pathStr = ''; | ||
var point = []; | ||
var paths = this.sectionPaths[index]; | ||
var paths = this.blockPaths[index]; | ||
@@ -588,4 +609,2 @@ for (var j = 0; j < paths.length; j++) { | ||
} | ||
}, { | ||
key: '_onMouseOver', | ||
@@ -597,7 +616,7 @@ /** | ||
*/ | ||
}, { | ||
key: '_onMouseOver', | ||
value: function _onMouseOver(data) { | ||
d3.select(this).attr('fill', shadeColor(data.baseColor, -0.2)); | ||
} | ||
}, { | ||
key: '_onMouseOut', | ||
@@ -609,7 +628,7 @@ /** | ||
*/ | ||
}, { | ||
key: '_onMouseOut', | ||
value: function _onMouseOut(data) { | ||
d3.select(this).attr('fill', data.fill); | ||
} | ||
}, { | ||
key: '_addSectionLabel', | ||
@@ -622,7 +641,9 @@ /** | ||
*/ | ||
value: function _addSectionLabel(group, index) { | ||
}, { | ||
key: '_addBlockLabel', | ||
value: function _addBlockLabel(group, index) { | ||
var i = index; | ||
var paths = this.sectionPaths[index]; | ||
var sectionData = this._getSectionData(index)[0]; | ||
var textStr = sectionData.label + ': ' + sectionData.formattedValue; | ||
var paths = this.blockPaths[index]; | ||
var blockData = this._getBlockData(index)[0]; | ||
var textStr = blockData.label + ': ' + blockData.formattedValue; | ||
var textFill = this.data[i][3] || this.label.fill; | ||
@@ -648,9 +669,2 @@ | ||
/** | ||
* Check if the supplied value is an array. | ||
* | ||
* @param {*} value | ||
* | ||
* @return {bool} | ||
*/ | ||
function isArray(value) { | ||
@@ -669,3 +683,3 @@ return Object.prototype.toString.call(value) === '[object Array]'; | ||
function extend(a, b) { | ||
var prop; | ||
var prop = undefined; | ||
for (prop in b) { | ||
@@ -692,6 +706,6 @@ if (b.hasOwnProperty(prop)) { | ||
var R = f >> 16, | ||
G = f >> 8 & 255; | ||
var B = f & 255; | ||
G = f >> 8 & 0x00FF; | ||
var B = f & 0x0000FF; | ||
var converted = 16777216 + (Math.round((t - R) * p) + R) * 65536 + (Math.round((t - G) * p) + G) * 256 + (Math.round((t - B) * p) + B); | ||
var converted = 0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B); | ||
@@ -698,0 +712,0 @@ return '#' + converted.toString(16).slice(1); |
@@ -1,2 +0,2 @@ | ||
/*! d3-funnel - v0.6.10 | 2015 */ | ||
"use strict";function _classCallCheck(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function t(t,i){for(var e=0;e<i.length;e++){var h=i[e];h.enumerable=h.enumerable||!1,h.configurable=!0,"value"in h&&(h.writable=!0),Object.defineProperty(t,h.key,h)}}return function(i,e,h){return e&&t(i.prototype,e),h&&t(i,h),i}}();!function(t,i){function e(t){return"[object Array]"===Object.prototype.toString.call(t)}function h(t,i){var e;for(e in i)i.hasOwnProperty(e)&&(t[e]=i[e]);return t}function s(t,i){var e=parseInt(t.slice(1),16),h=0>i?0:255,s=0>i?-1*i:i,a=e>>16,n=e>>8&255,o=255&e,r=16777216+65536*(Math.round((h-a)*s)+a)+256*(Math.round((h-n)*s)+n)+(Math.round((h-o)*s)+o);return"#"+r.toString(16).slice(1)}var a=function(){function t(i){_classCallCheck(this,t),this.selector=i,this.defaults={width:350,height:400,bottomWidth:1/3,bottomPinch:0,isCurved:!1,curveHeight:20,fillType:"solid",isInverted:!1,hoverEffects:!1,dynamicArea:!1,minHeight:!1,animation:!1,label:{fontSize:"14px",fill:"#fff"}}}return _createClass(t,[{key:"draw",value:function(t,e){this._initialize(t,e),i.select(this.selector).selectAll("svg").remove(),this.svg=i.select(this.selector).append("svg").attr("width",this.width).attr("height",this.height),this.sectionPaths=this._makePaths(),"gradient"===this.fillType&&this._defineColorGradients(this.svg),this.isCurved&&this._drawTopOval(this.svg,this.sectionPaths),this._drawSection(0)}},{key:"_initialize",value:function(t,s){if(!e(t)||0===t.length||!e(t[0])||t[0].length<2)throw{name:"D3 Funnel Data Error",message:"Funnel data is not valid."};s="undefined"!=typeof s?s:{},this.data=t;var a,n=h({},this.defaults);n.width=parseInt(i.select(this.selector).style("width"),10),n.height=parseInt(i.select(this.selector).style("height"),10);var o=Object.keys(s);for(a=0;a<o.length;a++)"label"!==o[a]&&(n[o[a]]=s[o[a]]);if(s.hasOwnProperty("label")){var r,l=/fontSize|fill/;for(r in s.label)r.match(l)&&(n.label[r]=s.label[r])}this.label=n.label,n.width<=0&&(n.width=this.defaults.width),n.height<=0&&(n.height=this.defaults.height);var d=i.scale.category10();for(a=0;a<this.data.length;a++){var c=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i;"2"in this.data[a]&&c.test(this.data[a][2])||(this.data[a][2]=d(a))}this.width=n.width,this.height=n.height,this.bottomWidth=n.width*n.bottomWidth,this.bottomPinch=n.bottomPinch,this.isCurved=n.isCurved,this.curveHeight=n.curveHeight,this.fillType=n.fillType,this.isInverted=n.isInverted,this.hoverEffects=n.hoverEffects,this.dynamicArea=n.dynamicArea,this.minHeight=n.minHeight,this.animation=n.animation,this.bottomLeftX=(this.width-this.bottomWidth)/2,this.dx=this.bottomPinch>0?this.bottomLeftX/(t.length-this.bottomPinch):this.bottomLeftX/t.length,this.dy=this.isCurved?(this.height-this.curveHeight)/t.length:this.height/t.length,this.onItemClick=n.onItemClick}},{key:"_makePaths",value:function(){var t=[],i=this.dx,h=this.dy,s=0,a=this.width,n=0;this.isInverted&&(s=this.bottomLeftX,a=this.width-this.bottomLeftX);var o=0,r=0,l=0,d=this.width/2;this.isCurved&&(n=10);var c=this.width,f=0,u=this.height*(this.width+this.bottomWidth)/2,v=2*this.height/(this.width-this.bottomWidth);if(this.minHeight!==!1){var g=this.height-this.minHeight*this.data.length;u=g*(this.width+this.bottomWidth)/2}for(var m=0,b=0,p=0;p<this.data.length;p++)m+=e(this.data[p][1])?this.data[p][1][0]:this.data[p][1];for(p=0;p<this.data.length;p++){if(b=e(this.data[p][1])?this.data[p][1][0]:this.data[p][1],this.dynamicArea){var y=b/m,w=y*u;this.minHeight!==!1&&(w+=this.minHeight*(this.width+this.bottomWidth)/2),f=Math.sqrt((v*c*c-4*w)/v),i=c/2-f/2,h=2*w/(c+f),this.isCurved&&(h-=this.curveHeight/this.data.length),c=f}this.bottomPinch>0&&(this.isInverted?(this.dynamicArea||(i=this.dx),i=p<this.bottomPinch?0:i):p>=this.data.length-this.bottomPinch&&(i=0)),o=s+i,r=a-i,l=n+h,this.isInverted&&(o=s-i,r=a+i),t.push(this.isCurved?[[s,n,"M"],[d,n+(this.curveHeight-10),"Q"],[a,n,""],[r,l,"L"],[r,l,"M"],[d,l+this.curveHeight,"Q"],[o,l,""],[s,n,"L"]]:[[s,n,"M"],[a,n,"L"],[r,l,"L"],[o,l,"L"],[s,n,"L"]]),s=o,a=r,n=l}return t}},{key:"_defineColorGradients",value:function(t){for(var i=t.append("defs"),e=0;e<this.data.length;e++)for(var h=this.data[e][2],a=s(h,-.25),n=i.append("linearGradient").attr({id:"gradient-"+e}),o=[[0,a],[40,h],[60,h],[100,a]],r=0;r<o.length;r++){var l=o[r];n.append("stop").attr({offset:l[0]+"%",style:"stop-color:"+l[1]})}}},{key:"_drawTopOval",value:function(t,i){var e=0,h=this.width,a=this.width/2;this.isInverted&&(e=this.bottomLeftX,h=this.width-this.bottomLeftX);var n=i[0],o="M"+e+","+n[0][1]+" Q"+a+","+(n[1][1]+this.curveHeight-10)+" "+h+","+n[2][1]+" M"+h+",10 Q"+a+",0 "+e+",10";t.append("path").attr("fill",s(this.data[0][2],-.4)).attr("d",o)}},{key:"_drawSection",value:function(t){if(t!==this.data.length){var i=this.svg.append("g"),e=this._getSectionPath(i,t);if(e.data(this._getSectionData(t)),this.animation!==!1){var h=this;e.transition().duration(this.animation).ease("linear").attr("fill",this._getColor(t)).attr("d",this._getPathDefinition(t)).each("end",function(){h._drawSection(t+1)})}else e.attr("fill",this._getColor(t)).attr("d",this._getPathDefinition(t)),this._drawSection(t+1);this.hoverEffects&&e.on("mouseover",this._onMouseOver).on("mouseout",this._onMouseOut),this.onItemClick&&e.on("click",this.onItemClick),this._addSectionLabel(i,t)}}},{key:"_getSectionPath",value:function(t,i){var e=t.append("path");return this.animation!==!1&&this._addBeforeTransition(e,i),e}},{key:"_addBeforeTransition",value:function(t,i){var e=this.sectionPaths[i],h="",s="";h=this.isCurved?"M"+e[0][0]+","+e[0][1]+" Q"+e[1][0]+","+e[1][1]+" "+e[2][0]+","+e[2][1]+" L"+e[2][0]+","+e[2][1]+" M"+e[2][0]+","+e[2][1]+" Q"+e[1][0]+","+e[1][1]+" "+e[0][0]+","+e[0][1]:"M"+e[0][0]+","+e[0][1]+" L"+e[1][0]+","+e[1][1]+" L"+e[1][0]+","+e[1][1]+" L"+e[0][0]+","+e[0][1],s=this._getColor("solid"===this.fillType?i>0?i-1:i:i),t.attr("d",h).attr("fill",s)}},{key:"_getSectionData",value:function(t){return[{index:t,label:this.data[t][0],value:e(this.data[t][1])?this.data[t][1][0]:this.data[t][1],formattedValue:e(this.data[t][1])?this.data[t][1][1]:this.data[t][1].toLocaleString(),baseColor:this.data[t][2],fill:this._getColor(t)}]}},{key:"_getColor",value:function(t){return"solid"===this.fillType?this.data[t][2]:"url(#gradient-"+t+")"}},{key:"_getPathDefinition",value:function(t){for(var i="",e=[],h=this.sectionPaths[t],s=0;s<h.length;s++)e=h[s],i+=e[2]+e[0]+","+e[1]+" ";return i}},{key:"_onMouseOver",value:function(t){i.select(this).attr("fill",s(t.baseColor,-.2))}},{key:"_onMouseOut",value:function(t){i.select(this).attr("fill",t.fill)}},{key:"_addSectionLabel",value:function(t,i){var e=i,h=this.sectionPaths[i],s=this._getSectionData(i)[0],a=s.label+": "+s.formattedValue,n=this.data[e][3]||this.label.fill,o=this.width/2,r=this.isCurved?(h[2][1]+h[3][1])/2+this.curveHeight/this.data.length:(h[1][1]+h[2][1])/2;t.append("text").text(a).attr({x:o,y:r,"text-anchor":"middle","dominant-baseline":"middle",fill:n,"pointer-events":"none"}).style("font-size",this.label.fontSize)}}]),t}();t.D3Funnel=a}(window,d3); | ||
/*! d3-funnel - v0.6.11 | 2015 */ | ||
"use strict";function _classCallCheck(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function t(t,i){for(var e=0;e<i.length;e++){var h=i[e];h.enumerable=h.enumerable||!1,h.configurable=!0,"value"in h&&(h.writable=!0),Object.defineProperty(t,h.key,h)}}return function(i,e,h){return e&&t(i.prototype,e),h&&t(i,h),i}}();!function(t,i){function e(t){return"[object Array]"===Object.prototype.toString.call(t)}function h(t,i){var e=void 0;for(e in i)i.hasOwnProperty(e)&&(t[e]=i[e]);return t}function a(t,i){var e=parseInt(t.slice(1),16),h=0>i?0:255,a=0>i?-1*i:i,s=e>>16,n=e>>8&255,o=255&e,r=16777216+65536*(Math.round((h-s)*a)+s)+256*(Math.round((h-n)*a)+n)+(Math.round((h-o)*a)+o);return"#"+r.toString(16).slice(1)}var s=function(){function t(i){_classCallCheck(this,t),this.selector=i,this.defaults={width:350,height:400,bottomWidth:1/3,bottomPinch:0,isCurved:!1,curveHeight:20,fillType:"solid",isInverted:!1,hoverEffects:!1,dynamicArea:!1,minHeight:!1,animation:!1,label:{fontSize:"14px",fill:"#fff"}}}return _createClass(t,[{key:"destroy",value:function(){i.select(this.selector).selectAll("svg").remove()}},{key:"draw",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];this.destroy(),this._initialize(t,e),this.svg=i.select(this.selector).append("svg").attr("width",this.width).attr("height",this.height),this.blockPaths=this._makePaths(),"gradient"===this.fillType&&this._defineColorGradients(this.svg),this.isCurved&&this._drawTopOval(this.svg,this.blockPaths),this._drawBlock(0)}},{key:"_initialize",value:function(t,a){if(!e(t)||0===t.length||!e(t[0])||t[0].length<2)throw new Error("Funnel data is not valid.");this.data=t;var s=void 0,n=h({},this.defaults);n.width=parseInt(i.select(this.selector).style("width"),10),n.height=parseInt(i.select(this.selector).style("height"),10);var o=Object.keys(a);for(s=0;s<o.length;s++)"label"!==o[s]&&(n[o[s]]=a[o[s]]);a.hasOwnProperty("label")&&!function(){var t=/fontSize|fill/;Object.keys(a.label).forEach(function(i){i.match(t)&&(n.label[i]=a.label[i])})}(),this.label=n.label,n.width<=0&&(n.width=this.defaults.width),n.height<=0&&(n.height=this.defaults.height);var r=i.scale.category10();for(s=0;s<this.data.length;s++){var l=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i;"2"in this.data[s]&&l.test(this.data[s][2])||(this.data[s][2]=r(s))}this.width=n.width,this.height=n.height,this.bottomWidth=n.width*n.bottomWidth,this.bottomPinch=n.bottomPinch,this.isCurved=n.isCurved,this.curveHeight=n.curveHeight,this.fillType=n.fillType,this.isInverted=n.isInverted,this.hoverEffects=n.hoverEffects,this.dynamicArea=n.dynamicArea,this.minHeight=n.minHeight,this.animation=n.animation,this.bottomLeftX=(this.width-this.bottomWidth)/2,this.dx=this.bottomPinch>0?this.bottomLeftX/(t.length-this.bottomPinch):this.bottomLeftX/t.length,this.dy=this.isCurved?(this.height-this.curveHeight)/t.length:this.height/t.length,this.onItemClick=n.onItemClick}},{key:"_makePaths",value:function(){var t=[],i=this.dx,h=this.dy,a=0,s=this.width,n=0;this.isInverted&&(a=this.bottomLeftX,s=this.width-this.bottomLeftX);var o=0,r=0,l=0,d=this.width/2;this.isCurved&&(n=10);var c=this.width,u=0,f=this.height*(this.width+this.bottomWidth)/2,v=2*this.height/(this.width-this.bottomWidth);if(this.minHeight!==!1){var g=this.height-this.minHeight*this.data.length;f=g*(this.width+this.bottomWidth)/2}for(var m=0,b=0,y=0;y<this.data.length;y++)m+=e(this.data[y][1])?this.data[y][1][0]:this.data[y][1];for(var y=0;y<this.data.length;y++){if(b=e(this.data[y][1])?this.data[y][1][0]:this.data[y][1],this.dynamicArea){var k=b/m,p=k*f;this.minHeight!==!1&&(p+=this.minHeight*(this.width+this.bottomWidth)/2),u=Math.sqrt((v*c*c-4*p)/v),i=c/2-u/2,h=2*p/(c+u),this.isCurved&&(h-=this.curveHeight/this.data.length),c=u}this.bottomPinch>0&&(this.isInverted?(this.dynamicArea||(i=this.dx),i=y<this.bottomPinch?0:i):y>=this.data.length-this.bottomPinch&&(i=0)),o=a+i,r=s-i,l=n+h,this.isInverted&&(o=a-i,r=s+i),t.push(this.isCurved?[[a,n,"M"],[d,n+(this.curveHeight-10),"Q"],[s,n,""],[r,l,"L"],[r,l,"M"],[d,l+this.curveHeight,"Q"],[o,l,""],[a,n,"L"]]:[[a,n,"M"],[s,n,"L"],[r,l,"L"],[o,l,"L"],[a,n,"L"]]),a=o,s=r,n=l}return t}},{key:"_defineColorGradients",value:function(t){for(var i=t.append("defs"),e=0;e<this.data.length;e++)for(var h=this.data[e][2],s=a(h,-.25),n=i.append("linearGradient").attr({id:"gradient-"+e}),o=[[0,s],[40,h],[60,h],[100,s]],r=0;r<o.length;r++){var l=o[r];n.append("stop").attr({offset:l[0]+"%",style:"stop-color:"+l[1]})}}},{key:"_drawTopOval",value:function(t,i){var e=0,h=this.width,s=this.width/2;this.isInverted&&(e=this.bottomLeftX,h=this.width-this.bottomLeftX);var n=i[0],o="M"+e+","+n[0][1]+" Q"+s+","+(n[1][1]+this.curveHeight-10)+" "+h+","+n[2][1]+" M"+h+",10 Q"+s+",0 "+e+",10";t.append("path").attr("fill",a(this.data[0][2],-.4)).attr("d",o)}},{key:"_drawBlock",value:function(t){var i=this;if(t!==this.data.length){var e=this.svg.append("g"),h=this._getBlockPath(e,t);h.data(this._getBlockData(t)),this.animation!==!1?h.transition().duration(this.animation).ease("linear").attr("fill",this._getColor(t)).attr("d",this._getPathDefinition(t)).each("end",function(){i._drawBlock(t+1)}):(h.attr("fill",this._getColor(t)).attr("d",this._getPathDefinition(t)),this._drawBlock(t+1)),this.hoverEffects&&h.on("mouseover",this._onMouseOver).on("mouseout",this._onMouseOut),this.onItemClick&&h.on("click",this.onItemClick),this._addBlockLabel(e,t)}}},{key:"_getBlockPath",value:function(t,i){var e=t.append("path");return this.animation!==!1&&this._addBeforeTransition(e,i),e}},{key:"_addBeforeTransition",value:function(t,i){var e=this.blockPaths[i],h="",a="";h=this.isCurved?"M"+e[0][0]+","+e[0][1]+" Q"+e[1][0]+","+e[1][1]+" "+e[2][0]+","+e[2][1]+" L"+e[2][0]+","+e[2][1]+" M"+e[2][0]+","+e[2][1]+" Q"+e[1][0]+","+e[1][1]+" "+e[0][0]+","+e[0][1]:"M"+e[0][0]+","+e[0][1]+" L"+e[1][0]+","+e[1][1]+" L"+e[1][0]+","+e[1][1]+" L"+e[0][0]+","+e[0][1],a=this._getColor("solid"===this.fillType?i>0?i-1:i:i),t.attr("d",h).attr("fill",a)}},{key:"_getBlockData",value:function(t){return[{index:t,label:this.data[t][0],value:e(this.data[t][1])?this.data[t][1][0]:this.data[t][1],formattedValue:e(this.data[t][1])?this.data[t][1][1]:this.data[t][1].toLocaleString(),baseColor:this.data[t][2],fill:this._getColor(t)}]}},{key:"_getColor",value:function(t){return"solid"===this.fillType?this.data[t][2]:"url(#gradient-"+t+")"}},{key:"_getPathDefinition",value:function(t){for(var i="",e=[],h=this.blockPaths[t],a=0;a<h.length;a++)e=h[a],i+=e[2]+e[0]+","+e[1]+" ";return i}},{key:"_onMouseOver",value:function(t){i.select(this).attr("fill",a(t.baseColor,-.2))}},{key:"_onMouseOut",value:function(t){i.select(this).attr("fill",t.fill)}},{key:"_addBlockLabel",value:function(t,i){var e=i,h=this.blockPaths[i],a=this._getBlockData(i)[0],s=a.label+": "+a.formattedValue,n=this.data[e][3]||this.label.fill,o=this.width/2,r=this.isCurved?(h[2][1]+h[3][1])/2+this.curveHeight/this.data.length:(h[1][1]+h[2][1])/2;t.append("text").text(s).attr({x:o,y:r,"text-anchor":"middle","dominant-baseline":"middle",fill:n,"pointer-events":"none"}).style("font-size",this.label.fontSize)}}]),t}();t.D3Funnel=s}(window,d3); |
@@ -5,2 +5,3 @@ var gulp = require('gulp'); | ||
var babel = require('gulp-babel'); | ||
var mocha = require('gulp-mocha-phantomjs'); | ||
var rename = require('gulp-rename'); | ||
@@ -13,23 +14,38 @@ var uglify = require('gulp-uglify'); | ||
gulp.task('build', function() { | ||
return gulp.src('./src/d3-funnel/d3-funnel.js') | ||
.pipe(jshint()) | ||
.pipe(jshint.reporter('default')) | ||
.pipe(jshint.reporter('fail')) | ||
.pipe(jscs({ | ||
esnext: true, | ||
verbose: true | ||
})) | ||
.pipe(babel()) | ||
.pipe(gulp.dest('./dist/')) | ||
.pipe(rename({ | ||
extname: '.min.js'} | ||
)) | ||
.pipe(uglify()) | ||
.pipe(header(banner, { | ||
pkg: pkg | ||
})) | ||
.pipe(gulp.dest('./dist/')); | ||
var src = ['./src/d3-funnel/d3-funnel.js']; | ||
gulp.task('test-format', function () { | ||
return gulp.src(src) | ||
.pipe(jshint()) | ||
.pipe(jshint.reporter('default')) | ||
.pipe(jshint.reporter('fail')) | ||
.pipe(jscs({ | ||
configPath: './.jscsrc' | ||
})); | ||
}); | ||
gulp.task('compile', function () { | ||
return gulp.src(src) | ||
.pipe(babel()) | ||
.pipe(gulp.dest('./compiled/')); | ||
}); | ||
gulp.task('test-mocha', ['compile'], function () { | ||
return gulp.src(['test/test.html']) | ||
.pipe(mocha({reporter: 'spec'})); | ||
}); | ||
gulp.task('build', ['test-format', 'test-mocha'], function () { | ||
return gulp.src(['./compiled/d3-funnel.js']) | ||
.pipe(gulp.dest('./dist/')) | ||
.pipe(rename({ | ||
extname: '.min.js'} | ||
)) | ||
.pipe(uglify()) | ||
.pipe(header(banner, { | ||
pkg: pkg | ||
})) | ||
.pipe(gulp.dest('./dist/')); | ||
}); | ||
gulp.task('default', ['build']); |
{ | ||
"name": "d3-funnel", | ||
"version": "0.6.10", | ||
"version": "0.6.11", | ||
"description": "A library for rendering SVG funnel charts using D3.js", | ||
@@ -14,13 +14,16 @@ "author": "Jake Zatecky", | ||
"devDependencies": { | ||
"chai": "^3.2.0", | ||
"gulp": "^3.9.0", | ||
"gulp-babel": "^5.1.0", | ||
"gulp-babel": "^5.2.0", | ||
"gulp-header": "^1.2.2", | ||
"gulp-jscs": "^1.6.0", | ||
"gulp-jshint": "^1.11.0", | ||
"gulp-jscs": "^2.0.0", | ||
"gulp-jshint": "^1.11.2", | ||
"gulp-mocha-phantomjs": "^0.8.1", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-uglify": "^1.2.0" | ||
"gulp-uglify": "^1.2.0", | ||
"mocha": "^2.2.5" | ||
}, | ||
"dependencies": { | ||
"d3": "~3.5.5" | ||
"d3": "~3.5.6" | ||
} | ||
} |
# D3 Funnel | ||
[![npm](https://img.shields.io/npm/v/d3-funnel.svg)](https://www.npmjs.com/package/d3-funnel) | ||
[![Build Status](https://travis-ci.org/jakezatecky/d3-funnel.svg?branch=master)](https://travis-ci.org/jakezatecky/d3-funnel) | ||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jakezatecky/d3-funnel/master/LICENSE.txt) | ||
**D3Funnel** is an extensible, open-source JavaScript library for rendering | ||
@@ -46,6 +50,6 @@ funnel charts using the [D3.js][d3] library. | ||
| `bottomWidth` | The percent of total width the bottom should be. | float | `1 / 3` | | ||
| `bottomPinch` | How many sections to pinch on the bottom to create a "neck". | int | `0` | | ||
| `bottomPinch` | How many blocks to pinch on the bottom to create a "neck". | int | `0` | | ||
| `isCurved` | Whether the funnel is curved. | bool | `false` | | ||
| `curveHeight` | The curvature amount (if `isCurved` is `true`). | int | `20` | | ||
| `fillType` | Either `"solid"` or `"gradient"`. | string | `'solid'` | | ||
| `fillType` | Either `'solid'` or `'gradient'`. | string | `'solid'` | | ||
| `isInverted` | Whether the funnel is inverted (like a pyramid). | bool | `false` | | ||
@@ -60,2 +64,10 @@ | `hoverEffects` | Whether the funnel has effects on hover. | bool | `false` | | ||
## API | ||
Additional methods beyond `draw()` are accessible after instantiating the chart: | ||
| Method | Description | | ||
| ---------------- | --------------------------------------------------------------------------- | | ||
| `destroy()` | Removes the funnel and its events from the DOM. | | ||
## Advanced Data | ||
@@ -62,0 +74,0 @@ |
@@ -1,2 +0,2 @@ | ||
(function(global, d3) { | ||
((global, d3) => { | ||
@@ -35,4 +35,4 @@ /* global d3 */ | ||
fontSize: '14px', | ||
fill: '#fff' | ||
} | ||
fill: '#fff', | ||
}, | ||
}; | ||
@@ -42,2 +42,13 @@ } | ||
/** | ||
* Remove the funnel and its events from the DOM. | ||
* | ||
* @return {void} | ||
*/ | ||
destroy() | ||
{ | ||
// D3's remove method appears to be sufficient for removing the events | ||
d3.select(this.selector).selectAll('svg').remove(); | ||
} | ||
/** | ||
* Draw the chart inside the container with the data and configuration | ||
@@ -54,10 +65,10 @@ * specified. This will remove any previous SVG elements in the container | ||
*/ | ||
draw(data, options) | ||
draw(data, options = {}) | ||
{ | ||
// Remove any previous drawings | ||
this.destroy(); | ||
// Initialize chart options | ||
this._initialize(data, options); | ||
// Remove any previous drawings | ||
d3.select(this.selector).selectAll('svg').remove(); | ||
// Add the SVG | ||
@@ -69,3 +80,3 @@ this.svg = d3.select(this.selector) | ||
this.sectionPaths = this._makePaths(); | ||
this.blockPaths = this._makePaths(); | ||
@@ -79,7 +90,7 @@ // Define color gradients | ||
if (this.isCurved) { | ||
this._drawTopOval(this.svg, this.sectionPaths); | ||
this._drawTopOval(this.svg, this.blockPaths); | ||
} | ||
// Add each block section | ||
this._drawSection(0); | ||
// Add each block | ||
this._drawBlock(0); | ||
} | ||
@@ -98,19 +109,13 @@ | ||
if (!isArray(data) || data.length === 0 || !isArray(data[0]) || data[0].length < 2) { | ||
throw { | ||
name: 'D3 Funnel Data Error', | ||
message: 'Funnel data is not valid.' | ||
}; | ||
throw new Error('Funnel data is not valid.'); | ||
} | ||
// Initialize options if not set | ||
options = typeof options !== 'undefined' ? options : {}; | ||
this.data = data; | ||
// Counter | ||
var i; | ||
let i; | ||
// Prepare the configuration settings based on the defaults | ||
// Set the default width and height based on the container | ||
var settings = extend({}, this.defaults); | ||
let settings = extend({}, this.defaults); | ||
settings.width = parseInt(d3.select(this.selector).style('width'), 10); | ||
@@ -120,3 +125,3 @@ settings.height = parseInt(d3.select(this.selector).style('height'), 10); | ||
// Overwrite default settings with user options | ||
var keys = Object.keys(options); | ||
let keys = Object.keys(options); | ||
for (i = 0; i < keys.length; i++) { | ||
@@ -130,9 +135,9 @@ if (keys[i] !== 'label') { | ||
if (options.hasOwnProperty('label')) { | ||
var validLabelOptions = /fontSize|fill/; | ||
var labelOption; | ||
for (labelOption in options.label) { | ||
let validLabelOptions = /fontSize|fill/; | ||
Object.keys(options.label).forEach((labelOption) => { | ||
if (labelOption.match(validLabelOptions)) { | ||
settings.label[labelOption] = options.label[labelOption]; | ||
} | ||
} | ||
}); | ||
} | ||
@@ -150,6 +155,6 @@ this.label = settings.label; | ||
// Initialize the colors for each block section | ||
var colorScale = d3.scale.category10(); | ||
// Initialize the colors for each block | ||
let colorScale = d3.scale.category10(); | ||
for (i = 0; i < this.data.length; i++) { | ||
var hexExpression = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i; | ||
let hexExpression = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i; | ||
@@ -182,9 +187,9 @@ // If a color is not set for the record, add one | ||
this.dx = this.bottomPinch > 0 ? | ||
this.bottomLeftX / (data.length - this.bottomPinch) : | ||
this.bottomLeftX / data.length; | ||
this.bottomLeftX / (data.length - this.bottomPinch) : | ||
this.bottomLeftX / data.length; | ||
// Change in y direction | ||
// Curved chart needs reserved pixels to account for curvature | ||
this.dy = this.isCurved ? | ||
(this.height - this.curveHeight) / data.length : | ||
this.height / data.length; | ||
(this.height - this.curveHeight) / data.length : | ||
this.height / data.length; | ||
@@ -196,3 +201,3 @@ // Support for events | ||
/** | ||
* Create the paths to be used to define the discrete funnel sections and | ||
* Create the paths to be used to define the discrete funnel blocks and | ||
* returns the results in an array. | ||
@@ -204,12 +209,12 @@ * | ||
{ | ||
var paths = []; | ||
let paths = []; | ||
// Initialize velocity | ||
var dx = this.dx; | ||
var dy = this.dy; | ||
let dx = this.dx; | ||
let dy = this.dy; | ||
// Initialize starting positions | ||
var prevLeftX = 0; | ||
var prevRightX = this.width; | ||
var prevHeight = 0; | ||
let prevLeftX = 0; | ||
let prevRightX = this.width; | ||
let prevHeight = 0; | ||
@@ -223,7 +228,7 @@ // Start from the bottom for inverted | ||
// Initialize next positions | ||
var nextLeftX = 0; | ||
var nextRightX = 0; | ||
var nextHeight = 0; | ||
let nextLeftX = 0; | ||
let nextRightX = 0; | ||
let nextHeight = 0; | ||
var middle = this.width / 2; | ||
let middle = this.width / 2; | ||
@@ -235,27 +240,27 @@ // Move down if there is an initial curve | ||
var topBase = this.width; | ||
var bottomBase = 0; | ||
let topBase = this.width; | ||
let bottomBase = 0; | ||
var totalArea = this.height * (this.width + this.bottomWidth) / 2; | ||
var slope = 2 * this.height / (this.width - this.bottomWidth); | ||
let totalArea = this.height * (this.width + this.bottomWidth) / 2; | ||
let slope = 2 * this.height / (this.width - this.bottomWidth); | ||
// This is greedy in that the section will have a guranteed height and | ||
// the remaining is shared among the ratio, instead of being shared | ||
// according to the remaining minus the guranteed | ||
// This is greedy in that the block will have a guaranteed height | ||
// and the remaining is shared among the ratio, instead of being | ||
// shared according to the remaining minus the guaranteed | ||
if (this.minHeight !== false) { | ||
var height = (this.height - this.minHeight * this.data.length); | ||
let height = (this.height - this.minHeight * this.data.length); | ||
totalArea = height * (this.width + this.bottomWidth) / 2; | ||
} | ||
var totalCount = 0; | ||
var count = 0; | ||
let totalCount = 0; | ||
let count = 0; | ||
// Harvest total count | ||
for (var i = 0; i < this.data.length; i++) { | ||
for (let i = 0; i < this.data.length; i++) { | ||
totalCount += isArray(this.data[i][1]) ? this.data[i][1][0] : this.data[i][1]; | ||
} | ||
// Create the path definition for each funnel section | ||
// Create the path definition for each funnel block | ||
// Remember to loop back to the beginning point for a closed path | ||
for (i = 0; i < this.data.length; i++) { | ||
for (let i = 0; i < this.data.length; i++) { | ||
count = isArray(this.data[i][1]) ? this.data[i][1][0] : this.data[i][1]; | ||
@@ -265,4 +270,4 @@ | ||
if (this.dynamicArea) { | ||
var ratio = count / totalCount; | ||
var area = ratio * totalArea; | ||
let ratio = count / totalCount; | ||
let area = ratio * totalArea; | ||
@@ -284,3 +289,3 @@ if (this.minHeight !== false) { | ||
// Stop velocity for pinched sections | ||
// Stop velocity for pinched blocks | ||
if (this.bottomPinch > 0) { | ||
@@ -293,8 +298,9 @@ // Check if we've reached the bottom of the pinch | ||
} | ||
// Pinch at the first sections relating to the bottom pinch | ||
// Revert back to normal velocity after pinch | ||
// Pinch at the first blocks relating to the bottom pinch | ||
// Revert back to normal velocity after pinch | ||
} else { | ||
// Revert velocity back to the intial if we are using | ||
// Revert velocity back to the initial if we are using | ||
// static area's (prevents zero velocity if isInverted | ||
// and bottomPinch are non trivial and dynamicArea is false) | ||
// and bottomPinch are non trivial and dynamicArea is | ||
// false) | ||
if (!this.dynamicArea) { | ||
@@ -308,3 +314,3 @@ dx = this.dx; | ||
// Calculate the position of next section | ||
// Calculate the position of next block | ||
nextLeftX = prevLeftX + dx; | ||
@@ -334,3 +340,3 @@ nextRightX = prevRightX - dx; | ||
// Left line | ||
[prevLeftX, prevHeight, 'L'] | ||
[prevLeftX, prevHeight, 'L'], | ||
]); | ||
@@ -349,7 +355,7 @@ // Plot straight lines | ||
// Wrap back to top | ||
[prevLeftX, prevHeight, 'L'] | ||
[prevLeftX, prevHeight, 'L'], | ||
]); | ||
} | ||
// Set the next section's previous position | ||
// Set the next block's previous position | ||
prevLeftX = nextLeftX; | ||
@@ -372,11 +378,11 @@ prevRightX = nextRightX; | ||
{ | ||
var defs = svg.append('defs'); | ||
let defs = svg.append('defs'); | ||
// Create a gradient for each section | ||
for (var i = 0; i < this.data.length; i++) { | ||
var color = this.data[i][2]; | ||
var shade = shadeColor(color, -0.25); | ||
// Create a gradient for each block | ||
for (let i = 0; i < this.data.length; i++) { | ||
let color = this.data[i][2]; | ||
let shade = shadeColor(color, -0.25); | ||
// Create linear gradient | ||
var gradient = defs.append('linearGradient') | ||
let gradient = defs.append('linearGradient') | ||
.attr({ | ||
@@ -387,15 +393,15 @@ id: 'gradient-' + i | ||
// Define the gradient stops | ||
var stops = [ | ||
let stops = [ | ||
[0, shade], | ||
[40, color], | ||
[60, color], | ||
[100, shade] | ||
[100, shade], | ||
]; | ||
// Add the gradient stops | ||
for (var j = 0; j < stops.length; j++) { | ||
var stop = stops[j]; | ||
for (let j = 0; j < stops.length; j++) { | ||
let stop = stops[j]; | ||
gradient.append('stop').attr({ | ||
offset: stop[0] + '%', | ||
style: 'stop-color:' + stop[1] | ||
style: 'stop-color:' + stop[1], | ||
}); | ||
@@ -410,11 +416,11 @@ } | ||
* @param {Object} svg | ||
* @param {Array} sectionPaths | ||
* @param {Array} blockPaths | ||
* | ||
* @return {void} | ||
*/ | ||
_drawTopOval(svg, sectionPaths) | ||
_drawTopOval(svg, blockPaths) | ||
{ | ||
var leftX = 0; | ||
var rightX = this.width; | ||
var centerX = this.width / 2; | ||
let leftX = 0; | ||
let rightX = this.width; | ||
let centerX = this.width / 2; | ||
@@ -426,5 +432,5 @@ if (this.isInverted) { | ||
// Create path form top-most section | ||
var paths = sectionPaths[0]; | ||
var path = 'M' + leftX + ',' + paths[0][1] + | ||
// Create path from top-most block | ||
let paths = blockPaths[0]; | ||
let path = 'M' + leftX + ',' + paths[0][1] + | ||
' Q' + centerX + ',' + (paths[1][1] + this.curveHeight - 10) + | ||
@@ -443,3 +449,3 @@ ' ' + rightX + ',' + paths[2][1] + | ||
/** | ||
* Draw the next section in the iteration. | ||
* Draw the next block in the iteration. | ||
* | ||
@@ -450,3 +456,3 @@ * @param {int} index | ||
*/ | ||
_drawSection(index) | ||
_drawBlock(index) | ||
{ | ||
@@ -458,11 +464,10 @@ if (index === this.data.length) { | ||
// Create a group just for this block | ||
var group = this.svg.append('g'); | ||
let group = this.svg.append('g'); | ||
// Fetch path element | ||
var path = this._getSectionPath(group, index); | ||
path.data(this._getSectionData(index)); | ||
let path = this._getBlockPath(group, index); | ||
path.data(this._getBlockData(index)); | ||
// Add animation components | ||
if (this.animation !== false) { | ||
var self = this; | ||
path.transition() | ||
@@ -473,4 +478,4 @@ .duration(this.animation) | ||
.attr('d', this._getPathDefinition(index)) | ||
.each('end', function () { | ||
self._drawSection(index + 1); | ||
.each('end', () => { | ||
this._drawBlock(index + 1); | ||
}); | ||
@@ -480,3 +485,3 @@ } else { | ||
.attr('d', this._getPathDefinition(index)); | ||
this._drawSection(index + 1); | ||
this._drawBlock(index + 1); | ||
} | ||
@@ -495,3 +500,3 @@ | ||
this._addSectionLabel(group, index); | ||
this._addBlockLabel(group, index); | ||
} | ||
@@ -505,5 +510,5 @@ | ||
*/ | ||
_getSectionPath(group, index) | ||
_getBlockPath(group, index) | ||
{ | ||
var path = group.append('path'); | ||
let path = group.append('path'); | ||
@@ -527,6 +532,6 @@ if (this.animation !== false) { | ||
{ | ||
var paths = this.sectionPaths[index]; | ||
let paths = this.blockPaths[index]; | ||
var beforePath = ''; | ||
var beforeFill = ''; | ||
let beforePath = ''; | ||
let beforeFill = ''; | ||
@@ -553,3 +558,3 @@ // Construct the top of the trapezoid and leave the other elements | ||
beforeFill = index > 0 ? this._getColor(index - 1) : this._getColor(index); | ||
// Use current background if gradient (gradients do not transition) | ||
// Use current background if gradient (gradients do not transition) | ||
} else { | ||
@@ -568,3 +573,3 @@ beforeFill = this._getColor(index); | ||
*/ | ||
_getSectionData(index) | ||
_getBlockData(index) | ||
{ | ||
@@ -574,5 +579,10 @@ return [{ | ||
label: this.data[index][0], | ||
value: isArray(this.data[index][1]) ? this.data[index][1][0] : this.data[index][1], formattedValue: isArray(this.data[index][1]) ? this.data[index][1][1] : this.data[index][1].toLocaleString(), | ||
value: isArray(this.data[index][1]) ? | ||
this.data[index][1][0] : | ||
this.data[index][1], | ||
formattedValue: isArray(this.data[index][1]) ? | ||
this.data[index][1][1] : | ||
this.data[index][1].toLocaleString(), | ||
baseColor: this.data[index][2], | ||
fill: this._getColor(index) | ||
fill: this._getColor(index), | ||
}]; | ||
@@ -604,7 +614,7 @@ } | ||
{ | ||
var pathStr = ''; | ||
var point = []; | ||
var paths = this.sectionPaths[index]; | ||
let pathStr = ''; | ||
let point = []; | ||
let paths = this.blockPaths[index]; | ||
for (var j = 0; j < paths.length; j++) { | ||
for (let j = 0; j < paths.length; j++) { | ||
point = paths[j]; | ||
@@ -643,14 +653,14 @@ pathStr += point[2] + point[0] + ',' + point[1] + ' '; | ||
*/ | ||
_addSectionLabel(group, index) | ||
_addBlockLabel(group, index) | ||
{ | ||
var i = index; | ||
var paths = this.sectionPaths[index]; | ||
var sectionData = this._getSectionData(index)[0]; | ||
var textStr = sectionData.label + ': ' + sectionData.formattedValue; | ||
var textFill = this.data[i][3] || this.label.fill; | ||
let i = index; | ||
let paths = this.blockPaths[index]; | ||
let blockData = this._getBlockData(index)[0]; | ||
let textStr = blockData.label + ': ' + blockData.formattedValue; | ||
let textFill = this.data[i][3] || this.label.fill; | ||
var textX = this.width / 2; // Center the text | ||
var textY = !this.isCurved ? // Average height of bases | ||
(paths[1][1] + paths[2][1]) / 2 : | ||
(paths[2][1] + paths[3][1]) / 2 + (this.curveHeight / this.data.length); | ||
let textX = this.width / 2; // Center the text | ||
let textY = !this.isCurved ? // Average height of bases | ||
(paths[1][1] + paths[2][1]) / 2 : | ||
(paths[2][1] + paths[3][1]) / 2 + (this.curveHeight / this.data.length); | ||
@@ -665,3 +675,3 @@ group.append('text') | ||
'fill': textFill, | ||
'pointer-events': 'none' | ||
'pointer-events': 'none', | ||
}) | ||
@@ -695,3 +705,3 @@ .style('font-size', this.label.fontSize); | ||
{ | ||
var prop; | ||
let prop; | ||
for (prop in b) { | ||
@@ -715,9 +725,9 @@ if (b.hasOwnProperty(prop)) { | ||
{ | ||
var f = parseInt(color.slice(1), 16); | ||
var t = shade < 0 ? 0 : 255; | ||
var p = shade < 0 ? shade * -1 : shade; | ||
var R = f >> 16, G = f >> 8 & 0x00FF; | ||
var B = f & 0x0000FF; | ||
let f = parseInt(color.slice(1), 16); | ||
let t = shade < 0 ? 0 : 255; | ||
let p = shade < 0 ? shade * -1 : shade; | ||
let R = f >> 16, G = f >> 8 & 0x00FF; | ||
let B = f & 0x0000FF; | ||
var converted = (0x1000000 + (Math.round((t - R) * p) + R) * | ||
let converted = (0x1000000 + (Math.round((t - R) * p) + R) * | ||
0x10000 + (Math.round((t - G) * p) + G) * | ||
@@ -724,0 +734,0 @@ 0x100 + (Math.round((t - B) * p) + B)); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
67618
1364
103
10
17
Updatedd3@~3.5.6