D3 LineChart with mouse move and show point - d3.js

I created a lineChart by d3(4.12.2). And I want to add mouse move event. It's not work for me. This is my code jsfiddle.
Thanks your help.
$(document).ready(function () {
function lineChart(elementId, xMax, yMax, xMin, yMin, x, y, dataset) {
var margin = {
top: 60,
right: 40,
bottom: 120,
left: 60
};
var w = 700;
var h = 300;
var width = w + margin.left + margin.right;
var height = h + margin.top + margin.bottom;
var xScale = d3.scaleTime()
.domain([xMin, xMax])
.range([0, w]);
var yScale = d3.scaleLinear().domain([yMin, yMax]).range([h, 0]);
var line = d3.line()
.x(function (d) {
return xScale(d[x]);
})
.y(function (d) {
return yScale(d[y]);
});
var svg = d3.select(`#${elementId}`).append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "transparent")
.on('mousemove', identifyMouse);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + h + ')')
.call(d3.axisBottom(xScale)
.tickFormat(d3.timeFormat('%Y-%m-%d %H:%M:%S')))
.selectAll('text')
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr('transform', 'rotate(-65)');
svg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(0,0)')
.call(d3.axisLeft(yScale));
svg.append('path').datum(dataset).attr('fill', 'none')
.attr('stroke', 'DodgerBlue')
.attr('stroke-width', 1)
.attr('d', line);
var bisectDate = d3.bisector(function (d) {
return d[x];
}).left;
var circle = svg.append('circle')
.style("fill", "black")
.style("stroke", "blue")
.attr('r', 5);
function identifyMouse() {
console.log(dataset.length);
var x0 = xScale.invert(d3.mouse(this)[0]);
console.log('old', x0);
x0 = new Date(`'${x0}'`).getTime();
console.log('new', x0);
var i = bisectDate(dataset, x0);
console.log(i);
var smaller = dataset[i - 1];
console.log('smaller', smaller);
var larger = dataset[i];
console.log('larger', larger);
var d = x0 - smaller[x] > larger[x] - x0 ? larger : smaller;
circle.attr("transform", "translate(" + xScale(d[x]) + "," + yScale(d[y]) + ")");
}
}
});

Instead of
var bisectDate = d3.bisector(function(d){ return d[x]; }).right;
it should have been
var bisectDate = d3.bisector(function(a, b){ return a[x] - b; }).right;
Then for bisect, to work its assumed that the dataset is sorted.
so sort the data like this before passing to bisect function:
dataset.sort(function(a, b){
return a[x]-b[x];
});
Finally, for getting the bisected data do:
var i = bisectDate(dataset, x0.getTime()); //sincex0is date object.
working code here
EDIT
How do you know to use a[x] - b
In this line below.
var i = bisectDate(dataset, x0.getTime())
here x0 is a date object.
So in the function:
d3.bisector(function(a, b){ return a[x] - b; }).right;
so a[x] is your unixtime which is tie stamp and b as mentioned is also time stamp.
So here in bisector function we subtracting both time stamps to find the closest point.

Related

Unable to create a line chart in D3.js

I want to create a line chart using D3.js.
Here an example of line chart.
This is my code:
var margin = {top: 0, right: 0, bottom: 0, left: 0};
var svg = d3.select('#linechart')
.append('svg')
.attr('width', 600)
.attr('height', 200);
var values = createAxisLine(svg);
var x = values[0];
var y = values[1];
var width = values[2];
var height = values[3];
createChartLine(svg, x, y, width, height);
function createAxisLine(thisSvg) {
var width = thisSvg.attr('width') - margin.left - margin.right;
var height = thisSvg.attr('height') - margin.top - margin.bottom;
thisSvg = thisSvg.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var x = d3.scaleBand()
.rangeRound([0, width])
.domain([2016, 2015, 2014, 2013, 2012, 2011, 2010]);
var y = d3.scaleLinear()
.range([height, 0])
.domain([0, 100]);
var xAxis = d3.axisBottom(x).tickSize(0, 0);
var yAxis = d3.axisLeft(y);
thisSvg.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', 'rotate(-65)');
thisSvg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + margin.left + ', 0)')
.call(yAxis)
.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '.71em')
.style('text-anchor', 'end');
return [x, y, width, height];
}
function createChartLine(thisSvg, x, y, width, height) {
thisSvg.selectAll(null)
.data(mydata)
.attr('transform', function(d) {
return 'translate(' + margin.left + ', ' + margin.top + ')';
});
var line = d3.line()
.x(function(d) {
return x(d.year);
})
.y(function(d) {
if(isNaN(d.value)) return 0;
else return y(d.value);
});
lines.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1.5)
.attr('d', line);
}
All the code is in this plunker.
When I run the code, nothing appears, no lines or axis are showed. But data are correctly getted so I don't understand what the problem is.
I get this error:
I need help
The problem for why nothing appears is that your the code inside script.js runs before the linechart element is loaded. One of the recommendation would be to include your script.js before the close of your body tag.
<body>
<div id='linechart'></div>
<script src="script.js"></script>
</body>

