d3-flame-graphs
Version:
D3.js plugin for rendering flame graphs
1 lines • 8.97 kB
JavaScript
(function(){var t,e=[].indexOf||function(t){for(var e=0,n=this.length;e<n;e++)if(e in this&&this[e]===t)return e;return-1};if(t=this.d3?this.d3:require("d3"),!t)throw new Error("d3.js needs to be loaded");t.flameGraphUtils={augment:function(e,n){var i,r;return r=e.children,e.augmented?e:(e.originalValue=e.value,e.level=e.children?1:0,e.hidden=[],e.location=n,(null!=r?r.length:void 0)?(i=r.reduce(function(t,e){return t+e.value},0),i<e.value&&r.push({value:e.value-i,filler:!0}),r.forEach(function(e,i){return t.flameGraphUtils.augment(e,n+"."+i)}),e.level+=r.reduce(function(t,e){return Math.max(e.level,t)},0),e.augmented=!0,e):(e.augmented=!0,e))},partition:function(e){return t.layout.partition().sort(function(t,e){return t.filler?1:e.filler?-1:t.name.localeCompare(e.name)}).nodes(e)},hide:function(t,e){var n,i,r,o,s;return null==e&&(e=!1),s=function(t){return t.reduce(function(t,e){return t+e},0)},o=function(t,e){var n;if(n=t.indexOf(e),n>=0)return t.splice(n,1)},n=function(t,n){return e?o(t.hidden,n):t.hidden.push(n),t.value=Math.max(t.originalValue-s(t.hidden),0)},i=function(t,e){if(t.children)return t.children.forEach(function(t){return n(t,e),i(t,e)})},r=function(t,e){var i;for(i=[];t.parent;)n(t.parent,e),i.push(t=t.parent);return i},t.forEach(function(t){var e;return e=t.originalValue,r(t,e),n(t,e),i(t,e)})}},t.flameGraph=function(n,i,r){var o,s,h;return null==r&&(r=!1),s=function(t){var e;return t?(e=t.split("."),e.slice(e.length-2).join(".")):""},h=function(t){var e,n,i,r,o,h,l,a;for(o=[0,0,1,10],l=o[0],i=o[1],a=o[2],r=o[3],t=s(t).slice(0,6),e=n=0,h=t.length-1;0<=h?n<=h:n>=h;e=0<=h?++n:--n)l+=a*(t.charCodeAt(e)%r),i+=a*(r-1),a*=.7;return i>0?l/i:l},new(o=function(){function n(e,n){this._selector=e,this._generateAccessors(["margin","cellHeight","zoomEnabled","zoomAction","tooltip","tooltipPlugin","color"]),this._ancestors=[],r?this.console=window.console:this.console={log:function(){},time:function(){},timeEnd:function(){}},this._size=[1200,800],this._cellHeight=20,this._margin={top:0,right:0,bottom:0,left:0},this._color=function(t){var e,n,i,r;return r=h(t.name),i=200+Math.round(55*r),n=0+Math.round(230*(1-r)),e=0+Math.round(55*(1-r)),"rgb("+i+", "+n+", "+e+")"},this._tooltipEnabled=!0,this._zoomEnabled=!0,this._tooltipEnabled&&t.tip&&(this._tooltipPlugin=t.tip()),this.console.time("augment"),this.original=t.flameGraphUtils.augment(n,"0"),this.console.timeEnd("augment"),this.root(this.original)}return n.prototype.size=function(e){return e?(this._size=e,t.select(this._selector).select(".flame-graph").attr("width",this._size[0]).attr("height",this._size[1]),this):this._size},n.prototype.root=function(e){return e?(this.console.time("partition"),this._root=e,this._data=t.flameGraphUtils.partition(this._root),this.console.timeEnd("partition"),this):this._root},n.prototype.hide=function(e,n){var i;if(null==n&&(n=!1),i=this.select(e,!1),i.length)return t.flameGraphUtils.hide(i,n),this._data=t.flameGraphUtils.partition(this._root),this.render()},n.prototype.zoom=function(t,n){if(!this.zoomEnabled())throw new Error("Zoom is disabled!");return this.tip&&this.tip.hide(),e.call(this._ancestors,t)>=0?this._ancestors=this._ancestors.slice(0,this._ancestors.indexOf(t)):this._ancestors.push(this._root),this.root(t).render(),"function"==typeof this._zoomAction&&this._zoomAction(t,n),this},n.prototype.width=function(){return this.size()[0]-(this.margin().left+this.margin().right)},n.prototype.height=function(){return this.size()[1]-(this.margin().top+this.margin().bottom)},n.prototype.label=function(t){var e;return(null!=t?t.name:void 0)?(e=s(t.name),e.substr(0,Math.round(this.x(t.dx)/(this.cellHeight()/10*4)))):""},n.prototype.select=function(e,n){var i;return null==n&&(n=!0),n?this.container.selectAll(".node").filter(e):i=t.flameGraphUtils.partition(this.original).filter(e)},n.prototype.render=function(){var e,n,i,r,o,s,h;if(!this._selector)throw new Error("No DOM element provided");return this.console.time("render"),this.container||this._createContainer(),this.fontSize=this.cellHeight()/10*.4,this.x=t.scale.linear().domain([0,t.max(this._data,function(t){return t.x+t.dx})]).range([0,this.width()]),h=Math.floor(this.height()/this.cellHeight()),i=this._root.level,this.y=t.scale.quantize().domain([t.max(this._data,function(t){return t.y}),0]).range(t.range(i).map(function(t){return function(e){return(e+h-(t._ancestors.length+i))*t.cellHeight()}}(this))),e=this._data.filter(function(t){return function(e){return t.x(e.dx)>.4&&t.y(e.y)>=0&&!e.filler}}(this)),s={x:function(t){return function(e){return t.x(e.x)}}(this),y:function(t){return function(e){return t.y(e.y)}}(this),width:function(t){return function(e){return t.x(e.dx)}}(this),height:function(t){return function(e){return t.cellHeight()}}(this),text:function(t){return function(e){if(e.name&&t.x(e.dx)>40)return t.label(e)}}(this)},n=this.container.selectAll(".node").data(e,function(t){return t.location}).attr("class","node"),this._renderNodes(n,s),r=n.enter().append("g").attr("class","node"),this._renderNodes(r,s,!0),n.exit().remove(),this.zoomEnabled()&&this._renderAncestors()._enableNavigation(),this.tooltip()&&this._renderTooltip(),this.console.timeEnd("render"),this.console.log("Processed "+this._data.length+" items"),this.console.log("Rendered "+(null!=(o=this.container.selectAll(".node")[0])?o.length:void 0)+" elements"),this},n.prototype._createContainer=function(){var e,n;return t.select(this._selector).select("svg").remove(),n=t.select(this._selector).append("svg").attr("class","flame-graph").attr("width",this._size[0]).attr("height",this._size[1]),e="translate("+this.margin().left+", "+this.margin().top+")",this.container=n.append("g").attr("transform",e),n.append("rect").attr("width",this._size[0]-(this._margin.left+this._margin.right)).attr("height",this._size[1]-(this._margin.top+this._margin.bottom)).attr("transform",e).attr("class","border-rect")},n.prototype._renderNodes=function(t,e,n){var i,r;return null==n&&(n=!1),n||(r=t.selectAll("rect")),n&&(r=t.append("rect")),r.attr("fill",function(t){return function(e){return t._color(e)}}(this)).transition().attr("width",e.width).attr("height",this.cellHeight()).attr("x",e.x).attr("y",e.y),n||(i=t.selectAll("text")),n&&(i=t.append("text")),t.selectAll("text").attr("class","label").style("font-size",this.fontSize+"em").transition().attr("dy",this.fontSize/2+"em").attr("x",function(t){return function(t){return e.x(t)+2}}(this)).attr("y",function(t){return function(n,i){return e.y(n,i)+t.cellHeight()/2}}(this)).text(e.text),this},n.prototype._renderTooltip=function(){return this._tooltipPlugin&&this._tooltipEnabled?(this.tip=this._tooltipPlugin.attr("class","d3-tip").html(this.tooltip()).direction(function(t){return function(e){return t.x(e.x)+t.x(e.dx)/2>t.width()-100?"w":t.x(e.x)+t.x(e.dx)/2<100?"e":"s"}}(this)).offset(function(t){return function(e){var n,i,r;return n=t.x(e.x)+t.x(e.dx)/2,i=Math.max(Math.ceil(t.x(e.dx)/2),5),r=Math.ceil(t.cellHeight()/2),t.width()-100<n?[0,-i]:n<100?[0,i]:[r,0]}}(this)),this.container.call(this.tip),this.container.selectAll(".node").on("mouseover",function(e){return function(n){return e.tip.show(n,t.event.currentTarget)}}(this)).on("mouseout",this.tip.hide).selectAll(".label").on("mouseover",function(e){return function(n){return e.tip.show(n,t.event.currentTarget.parentNode)}}(this)).on("mouseout",this.tip.hide),this):this},n.prototype._renderAncestors=function(){var e,n,i,r,o,h,l,a,u;if(!this._ancestors.length)return i=this.container.selectAll(".ancestor").remove(),this;for(n=this._ancestors.map(function(t,e){return{name:t.name,value:e+1,location:t.location}}),r=o=0,h=n.length;o<h;r=++o)e=n[r],a=n[r-1],a&&(a.children=[e]);return u={x:function(t){return function(t){return 0}}(this),y:function(t){return function(e){return t.height()-e.value*t.cellHeight()}}(this),width:this.width(),height:this.cellHeight(),text:function(t){return function(t){return"↩ "+s(t.name)}}(this)},i=this.container.selectAll(".ancestor").data(t.layout.partition().nodes(n[0]),function(t){return t.location}),this._renderNodes(i,u),l=i.enter().append("g").attr("class","ancestor"),this._renderNodes(l,u,!0),i.exit().remove(),this},n.prototype._enableNavigation=function(){var e;return e=function(t){return function(e){var n;return Math.round(t.width()-t.x(e.dx))>0&&(null!=(n=e.children)?n.length:void 0)}}(this),this.container.selectAll(".node").classed("clickable",function(t){return function(t){return e(t)}}(this)).on("click",function(n){return function(i){if(n.tip&&n.tip.hide(),e(i))return n.zoom(i,t.event)}}(this)),this.container.selectAll(".ancestor").on("click",function(e){return function(n,i){return e.tip&&e.tip.hide(),e.zoom(e._ancestors[i],t.event)}}(this)),this},n.prototype._generateAccessors=function(t){var e,n,i,r;for(r=[],n=0,i=t.length;n<i;n++)e=t[n],r.push(this[e]=function(t){return function(e){return arguments.length?(this["_"+t]=e,this):this["_"+t]}}(e));return r},n}())(n,i)}}).call(this);