I have a scatter plot that don't zoom and don't move the line of mean when drag and zoom.
The mean line stay fixed.
var margin = {top: 50, right: 20, bottom: 100, left: 80};
var width = 1024 - margin.left - margin.right;
var height = 390;
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
d3.json("data.json", function(error, data) {
data.forEach(function(d)
d.date = parseDate(d.date);
d.tiempo = +d.tiempo;
});
var x = d3.time.scale().range([0, width])
.domain(d3.extent(data, function(d) { return d.date; }))
.nice();
var y = d3.scale.linear().range([height, 0])
.domain([0, d3.max(data, function(d) { return d.tiempo; })])
.nice();
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 100])
.on("zoom", zoomed);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(15)
.tickSize(-height);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(15)
.tickSize(-width);
var svg = d3.select("body")
.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 + ")")
.call(zoom);
var Rect = svg.append("rect")
.attr("width", width)
.attr("height", height);
// Eje X
svg.append("g")
.classed("x axis", true)
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.classed("label", true)
.attr("x", width)
.attr("y", margin.bottom - 10)
.style("text-anchor", "end")
.text("Tiempo de llegada");
// Eje Y
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.classed("label", true)
.attr("transform", "rotate(-90)")
.attr("y", -margin.left)
.attr("dy", "1.91em")
.style("text-anchor", "end")
.text("Tiempos de espera")
// Objetos, puntos.
var objects = svg.append("svg")
.classed("objects", true)
.attr("width", width)
.attr("height", height);
objects.append("svg:line")
.classed("axisLine hAxisLine", true)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", width)
.attr("y2", 0)
.attr("transform", "translate(0," + height + ")");
objects.append("svg:line")
.classed("axisLine vAxisLine", true)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", height);
var puntos = objects.selectAll(".dot")
.data(data)
.enter().append("circle")
.classed("dot", true)
.attr("r", 3.5)
.attr("class", function(d) {
if(d.d7up==1) {
return "dot s7";
}else if(d.d7do==1) {
return "dot b7";
};
return "dot pu";
});
puntos.attr("transform", transform);
var meanData = [
{date: data[0].date, tiempo: 6.22},
{date: data[data.length - 1].date, tiempo: 6.22}
];
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.tiempo); });
var l = objects.selectAll(".lineamedia")
.data(meanData)
.enter().append("circle")
.classed("lineamedia", true)
.attr("r", 5)
.attr("stroke", "red")
.attr("fill", "red")
.attr("transform", transform);
var ll = objects.append("g")
.classed("grupolinea", true);
ll.append("line")
.attr("x1", x(meanData[0].date))
.attr("y1", y(meanData[0].tiempo))
.attr("x2", x(meanData[meanData.length - 1].date))
.attr("y2", y(meanData[meanData.length - 1].tiempo))
.attr("stroke", "red")
.attr("fill", "red")
.attr("stroke-width", 4)
.classed("medias", true);
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
//svg.selectAll(".dot").attr("transform", transform);
puntos.attr("transform", transform);
l.attr("transform", transform);
//svg.select(".grupolinea").attr("transform", transform);
}
function transform(d) {
return "translate(" + x(d.date) + "," + y(d.tiempo) + ")";
}
})
My data array is:
var = data[{"date":"2016-04-25 07:37:24","tiempo":29.366666666667}, {"date":"2016-04-25 08:18:36","tiempo":8.4833333333333},{"date":"2016-04-25 08:32:15","tiempo":5.25},{"date":"2016-04-25 08:40:57","tiempo":2.4166666666667},{"date":"2016-04-25 08:41:09","tiempo":5.3166666666667},{"date":"2016-04-25 08:58:10","tiempo":5.5833333333333},{"date":"2016-04-25 09:00:20","tiempo":4.2166666666667},{"date":"2016-04-25 09:00:42","tiempo":5.2666666666667}]
Is a graph de times wait where
date: of comming patient;
time: time of wait;
Related
I have the following segment in one of my d3 graph.
What I want is to display some text in a rectangle.
var values = $('#<%=hdnDtArray.ClientID%>').val();
var data = JSON.parse(values);
margin = {
top: 20,
right: 60,
bottom: 20,
left: 100
};
var width = 900,
height = 350;
var vis = d3.select("#line_chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var parseTime = d3.time.format("%Y.%m.%d").parse;
max_y = 0;
min_y = data[0].close;
var extent = d3.extent(data.map(function(d) {
return d.date
}));
max_x = extent[1];
min = extent[0];
for (i = 0; i < data.length; i++) {
max_y = Math.max(max_y, data[i].close);
min_y = Math.min(min_y, data[i].close);
}
var x = d3.time.scale()
.rangeRound([margin.left, width]);
xScale = x.domain(d3.extent(data, function(d) {
return parseTime(d.date);
}));
yScale = d3.scale.linear().range([height - margin.top, margin.bottom]).domain([0, max_y]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.innerTickSize(-width + margin.left)
.outerTickSize(0)
.tickPadding(10);
vis.append("svg:g")
.attr("class", "x axis")
.style({
'stroke': 'Black',
'fill': 'none',
"stroke-width": 1,
"font-size": "13px"
})
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(xAxis)
.selectAll("text")
.attr("transform", "translate(-10,0) rotate(-40)")
.style("text-anchor", "end");
vis.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.attr("x", width + 120)
.attr("y", height - 10)
.attr("font-weight", "bold");
vis.append("svg:g")
.attr("class", "y axis")
.style({
'stroke': 'Black',
'fill': 'none',
'stroke-width': 1,
"font-size": "13px"
})
.attr("transform", "translate(" + (margin.left) + ",0)")
.call(yAxis);
vis.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("x", margin.left + 5)
.attr("y", margin.top - 2)
.attr("font-weight", "bold");
var line = d3.svg.line()
.x(function(d) {
return xScale(parseTime(d.date));
})
.y(function(d) {
return yScale(d.close);
})
.interpolate("basis");
vis.append('svg:path')
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
var hoverLineGroup = vis.append("g")
.attr("class", "hover-line");
var hoverLine = hoverLineGroup.append("line")
.attr("stroke", "#000000")
.attr("stroke-width", "1px")
.attr("x1", 10).attr("x2", 10)
.attr("y1", 20).attr("y2", height - 20);
var hoverTT = hoverLineGroup.append('text')
.attr("class", "hover-tex capo")
.attr('dy', "0.35em");
var cle = hoverLineGroup.append("circle")
.attr("r", 4.5);
var hoverTT2 = hoverLineGroup.append('text')
.attr("class", "hover-text capo")
.attr('dy', "0.55em");
hoverLineGroup.style("opacity", 1e-6);
var rectHover = vis.append("rect")
.data(data)
.attr("fill", "none")
.attr("width", width)
.attr("height", height);
var hoverCircle = hoverLineGroup.append("circle");
var hoverRect = hoverLineGroup
.append("rect");
vis.on("mouseout", hoverMouseOff)
.on("mousemove", hoverMouseOn);
var bisectDate = d3.bisector(function(d) {
return parseTime(d.date);
}).left;
function hoverMouseOn() {
var mouse_x = d3.mouse(this)[0];
var mouse_y = d3.mouse(this)[1];
var graph_y = yScale.invert(mouse_y);
var graph_x = xScale.invert(mouse_x);
var mouseDate = xScale.invert(mouse_x);
var i = bisectDate(data, mouseDate);
var d0 = data[i - 1]
var d1 = data[i];
var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;
hoverRect.attr("class", "y")
.style("fill", "none")
.style("stroke", "black")
.attr('x', mouse_x + 8)
.attr('y', yScale(d.close) - 20)
.attr("width", 200)
.attr("height", 50);
hoverTT.text("Test Text")
.attr("opacity", "1");
hoverTT.attr('x', mouse_x + 23);
hoverTT.attr('y', yScale(d.close));
/*
hoverTT.text("Date: " + d.date);
hoverTT.attr('x', mouse_x + 23);
hoverTT.attr('y', yScale(d.close));
hoverTT2.text("Portfolio Value: " + Math.round(d.close * 100) / 100)
.attr('x', mouse_x + 23)
.attr('y', yScale(d.close) + 10);
*/
hoverLine.attr("x1", mouse_x).attr("x2", mouse_x)
hoverLineGroup.style({
'font-weight': 'bold',
'opacity': 1
});
hoverCircle.attr("class", "y")
.style("fill", "blue")
.style("stroke", "blue")
.attr("r", 4)
.attr('cx', mouse_x)
.attr('cy', yScale(d.close));
}
function hoverMouseOff() {
hoverLineGroup.style("opacity", 1e-6);
}
The text is not visible now. But if I set the "fill" property to "none", then the text becomes visible.
What I want is the background to be non transparent, that's why I made it white.
Still I want the text to be visible.
The problem with your code is the order of the selections.
In an SVG, just like a real painter using ink in a real canvas, what is painted later remains on top. So, if you want the text to be on top of the rectangle (with any fill you want), set the text's selection after the rectangle's selection.
Therefore, in your case, this...
var hoverTT = hoverLineGroup.append('text')
.attr("class", "hover-tex capo")
.attr('dy', "0.35em");
... has to be after this:
var hoverRect = hoverLineGroup
.append("rect");
Here is a demo, the rectangle has a solid white fill. Have a look at the order of the selections:
var svg = d3.select("svg");
var hoverRect = svg.append("rect")
.attr("fill", "white")
.attr("stroke", "firebrick")
.attr("width", 40)
.attr("height", 30)
.attr("opacity", 0);
var hoverText = svg.append("text")
.text("foo")
svg.on("mousemove", function() {
var coords = d3.mouse(this);
hoverRect.attr("x", coords[0] + 15)
.attr("y", coords[1])
.attr("opacity", 1)
hoverText.attr("x", coords[0] + 25)
.attr("y", coords[1] + 20)
})
svg {
border: 1px solid gray;
background-color: gainsboro;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
I have a bar chart/histogram, all working fine.
I need to change the text and lines on the chart is on a black background.I
Also, the bar colors need to be orange.
I have had a look around the web, and seen some references to .attr("style":...); and have tried this without success.
Any pointers gratefully received.
<script>
// set the dimensions of the canvas
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 1890 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// set the ranges
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
// define the axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
// add the SVG element
var svg = d3.select("body").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 + ")");
// load the data
d3.json("/assets/js/risk_hist_values.json", function(error, data) {
// the number of columns in this chart
var numCols = data.length;
data.forEach(function(d) {
d.Letter = d.bin_no;
d.Freq = +d.count;
});
// scale the range of the data
x.domain(data.map(function(d) { return d.Letter; }));
y.domain([0, d3.max(data, function(d) { return d.Freq; })]);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Count:</strong> <span style='color:red'>" + d.count + "</span>";
})
// call the tips
svg.call(tip);
// add axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Count");
// Add bar chart
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.Letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.Freq); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on('click', drill)
.attr("id", function(d, i){ return 'b_'+i+''; })
.attr("height", function(d) { return height - y(d.Freq); });
});
function drill(){
alert( 'drilling' );
}
</script>
I am developing bar graph using d3.js integrating with angular js.I am new to d3.js. I dont know how we can limt the the no.of x and y axis ticks.
The working is given below
mainApp.directive('ngTest', function() {
return {
restrict: 'AE',
scope: {
data: '='
},
link: function (scope, element) {
var margin = {top: 20, right: 30, bottom: 30, 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 "<strong>Frequency:</strong> <span style='color:red'>" + d.value + "</span>";
});
chart.call(tip);
//Render graph based on 'data'
scope.render = function(data) {
var y = d3.scale.linear()
.range([height, 0])
.domain(d3.extent(data, function(d) { return d.value; }))
.nice();
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
x.domain(data.map(function(d) { return d.name; }));
//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("Value");
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', tip.show)
.on('mouseout', tip.hide)
.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());
.attr("width", Math.min.apply(null, [x.rangeBand()-2, 100]));
};
scope.$watch('data', function() {
scope.render(scope.data);
}, true);
}
};
});
The working example is given in following fiddle adderss
http://jsfiddle.net/HB7LU/9000/
Use ticks method of d3 axis. Since tick format of x axis is time, you might specify both a count and a tick format.
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(d3.time.day, 2);
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
You can refer more about d3 svg axis from here and about time formats from here
I want to display negative and positive values with d3js... with dis code, it made only the positive values.
i've worked with this : http://jsfiddle.net/chrisJamesC/tNdJj/4/
can anyone help me?
her it is the code:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 390 - margin.top - margin.bottom;
var y0 = Math.max(Math.abs(d3.min(d3.csv)), Math.abs(d3.max(d3.csv)));
var y = d3.scale.linear()
.domain([-y0, y0])
.range([height,0])
.nice();
var x = d3.scale.ordinal()
.domain(d3.range(d3.csv.length))
.rangeRoundBands([0, width], .1);
var color = d3.scale.ordinal()
.range(["#FFFFFF", "#FF0000", "#FE642E", "#00FF00", "#04B404", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var chart2 = d3.select("#graph2")
.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 div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
d3.csv("dataanzeigeauto3.asp", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
chart2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart2.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("dy", ".71em")
.attr("y", 6)
.style("text-anchor", "end")
.text("Anzahl");
var state2 = chart2.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });
state2.selectAll("rect")
.data(function(d) { return d.ages; }) .enter().append("rect")
.attr("class", function(d) { return d < 0 ? "bar negative" : "bar positive"; })
.attr("y", function(d) { return y(Math.max(0, (d.y1))); })
.attr("height", function(d) { return Math.abs(y(d.y0) - y(d.y1)); })
.attr("width", x.rangeBand())
.style("fill", function(d) { return color(d.name); })
.call(d3.helper.tooltip()
.attr({class: 'tooltip2'})
.text(function(d, i){ return d.name + ': '+ (-((d.y0) - (d.y1))) ; })
);
var legend2 = chart2.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 100 + ")"; });
legend2.append("rect")
.attr("x", width - 30)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend2.append("text")
.attr("x", width - 35)
.attr("y", 14)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
I have created a bar chart using d3.js but I need a solid black line at 80 on the y axis going across the chart to indicate a 'maximum threshold'
I've figured out how to draw a line at the bottom but I need it to always appear at the value 80 on the chart. Is there anyway to do this?
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0])
.domain([0,1000]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select("body").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 + ")");
d3.tsv("data.tsv", type, function(error, data) {
x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(data, function(d) { return d.risk; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand())
.attr("y", function(d) { console.log(d); return y(d.risk); })
.attr("height", function(d) { return height - y(d.risk); })
.style("fill", function(d) { // <== Add these
if (d.risk >= 80) {return "#e74c3c"} // <== Add these
else { return "#3498db" } // <== Add these
;})
.on("mouseover", function(d) {
// debugger
d3.select(this).transition().style({opacity:'0.6'});
console.log(d,this.x);
div.transition()
.duration(200)
.style("opacity", .9);
div .html(d.risk)
.style("left", (this.x.baseVal.value + (this.width.baseVal.value/2) + 15) + "px")
.style("top", (this.y.baseVal.value + (this.height.baseVal.value/2)) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition().style({opacity:'1'});
});
var median = d3.median(svg.selectAll('.bar').data(),
function(d) { return d.risk; });
var median = svg.append("line")
.attr("x1", 0)
.attr("y1", (height/10)*0.8)
.attr("x2", width)
.attr("y2", (height/10)*0.8)
.attr("stroke-width", 2)
.attr("stroke", "black");
});
You have already built a scale function y which translates values on your input scale into your chart height output range. You use this when you calculate where to draw the top of each bar. You can simply use this function again when drawing the threshold line:
// not clear if you meant 80 as 80% or as literal value 80 on your input scale
var threshold = 80;
var median = svg.append("line")
.attr("x1", 0)
.attr("y1", y(threshold))
.attr("x2", width)
.attr("y2", y(threshold))
.attr("stroke-width", 2)
.attr("stroke", "black");