SVG path goes beyond chart area on d3 brush

When I try to brush & zoom a portion of the line chart, some parts of the selected area render outside the chart.
Code and behavior reproduction can be found at this jsbin.
Click & drag to select a portion and zoom in, double click to zoom out.
var svg = d3
.select('body')
.append('svg')
.attr('class', 'chart')
.attr('width', 960)
.attr('height', 500);
var margin = {
top: 40,
right: 40,
bottom: 40,
left: 40
};
var width = +svg.attr('width') - margin.left - margin.right;
var height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var timeParser = d3.timeParse('%Y-%m-%d');
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var brush = d3.brush().on('end', brushended);
var idleTimeout;
var idleDelay = 350;
var x0;
var y0;
var xAxis;
var yAxis;
var line = d3
.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.price);
})
.curve(d3.curveNatural);
var start = new Date();
var end = new Date(start.toDateString());
start.setFullYear(end.getFullYear() - 1);
var startStr = start.toISOString().slice(0, 10);
var endStr = end.toISOString().slice(0, 10);
var url = "https://api.coindesk.com/v1/bpi/historical/close.json?start=" + startStr + "&end=" + endStr;
d3.json(url, function(error, response) {
var data = Object.keys(response.bpi).map(function(date) {
return {
date: timeParser(date),
price: response.bpi[date]
};
});
x0 = d3.extent(data, function(d) {
return d.date;
});
y0 = d3.extent(data, function(d) {
return d.price;
});
x.domain(x0);
y.domain(y0);
xAxis = d3.axisBottom(x);
yAxis = d3.axisLeft(y);
g
.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
g
.append('g')
.attr('class', 'axis axis--y')
.call(yAxis);
g
.append('path')
.attr('class', 'line')
.datum(data)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('d', line);
svg
.append('g')
.attr('class', 'brush')
.call(brush);
});
function brushended() {
var s = d3.event.selection;
if (!s) {
if (!idleTimeout) {
return (idleTimeout = setTimeout(idled, idleDelay));
}
x.domain(x0);
y.domain(y0);
} else {
x.domain([s[0][0] - 40, s[1][0] - 40].map(x.invert, x));
y.domain([s[1][1] - 40, s[0][1] - 40].map(y.invert, y));
svg.select('.brush').call(brush.move, null);
}
zoom();
}
function idled() {
idleTimeout = null;
}
function zoom() {
var t = svg.transition().duration(750);
svg
.select('.axis--x')
.transition(t)
.call(xAxis);
svg
.select('.axis--y')
.transition(t)
.call(yAxis);
svg
.select('.line')
.transition(t)
.attr('d', line);
}
.chart {
border: 1px solid #bdbdbd;
box-sizing: border-box;
}
<script src="https://unpkg.com/d3#4.12.2/build/d3.min.js"></script>
That's the expected behaviour. The most common way to deal with that is using a <clipPath>.
For instance, in your case:
var clipPath = g.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
Then, in your path:
g.append('path')
//etc...
.attr("clip-path", "url(#clip)");
Here is the updated JSBin: https://jsbin.com/tatuhipevi/1/edit?js,output
And here the updated S.O. snippet:
var svg = d3
.select('body')
.append('svg')
.attr('class', 'chart')
.attr('width', 960)
.attr('height', 500);
var margin = {
top: 40,
right: 40,
bottom: 40,
left: 40
};
var width = +svg.attr('width') - margin.left - margin.right;
var height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var clipPath = g.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var timeParser = d3.timeParse('%Y-%m-%d');
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var brush = d3.brush().on('end', brushended);
var idleTimeout;
var idleDelay = 350;
var x0;
var y0;
var xAxis;
var yAxis;
var line = d3
.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.price);
})
.curve(d3.curveNatural);
var start = new Date();
var end = new Date(start.toDateString());
start.setFullYear(end.getFullYear() - 1);
var startStr = start.toISOString().slice(0, 10);
var endStr = end.toISOString().slice(0, 10);
var url = "https://api.coindesk.com/v1/bpi/historical/close.json?start=" + startStr + "&end=" + endStr;
d3.json(url, function(error, response) {
var data = Object.keys(response.bpi).map(function(date) {
return {
date: timeParser(date),
price: response.bpi[date]
};
});
x0 = d3.extent(data, function(d) {
return d.date;
});
y0 = d3.extent(data, function(d) {
return d.price;
});
x.domain(x0);
y.domain(y0);
xAxis = d3.axisBottom(x);
yAxis = d3.axisLeft(y);
g
.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
g
.append('g')
.attr('class', 'axis axis--y')
.call(yAxis);
g
.append('path')
.attr('class', 'line')
.datum(data)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('d', line)
.attr("clip-path", "url(#clip)");
svg
.append('g')
.attr('class', 'brush')
.call(brush);
});
function brushended() {
var s = d3.event.selection;
if (!s) {
if (!idleTimeout) {
return (idleTimeout = setTimeout(idled, idleDelay));
}
x.domain(x0);
y.domain(y0);
} else {
x.domain([s[0][0] - 40, s[1][0] - 40].map(x.invert, x));
y.domain([s[1][1] - 40, s[0][1] - 40].map(y.invert, y));
svg.select('.brush').call(brush.move, null);
}
zoom();
}
function idled() {
idleTimeout = null;
}
function zoom() {
var t = svg.transition().duration(750);
svg
.select('.axis--x')
.transition(t)
.call(xAxis);
svg
.select('.axis--y')
.transition(t)
.call(yAxis);
svg
.select('.line')
.transition(t)
.attr('d', line);
}
.chart {
border: 1px solid #bdbdbd;
box-sizing: border-box;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
Also, it's a good idea using a <clipPath> in the axes as well.

Using d3-tip on line graph without defined points

So I've gone and implemented something similar to this using that as a tutorial. However, where it reaches the point about a tooltip I want to do something slightly different, I really want to use d3-tip. So I've spent a bunch of time learning how to use d3-tip but it seems that everywhere I look people are defining elements and then attaching mouseover and mouseout events to them in order to make the tooltip appear. I don't believe I can do that because I'm using the previous method of drawing a circle over the line based on where my mouse is on the graph. So I'm wondering what I can do to get d3-tip to work with this implementation, or if it's even possible?
The following is my code:
var margin = {
top: 20,
left: 50,
right: 50,
bottom: 50
},
width = $element.innerWidth() - margin.left - margin.right,
height = 0.2 * width;
var parseTime = d3.timeParse('%m/%d/%Y');
data.forEach(function(d) {
d.date = parseTime(d.date);
d.price = +d.price;
});
data.sort(function(a, b) {
return d3.ascending(a.date, b.date);
});
var formatDate = d3.timeFormat('%b %-d / %Y');
var bisectDate = d3.bisector(function(d) { return d.date; }).left;
var x = d3.scaleTime()
.domain(d3.extent(data, function(d, i) {
return d.date;
}))
.range([0, width]);
var y = d3.scaleLinear()
.domain(d3.extent(data, function(d, i) {
return d.price;
}))
.range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickSizeOuter(0);
var yAxis = d3.axisLeft(y)
.ticks(5)
.tickSizeOuter(0);
var area = d3.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return 'Closing: ' + d.price +
'<br />' +
'Date: ' + formatDate(d.date);
});
var svg = d3.select('#priceChart')
.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 + ')');
svg.call(tip);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis);
var areaSvg = svg.append('g');
areaSvg.append('path')
.attr('class', 'area')
.attr('d', area(data))
.style('opacity', 0.3);
var lineSvg = svg.append('g');
lineSvg.append('path')
.attr('class', 'line')
.attr('d', line(data));
var focus = svg.append('g')
.style('display', 'none');
focus.append('line')
.attr('class', 'x dash')
.attr('y1', 0)
.attr('y2', height);
focus.append('line')
.attr('class', 'y dash')
.attr('x1', width)
.attr('x2', width);
focus.append('circle')
.attr('class', 'y circle')
.attr('r', 5);
svg.append('rect')
.attr('width', width)
.attr('height', height)
.style('fill', 'none')
.style('pointer-events', 'all')
.on('mouseover', function() { focus.style('display', null); })
.on('mouseout', function() { focus.style('display', 'none'); })
.on('mousemove', mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select('circle.y')
.attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')');
focus.select('.x')
.attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')')
.attr('y2', height - y(d.price));
focus.select('.y')
.attr('transform', 'translate(' + width * -1 + ',' + y(d.price) + ')')
.attr('x2', width + width);
}
Also, I've got this jsFiddle here that shows all my current work. I've got everything in place and it all works great, minus actually showing the tooltip.
I changed your fiddle a bit so that the tooltip is shown and the text is updated accordingly:
.on('mouseover', function(d) {
focus.style('display', null);
if(d!=undefined){
tip.show(d);// give the tip the data it needs to show
}
})
.on('mouseout', function() {
focus.style('display', 'none');
tip.hide();
})
I also changed mousemove function to update the tip
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select('circle.y')
.attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')');
focus.select('.x')
.attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')')
.attr('y2', height - y(d.price));
focus.select('.y')
.attr('transform', 'translate(' + width * -1 + ',' + y(d.price) + ')')
.attr('x2', width + width);
// we need to update the offset so that the tip shows correctly
tip.offset([y(d.price) - 20, x(d.date) - (width/2)] ) // [top, left]
tip.show(d);
}
Also updated the css:
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 15px;
width: 1%;
line-height: 4;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
pointer-events: none;
left: 45%;
}
https://jsfiddle.net/mkaran/5t3ycyxs/1/
There could be a better way though.Hope this helps! Good luck!

