hi I am using the following code to basically create a bar graph by consuming data from a service call. The problem with this is as the data from the service call changes, it is not reflected in the bar graph, it remains in its original state. The Appname and Appcount are two things which i am getting from the service call
jQuery(function($)
{
Appnames = []//array will be populated from service call,
Appcount = []//array will be populated from serv`enter code here`ice call,
chart,
width = 700,
bar_height = 40,
gap = 2,
height = bar_height * Appnames.length;
var margin = {top: 20, right: 120, bottom: 20, left: 120};
/* step 1 - create the background*/
chart = d3.select($("#step-1")[0])
.append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height);
/* step 2 - create the bars*/
var x, y;
chart = d3.select($("#step-2")[0])
.append('svg')
.attr('class', 'chart')
.attr('width', width + margin.right + margin.left)
.attr('height', height);
x = d3.scale.linear()
.domain([0, d3.max(Appcount)])
.range([0, width]);
y = function(i) { return bar_height * i; }
chart.selectAll("rect")
.data(Appcount)
.enter().append("rect")
.attr("x", 0)
.attr("y", function(d, i) { return y(i);})
.attr("width", x)
.attr("height", bar_height);
/* step 3 - add counts to the bars*/
chart = d3.select($("#step-3")[0])
.append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height);
chart.selectAll("rect")
.data(Appcount)
.enter().append("rect")
.attr("x", 0)
.attr("y", function(d, i) { return y(i);})
.attr("width", x)
.attr("height", bar_height);
chart.selectAll("text")
.data(Appcount)
.enter().append("text")
.attr("x", x)
.attr("y", function(d, i){ return y(i) + bar_height/2; } )
.attr("dx", -5)
.attr("dy", ".36em")
.attr("text-anchor", "end")
.text(String);
/* step 4 - add Appnames to bars*/
var left_width = 100;
chart = d3.select($("#step-4")[0])
.append('svg')
.attr('class', 'chart')
.attr('width', left_width + width)
.attr('height', height);
chart.selectAll("rect")
.data(Appcount)
.enter().append("rect")
.attr("x", left_width)
.attr("y", function(d, i) { return y(i);})
.attr("width", x)
.attr("height", bar_height);
chart.selectAll("text.score")
.data(Appcount)
.enter().append("text")
.attr("x", function(d) { return x(d) + left_width; })
.attr("y", function(d, i) { return y(i) + bar_height / 2;})
.attr("dx", -5)
.attr("dy", ".36em")
.attr("text-anchor", "end")
.attr('class', 'score')
.text(String);
chart.selectAll("text.name")
.data(Appnames)
.enter().append("text")
.attr("x", left_width / 2)
.attr("y", function(d, i){ return y(i) +bar_height/2; } )
.attr("dy", ".36em")
.attr("text-anchor", "middle")
.attr('class', 'name')
.text(String);
/* step 5 - add a ruler line to the bars*/
var gap = 2, yRangeBand;
// redefine y for adjusting the gap
yRangeBand = bar_height + 2 * gap;
y = function(i) { return yRangeBand * i; };
chart = d3.select($("#step-5")[0])
.append('svg')
.attr('class', 'chart')
.attr('width', left_width + width + 40)
.attr('height', (bar_height + gap * 2) * Appnames.length + 30)
.append("g")
.attr("transform", "translate(10, 20)");
chart.selectAll("line")
.data(x.ticks(d3.max(Appcount)))
.enter().append("line")
.attr("x1", function(d) { return x(d) + left_width; })
.attr("x2", function(d) { return x(d) + left_width; })
.attr("y1", 0)
.attr("y2", (bar_height + gap * 2) * Appnames.length);
chart.selectAll(".rule")
.data(x.ticks(d3.max(Appcount)))
.enter().append("text")
.attr("class", "rule")
.attr("x", function(d) { return x(d) + left_width; })
.attr("y", 0)
.attr("dy", -6)
.attr("text-anchor", "middle")
.attr("font-size", 10)
.text(String);
chart.selectAll("rect")
.data(Appcount)
.enter().append("rect")
.attr("x", left_width)
.attr("y", function(d, i) { return y(i) + gap; })
.attr("width", x)
.attr("height", bar_height);
chart.selectAll("text.score")
.data(Appcount)
.enter().append("text")
.attr("x", function(d) { return x(d) + left_width; })
.attr("y", function(d, i) { return y(i) + yRangeBand/2;})
.attr("dx", -5)
.attr("dy", ".36em")
.attr("text-anchor", "end")
.attr('class', 'score')
.text(String);
chart.selectAll("text.name")
.data(Appnames)
.enter().append("text")
.attr("x", left_width / 2)
.attr("y", function(d, i){ return y(i) + yRangeBand/2; } )
.attr("dy", ".36em")
.attr("text-anchor", "middle")
.attr('class', 'name')
.text(String); }(jQuery));
d3 uses an enter, update and exit pattern. Your code is only handling the enter state. Split it up to handle all 3 states:
var rects = chart.selectAll("rect")
.data(Appcount); //<-- create your data join
rects.enter().append("rect"); //<-- ENTER - when data enters the join append a rect element to dom
rects.exit().remove(); //<-- EXIT - when data leaves the join, remove the rect
rects.attr("x", 0) //<-- UPDATE - update the rects based on data
.attr("y", function(d, i) { return y(i);})
.attr("width", x)
.attr("height", bar_height);
Related
I want to make the axis lines either less opaque, or make them light grey. I tried to just do .style(opacity, 0.5), but it only makes the TICKS opaque, not the actual line itself. I want to make the ACTUAL LINE less opaque/light grey. I also tried adding the call(d3.axisLeft...).style(less opaque) approach but I still get nothing. How do I go about doing that?
import React, {Component, useRef, useEffect} from 'react';
import ExperienceScoresData from './experience_scores';
import * as d3 from "d3";
import { select, csv} from 'd3';
import { extent, max, min } from "d3-array";
ExperienceScoresData.map(function(val){
val.customerExperienceScore *= 100;
return 0;
})
class Linechart extends Component {
constructor(props){
super(props)
this.createBarChart = this.createBarChart.bind(this)
}
componentDidMount() {
this.createBarChart()
}
componentDidUpdate() {
this.createBarChart()
}
createBarChart() {
var margin = {top: 85, right: 60, bottom: 60, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = select(node)
var svgObj = divObj
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/5_OneCatSevNumOrdered.csv", function(data) {
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.name;})
.entries(data);
//console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class","tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px")
.text("I AM A TOOLTIP pakistan zindabad");
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Online Ratings");
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.year; }))
.range([ 0, width ]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.n; })])
.range([ height, 0 ]);
svgObj.append("g")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width/2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Year Of Birth");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height/2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("N-Value")
// color palette
var key = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c','#377eb8','#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d,i){ return 250 + i*120})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d){ return color(d)})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d,i){ return 270 + i*120})
.attr("y", -28)
.text(function(d){ return d})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 4.5)
.attr("d", function(d){
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
var dataUnpacked = sumstat.map( function(d){return d.values})
console.log(data)
// Draw dots on points
svgObj.selectAll(".lineChartDots")
.data(data)
.enter()
.append("circle")
.attr("class","lineChartDots")
.style("fill","white")
.style("stroke-width", "3px")
.style("stroke", function (d) { return color(d.name) })
.attr("cx", function(d) {return x(d.year); })
.attr("cy", function(d) {return y(d.n); })
.attr("r", 5.5)
})
}
render() {
return <div ref={node => this.node = node} className="example_div"> </div>
}
}
export default Linechart;
The following could change the axis line's opacity.
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => { // manipulate the elements' attrs here
g.select("path")
.attr("opacity", 0.5)
});
I run your code and found that the above code actually worked but since there are two svg lines in the axis, both the axis path and the first background grid line, so you might feel the opacity wasn't changed. See jsfiddle here.
a simple demo:
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",
// When reading the csv, I must format variables:
function(d){
return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
},
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => {
g.select("path")
.attr("opacity", 0.5)
});
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>
SO community,
I'm making a D3 histogram as an Angular directive and I want it to be able to change/update accordingly as the data it reads in changes. In other words, I am using Angular to watch the changes in data and (hope to) redraw the histogram every time the data is changed.
This might mostly be a question about D3's updating and binding of data because the $watchCollection seems to work fine. Even though I have went through this tutorial on adding elements to a d3 chart, I still cannot apply it on my histogram. I think the way the elements in my histogram are nested is really confusing me...
Context: Ideally this histogram will read from an array to which data returned from several Ajax calls will get stored in. So every time a new set of data arrive, the histogram will grow itself another bar. That's why I would love to know how to update the chart as well as the x-axis properly.
Thank you! :)
The JS fiddle is here: http://jsfiddle.net/santina/wrtenjny/1/
Code for just the d3 part is here, largely taken from mbostock's sortable bar chart.
// Aesthetic settings
var margin = {top: 20, right: 50, bottom: 20, left: 50},
width = document.getElementById('performance').clientWidth - margin.left - margin.right ||
940 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
barColor = "steelblue",
axisColor = "whitesmoke",
axisLabelColor = "grey",
yText = "# QUERIES",
xText = "BEACON IDs";
// Inputs to the d3 graph
var data = scope[attrs.data];
// A formatter for counts.
var formatCount = d3.format(",.0f");
// Set the scale, separate the first bar by a bar width from y-axis
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatCount);
// Initialize histogram
var svg = d3.select(".histogram-chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function drawAxis(){
data.forEach(function(d) {
d.nqueries = +d.nqueries;
});
x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(data, function(d) { return d.nqueries; })]);
// Draw x-axis
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("y", 6)
.attr("dy", "-0.71em")
.attr("x", width )
.style("text-anchor", "end")
.style("fill", axisLabelColor)
.text(xText);
// Draw y-axis
svg.append("g")
.attr("class", "y-axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style("fill", axisLabelColor)
.text(yText);
// Change axis color
d3.selectAll("path").attr("fill", axisColor);
}
function updateAxis(){
console.log(data);
data.forEach(function(d) {
d.nqueries = +d.nqueries;
});
x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(data, function(d) { return d.nqueries; })]);
svg.selectAll("g.y_axis").call(yAxis);
svg.selectAll("g.x_axis").call(xAxis);
}
function drawHistogram(){
drawAxis();
var bar = svg.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "barInfo");
bar.append("rect")
.attr("class", "bar")
.attr("x", function(d){ return x(d.name) })
.attr("width", x.rangeBand())
.attr("y", function(d){ return y(d.nqueries) })
.attr("height", function(d) { return height - y(d.nqueries); })
.attr("fill", barColor);
bar.append("text")
.attr("y", function(d){ return y(d.nqueries) })
.attr("x", function(d){ return x(d.name) })
.attr("dy", "-1px")
.attr("dx", x.rangeBand()/2 )
.attr("text-anchor", "middle")
.attr("class", "numberLabel")
.text(function(d) { return formatCount(d.nqueries); });
}
// Doesn't work :(
function updateHistogram(){
console.log("updating");
// Redefine scale and update axis
updateAxis();
// Select
var bar = svg.selectAll(".barInfo").data(data);
// Update - rect
var rects = bar.selectAll("rect")
.attr("class", "bar")
.attr("x", function(d){ return x(d.name) })
.attr("width", x.rangeBand());
// Update
var texts = bar.selectAll("text")
.attr("x", function(d){ return x(d.name) })
.attr("dx", x.rangeBand()/2 );
// Enter
bar.enter().append("g")
.attr("class", "bar").selectAll("rect").append("rect")
.attr("class", "bar")
.attr("x", function(d){ return x(d.name) })
.attr("width", x.rangeBand())
.attr("y", function(d){ return y(d.nqueries) })
.attr("height", function(d) { return height - y(d.nqueries); })
.attr("fill", barColor);
bar.enter().append("g")
.attr("class", "bar").selectAll("text").append("text")
.attr("y", function(d){ return y(d.nqueries) })
.attr("x", function(d){ return x(d.name) })
.attr("dy", "-1px")
.attr("dx", x.rangeBand()/2 )
.attr("text-anchor", "middle")
.attr("class", "numberLabel")
.text(function(d) { return formatCount(d.nqueries); });
}
drawHistogram();
First, you got the wrong class selector when you update your axis:
svg.selectAll("g.y-axis").call(yAxis); //<-- dash not underscore
svg.selectAll("g.x-axis").call(xAxis);
Second, you were close on your update, but we can clean it up a bit:
// select on what you originally binded data to
var bar = svg.selectAll(".barInfo").data(data);
// for data entering
var bEnter = bar.enter().append("g")
.attr("class", "barInfo");
// append a rect
bEnter.append("rect")
.attr("class", "bar");
// and the text elements
bEnter.append("text")
.attr("class","numberLabel");
// now we can update everybody together
bar.select("rect")
.attr("x", function(d){ return x(d.name) })
.attr("width", x.rangeBand())
.attr("y", function(d){ return y(d.nqueries) })
.attr("height", function(d) { return height - y(d.nqueries); })
.attr("fill", barColor);
bar.select("text")
.attr("y", function(d){ return y(d.nqueries) })
.attr("x", function(d){ return x(d.name) })
.attr("dy", "-1px")
.attr("dx", x.rangeBand()/2 )
.attr("text-anchor", "middle")
.attr("class", "numberLabel")
.text(function(d) { return formatCount(d.nqueries); });
Udpated example here.
EDITS
Opps, I'm not selecting correctly on my updates.
bar.selectAll("rect")
Should be:
bar.select("rect")
This fixes both the updates and the sorting...
Updated fiddle.
Also notice that I collapsed your code further. With your angular watch you really don't need a seperate draw and update function, one can do both.
I am developing bar graph using d3.js integrating with Angularjs. The angular directive code I am using is given below . My problem is ,in my real application , the bar graph is not redrawing but its axis changes when data associated with the bar graph changes
mainApp.directive('ngDatenobargraph', function() {
return {
restrict: 'AE',
scope: {
data: '='
},
link: function (scope, element) {
var margin = {top: 10, right: 10, bottom: 40, left: 60},
width = 410 - margin.left - margin.right,
height = 230 - margin.top - margin.bottom;
var chart = d3.select(element[0])
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<span style='font-size: 13px'>Date: </span><span style='color:red;font-size: 13px'>" + d.xValue+ "</span><br>"+
"<span style='font-size: 13px'>Net Value: </span><span style='color:red;font-size: 13px'>" + d.yValue+ "</span><br>"+
"<span style='font-size: 13px'>Buy Value: </span><span style='color:red;font-size: 13px'>" + d.buyValue+ "</span><br>"+
"<span style='font-size: 13px'>Sell Value: </span><span style='color:red;font-size: 13px'>" + d.sellValue+ "</span>";
});
chart.call(tip);
//Render graph based on 'data'
scope.render = function(data) {
if(data) {
var y = d3.scale.linear()
.range([height, 0])
.domain(d3.extent(data, function(d) { return d.yValue; }))
.nice();
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(7);
x.domain(data.map(function(d) { return d.xValue; }));
//Redraw the axes
chart.selectAll('g.axis').remove();
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-20)";
});
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0-margin.left)
.attr("x",0-(height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Net Value");
chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) { return d.yValue < 0 ? "bar negative" : "bar positive"; })
.attr("x", function(d) { return x(d.xValue); })
.attr("y", height)
.attr("height", 0)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.transition().duration(2000)
.attr("y", function(d) {return y(Math.max(0, d.yValue)); })
.attr("height", function(d) {return Math.abs(y(d.yValue) - y(0)); })
// .attr("width", x.rangeBand());
.attr("width", Math.min.apply(null, [x.rangeBand()-2, 100]));
}
};
scope.$watch('data', function() {
scope.render(scope.data);
}, true);
}
};
});
I am new to d3.js . If any have solution please help me .The code in application is given http://jsfiddle.net/HB7LU/9000/
I am using d3.js integrating with angularJs. But it is not working and got an error when calling tip.show and tip.hide.
var chart = d3.select(element[0])
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
chart.call(tip);
chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) { return d.value < 0 ? "bar negative" : "bar positive"; })
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("height", 0)
.transition().duration(2000)
.attr("y", function(d) {return y(Math.max(0, d.value)); })
.attr("height", function(d) {return Math.abs(y(d.value) - y(0)); })
.attr("width", x.rangeBand())
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
The complete working example is given in fiddle
http://jsfiddle.net/HB7LU/8984/
You are binding the mouse listeners on each transition. Bind the listeners to the selection
chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) { return d.value < 0 ? "bar negative" : "bar positive"; })
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("height", 0)
.on('mouseover', tipX.show) //Moved up
.on('mouseout', tipX.hide) //Moved up
.transition().duration(2000)
.attr("y", function(d) {return y(Math.max(0, d.value)); })
.attr("height", function(d) {return Math.abs(y(d.value) - y(0)); })
.attr("width", x.rangeBand());
Also update this code, since d is an object here.
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
//Changed d to d.value
return "<strong>Frequency:</strong> <span style='color:red'>" + d.value + "</span>";
});
Here is the updated fiddle
I think you can draw a div to do the trick.
I'm not sure if it is a good way.
var div = d3.select('body').append('div')
.attr('class', 'tooltip')
.style('opacity', 0);
fiddle
I'm using mbostock’s Bilevel Partition and I need to include each node's text on each path. I'm trying to use this Coffee Wheel example but I'm having no luck.
This is all being written with Backbone.js which is giving me some trouble with nesting "this", so that may cause a problem.
Here is my render function. I try adding in text at the bottom.
render: function(root, svgVar) {
var that = this;
$('.breadcrumb').append('<li>'+root.name+'</li>');
var svg = d3.select(".associations-container").append("svg")
.attr("width", svgVar.width)
.attr("height", svgVar.height)
.append("g")
.attr("transform", "translate(" + (svgVar.width/2) + "," + ((svgVar.height/2)-svgVar.padding) + ")");
this.partition = d3.layout.partition()
.sort(function(a, b) { return d3.ascending(a.name, b.name); })
.size([2 * Math.PI, svgVar.radius]);
this.arc = d3.svg.arc()
.startAngle(function(d) { return d.x; })
.endAngle(function(d) { return d.x + d.dx - .01 / (d.depth + .5); })
.innerRadius(function(d) { return svgVar.radius / 3 * d.depth; })
.outerRadius(function(d) { return svgVar.radius / 3 * (d.depth + 1) - 1; });
// Compute the initial layout on the entire tree to sum sizes.
// Also compute the full name and fill color for each node,
// and stash the children so they can be restored as we descend.
this.partition
.value(function(d) { return 1; })
.nodes(root)
.forEach(function(d) {
d._children = d.children;
d.sum = d.value;
d.key = that.key(d);
d.fill = that.fill(d);
});
// Now redefine the value function to use the previously-computed sum.
this.partition
.children(function(d, depth) { return depth < 2 ? d._children : null; })
.value(function(d) { return d.sum; });
this.centerCircle = svg.append("circle")
.attr("r", svgVar.radius / 3)
.attr("fill", "grey")
.on("click", this.zoomOut);
var centerControls = svg.append("g");
centerControls.append("svg:foreignObject")
.attr("width", 40)
.attr("height", 40)
.attr("y", "-20px")
.attr("x", "-48px")
.append("xhtml:span")
.attr("class", "control glyphicon glyphicon-filter");
centerControls.append("svg:foreignObject")
.attr("width", 40)
.attr("height", 50)
.attr("y", "-20px")
.attr("x", "8px")
.append("xhtml:span")
.attr("class", "control glyphicon glyphicon-th-list toggle-list");
this.path = svg.selectAll("path")
.data(this.partition.nodes(root).slice(1))
.enter().append("path")
.attr("d", this.arc)
.style("fill", function(d) { return d.fill; })
.each(function(d) { this._current = that.updateArc(d); })
.on("click", this.zoomIn);
this.text = svg.selectAll("text").data(root);
this.textEnter = this.text.enter().append("text")
.style("fill-opacity", 1)
.style("fill", "white")
.attr("text-anchor", function(d) {
return x(d.x + d.dx / 2) >Math.PI ? "end" : "start";
})
.attr("dy", ".2em")
.attr("transform", function(d) {
var multiline = (d.name || "").split(" ").length > 1,
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle + (multiline ? -.5 : 0);
return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
});
this.textEnter.append("tspan")
.attr("x", 0)
.text(function(d) { return d.name; });