admin管理员组文章数量:1355754
i have created some histogram with d3.js
.
I managed to change fill color of rect
depending on the position of the brush
.
But i would like to change the color inside a rect
. For example if the brush start
is in the middle of the rect
i would like to have my rect
with two color.
At the moment this is what i have :
And this is what i would like to have :
I have seen some examples like Here. I'm new to d3 and i try to understand the code.
I see that they use clip-path
that certainly hide the background bar when their is no brush and show them when their is one depending on the range of the brush.
Here is a JS Bin
Update
I have read in details the code provided in the link. And i found that they dont create <rect>
element to make chart but barPath
like follow :
function barPath(groups) {
var path = [],
i = -1,
n = groups.length,
d;
while (++i < n) {
d = groups[i];
path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
}
return path.join("");
}
But i didn't event understand what happend in this function and how to dot it in this way if their is no other way to do this.
i have created some histogram with d3.js
.
I managed to change fill color of rect
depending on the position of the brush
.
But i would like to change the color inside a rect
. For example if the brush start
is in the middle of the rect
i would like to have my rect
with two color.
At the moment this is what i have :
And this is what i would like to have :
I have seen some examples like Here. I'm new to d3 and i try to understand the code.
I see that they use clip-path
that certainly hide the background bar when their is no brush and show them when their is one depending on the range of the brush.
Here is a JS Bin
Update
I have read in details the code provided in the link. And i found that they dont create <rect>
element to make chart but barPath
like follow :
function barPath(groups) {
var path = [],
i = -1,
n = groups.length,
d;
while (++i < n) {
d = groups[i];
path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
}
return path.join("");
}
But i didn't event understand what happend in this function and how to dot it in this way if their is no other way to do this.
Share Improve this question edited Aug 5, 2016 at 12:36 Christophe D. asked Aug 5, 2016 at 9:00 Christophe D.Christophe D. 1,08911 silver badges21 bronze badges2 Answers
Reset to default 6Instead of trying to draw partial bars (as your edit seems to suggest), I would instead append the bars twice, once gray on bottom and then steelblue on top. You can then just apply a clip-path to the blue bars and when they are clipped you'll see the gray below.
Full code:
<!DOCTYPE html>
<html>
<head>
<script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare./ajax/libs/d3/3.5.3/d3.js"></script>
<style>
.charts {
padding: 10px 0;
}
.chart {
padding-left: 20px;
padding-top: 10px;
}
.axis text {
font: 10px sans-serif;
fill: black;
}
.chart text {
font: 10px sans-serif;
fill: black;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
/*dont display yAxis for categorical variable*/
#chart .y.axis g {
display: none;
}
/*Labels in categorical chart */
text#catTitle.catTitle {
font: 10px sans-serif;
fill: white;
}
/*Color for the brush */
.brush rect.extent {
fill: steelblue;
fill-opacity: .125;
}
/*Color for the brush resize path*/
.brush .resize path {
fill: #eee;
stroke: #666;
}
/*Color for the hidden object*/
.hidden {
fill: grey;
}
.bar {
fill: steelblue;
}
</style>
</head>
<body>
<svg class="chart" id="chart"></svg>
<script>
var data = [{
key: 1,
value: 37
}, {
key: 1.5,
value: 13
}, {
key: 2.5,
value: 1
}, {
key: 3,
value: 4
}, {
key: 3.5,
value: 14
}, {
key: 4,
value: 18
}, {
key: 4.5,
value: 21
}, {
key: 5,
value: 17
}, {
key: 5.5,
value: 16
}, {
key: 6,
value: 5
}, {
key: 6.5,
value: 4
}];
var margin = {
top: 10,
right: 41,
bottom: 42,
left: 10
};
var width = 400 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.value
})])
.range([height, 0]);
var x = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.key;
}) + 1])
.rangeRound([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var chart = d3.select(".chart#chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", 15 + "px");
chart.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var brush = d3.svg.brush()
.x(x)
.on("brush", brushed)
.on("brushend", brushend);
function brushend() {
if (brush.empty()){
chart.select("#clip>rect")
.attr("x", 0)
.attr("width", width);
}
}
function brushed() {
var e = brush.extent();
chart.select("#clip>rect")
.attr("x", x(e[0]))
.attr("width", x(e[1]) - x(e[0]));
}
chart.selectAll(".hidden")
.data(data)
.enter().append("rect")
.attr("class", "hidden")
.attr("x", function(d) {
return x(d.key);
})
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
})
.attr("width", x(0.5))
.style("stroke", "white")
.append("title")
.text(function(d) {
return d.key;
});
chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("clip-path", "url(#clip)")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.key);
})
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
})
.attr("width", x(0.5))
.style("stroke", "white")
.append("title")
.text(function(d) {
return d.key;
});
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("text") //Add chart title
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom) + ")")
.style("text-anchor", "middle")
.text("Petal Length");
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
chart.append("g")
.attr("class", "x brush")
.call(brush) //call the brush function, causing it to create the rectangles
.selectAll("rect") //select all the just-created rectangles
.attr("y", -6)
.attr("height", (height + margin.top)) //set their height
function resizePath(d) {
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 3;
return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8);
}
chart.selectAll(".resize").append("path").attr("d", resizePath);
</script>
</body>
</html>
For anyone looking to bring @Mark's answer to v6:
const data = [{
key: 1,
value: 37
}, {
key: 1.5,
value: 13
}, {
key: 2.5,
value: 1
}, {
key: 3,
value: 4
}, {
key: 3.5,
value: 14
}, {
key: 4,
value: 18
}, {
key: 4.5,
value: 21
}, {
key: 5,
value: 17
}, {
key: 5.5,
value: 16
}, {
key: 6,
value: 5
}, {
key: 6.5,
value: 4
}];
// svg sizes
const width = 400,
height = 200;
const m = 50;
const margin = {
top: m,
right: m,
bottom: m,
left: m,
};
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.value))
.range([height - margin.bottom, margin.top]);
const x = d3.scaleLinear()
.domain(d3.extent(data, d => d.key).map((v, i) => i==0 ? v - 1 : v + 1))
.rangeRound([margin.left, width - margin.right]);
const svg = d3.select('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', `0 0 ${width} ${height}`)
const rects = svg.append('g').attr('class', 'rects');
const clips = svg.append('g').attr('class', 'clips');
svg.append('g')
.attr('class', 'x-axis')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append('g')
.attr('class', 'y-axis')
.style('display', 'none')
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', margin.left)
.attr('y', margin.top)
.attr('width', width - margin.right)
.attr('height', height - margin.bottom);
const brush = d3.brushX()
.extent([
[x.range()[0], margin.top],
[x.range()[1], height - margin.bottom]
])
.on('brush', brushed)
.on('start', brushed)
.on('end', brushend);
function brushend(e) {
if (!e.selection || !e.selection.length) {
svg.select('#clip>rect')
.attr('x', margin.left)
.attr('width', width - margin.right);
}
}
function brushed(e) {
svg.select('#clip>rect')
.attr('x', e.selection[0])
.attr('width', e.selection[1] - e.selection[0]);
const selected = {
x0: x.invert(e.selection[0]),
x1: x.invert(e.selection[1]),
}
}
rects.selectAll('rect')
.data(data)
.enter().append('rect')
.attr('x', d => x(d.key))
.attr('y', d => y(d.value))
.attr('height', d => height - y(d.value) - margin.bottom)
.attr('width', 20)
.style('stroke', 'white')
.style('fill', 'gray')
.append('title')
.text(d => d.key);
clips.selectAll('rect')
.data(data)
.enter().append('rect')
.attr('clip-path', 'url(#clip)')
.attr('x', d => x(d.key))
.attr('y', d => y(d.value))
.attr('height', d => height - y(d.value) - margin.bottom)
.attr('width', 20)
.style('stroke', 'white')
.append('title')
.text(d => d.key);
svg.append('g')
.attr('class', 'x brush')
.call(brush) // initialize the brush
.selectAll('rect')
.attr('y', 0)
.attr('height', height)
<script src="https://cdnjs.cloudflare./ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg/>
本文标签: javascriptd3js brush fill color histogramStack Overflow
版权声明:本文标题:javascript - d3.js brush fill color histogram - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743952970a2567626.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论