D3.js - Adding a tick value on the x axis (date format)

I have created a waterfall chart using D3 (V4) with three values (ticks) for the y axis.
The x axis tick values are automatically calculated.
How can I add an additional tick value (today's date) on the x axis (date values)?
function risklevels(d) {
if (d <= 25 && d >= 13.5) {
return "High";
} else if (d <= 13.5 && d > 7) {
return "Med";
}
return "Low";
}
function drawWaterfall(){
var margin = {top: 20, right: 20, bottom: 30, left: 50};
var width = 800 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
dt = new Date();
var x = d3.scaleTime()
.rangeRound([0, width]);
var y = d3.scaleLinear()
.rangeRound([height, 1]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y).tickFormat(risklevels).tickValues([4, 10.25, 19.125]);
var parseDate = d3.timeParse("%Y-%m-%d");
var riskwaterfall = d3.select('#riskwaterfall').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+')');
riskwaterfall.append('rect')
.attr('class', 'high')
.attr("x", 0) // start rectangle on the good position
.attr("y", 0) // no vertical translate
.attr("width", width) // correct size
.attr("height", height*((25.0-13.5)/25.0) + height*0.5/25)
.attr("fill", "#ee0000"); // full height
riskwaterfall.append('rect')
.attr('class', 'high')
.attr("x", 0) // start rectangle on the good position
.attr("y", height*((25.0-13.5)/25.0) + height*0.5/25.0) // no vertical translate
.attr("width", width) // correct size
.attr("height", height*((13.5-7.0)/25.0) + height*0.5/25.0)
.attr("fill", "#eeee00"); // full height
riskwaterfall.append('rect')
.attr('class', 'high')
.attr("x", 0) // start rectangle on the good position
.attr("y", (25-7)*height/25 + height*0.5/25.0)// no vertical translate
.attr("width", width) // correct size
.attr("height", 7*height/25 - height*0.5/25.0)
.attr("fill", "#00ee00"); // full height
var line = d3.line()
.curve(d3.curveStepAfter)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.risk); });
line('step-after');
risk.forEach(function(d) {
d.date = parseDate(d.date);
d.risk = +d.risk;
});
x.domain(d3.extent(risk, function(d) { return d.date; }));
y.domain(d3.extent(risk, function(d) { return d.risk; }));
riskwaterfall.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,'+height+')')
.call(xAxis);
riskwaterfall.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '.71em')
.style('text-anchor', 'end');
riskwaterfall.append('path')
.datum(risk)
.attr('d', line(risk));
for (var i = 0; i < risk.length; i++)
riskwaterfall.append('circle')
.datum(risk[i])
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.risk); })
.attr("stroke-width", "2px")
.attr("fill", "black" )
//.attr("fill-opacity", .5)
//.attr("visibility", "hidden")
.attr("r", 5);
}
Right now, you're creating a new date for today:
dt = new Date();
But this has no effect on the x scale (which is used by the axis generator). So, instead of:
x.domain(d3.extent(risk, function(d) { return d.date; }));
Which only goes to the maximum date in the risk data, it should be:
x.domain([d3.min(risk, function(d) { return d.date; }), dt]);
After that, to make sure that the last tick shows up, you can use nice() or concat the end domain in your tick values.

d3js v4 can't remove old data chart after update

I've modified nice AlainRo’s Block for my needs (unfortunately can't link to it, because have not enough reputation), and I can't remove old data chart after entering new data. There is my codepen. In another example I've added merge(), and the chart is well aligned but the old one is still visible and text values are missed.
I spent a lot of time on it, and I run out of ideas.
There's code
barData = [
{ index: _.uniqueId(), value: _.random(1, 20) },
{ index: _.uniqueId(), value: _.random(1, 20) },
{ index: _.uniqueId(), value: _.random(1, 20) }
];
var margin = {top: 20, right: 20, bottom: 50, left: 70},
width = 400 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
delim = 4;
var scale = d3.scaleLinear()
.domain([0, 21])
.rangeRound([height, 0]);
var x = d3.scaleLinear()
.domain([0, barData.length])
.rangeRound([0, width]);
var y = d3.scaleLinear()
.domain([0, 21])
.rangeRound([height, 0]);
var svg = d3.select('#chart')
.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 + ")");
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
function draw() {
x.domain([0, barData.length]);
var brush = d3.brushY()
.extent(function (d, i) {
return [[x(i)+ delim/2, 0],
[x(i) + x(1) - delim/2, height]];})
.on("brush", brushmove);
var svgbrush = svg.selectAll('.brush')
.data(barData)
.enter()
.append('g')
.attr('class', 'brush')
.append('g')
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
svgbrush
.append('text')
.attr('y', function (d){return scale(d.value) + 25;})
.attr('x', function (d, i){return x(i) + x(0.5);})
.attr('dx', '-.60em')
.attr('dy', -5)
.style('fill', 'white')
.text(function (d) {return d3.format('.2')(d.value);});
svgbrush
.exit()
.append('g')
.attr('class', 'brush')
.remove();
function brushmove() {
if (!d3.event.sourceEvent) return; // Only transition after input.
if (!d3.event.selection) return; // Ignore empty selections.
if (d3.event.sourceEvent.type === "brush") return;
var d0 = d3.event.selection.map(scale.invert);
var d = d3.select(this).select('.selection');;
var d1 =[d0[0], 0];
d.datum().value = d0[0]; // Change the value of the original data
d3.select(this).call(d3.event.target.move, d1.map(scale));
svgbrush
.selectAll('text')
.attr('y', function (d){return scale(d.value) + 25;})
.text(function (d) {return d3.format('.2')(d.value);});
}
}
draw();
function upadateChartData() {
var newBarsToAdd = document.getElementById('charBarsCount').value;
var newBarData = function() {
return { index: _.uniqueId(), value: _.random(1, 20) }
};
newBarData = _.times(newBarsToAdd, newBarData);
barData = _.concat(barData, newBarData)
draw();
};
Is it also possible to remove cross pointer and leave only resize, when I'm dragging top bar border?
You're appending g elements twice. This:
svgbrush.enter()
.append('g')
.attr('class', 'brush')
.merge(svgbrush)
.append('g')
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
Should be:
svgbrush.enter()
.append('g')
.attr('class', 'brush')
.merge(svgbrush)
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
Here is your updated Pen: http://codepen.io/anon/pen/VmavyX
PS: I also made other changes, declaring some new variables, just to organize your enter and update selections and solving the texts problem.

Resources