I have an SVG clipPath made of multiple path elements, which I need to apply to a group of elements. I only want to clip out the area under the path stroke itself, not in between the paths. (example that doesn't do what I want follows)
var lineData = [ { "x": 1, "y": 5}, { "x": 100, "y": 400},
{ "x": 300, "y": 100}, { "x": 600, "y": 600},
{ "x": 700, "y": 50} ];
var lineData2 = [ { "x": 1, "y": 500}, { "x": 100, "y": 100},
{ "x": 300, "y": 700}, { "x": 600, "y": 60},
{ "x": 700, "y": 700} ];
var lineFunction = d3.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.curve(d3.curveBundle);
var svg = d3.select('body')
.append('svg')
.attr('id', 'svg')
.attr('width', 660)
.attr('height', 660)
.style('outline', '1px solid red')
.append('g')
.attr('clip-path', 'url(#clippy)');
var polygon = svg.append('polygon')
.attr('points', '230 10, 660 330, 230 650')
.attr('fill', '#c99');
var circle = svg.append('circle')
.attr('cx', 230)
.attr('cy', 330)
.attr('r', 200)
.attr('fill', '#9c6')
var clippy = d3.select('#svg')
.append('defs')
.append('clipPath')
.attr('id', 'clippy');
clippy.append("path")
.attr("d", lineFunction(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 18)
.attr("fill", "none");
clippy.append("path")
.attr("d", lineFunction(lineData2))
.attr("stroke", "blue")
.attr("stroke-width", 18)
.attr("fill", "none");
Basically I want to accomplish something similar to what you get using letters, but instead using lines/paths.
var lineData = [ { "x": 1, "y": 5}, { "x": 100, "y": 400},
{ "x": 300, "y": 100}, { "x": 600, "y": 600},
{ "x": 700, "y": 50} ];
var lineData2 = [ { "x": 1, "y": 500}, { "x": 100, "y": 100},
{ "x": 300, "y": 700}, { "x": 600, "y": 60},
{ "x": 700, "y": 700} ];
var lineFunction = d3.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.curve(d3.curveBundle);
var svg = d3.select('body')
.append('svg')
.attr('id', 'svg')
.attr('width', 660)
.attr('height', 660)
.style('outline', '1px solid red')
.append('g')
.attr('clip-path', 'url(#clippy)');
var polygon = svg.append('polygon')
.attr('points', '230 10, 660 330, 230 650')
.attr('fill', '#c99');
var circle = svg.append('circle')
.attr('cx', 230)
.attr('cy', 330)
.attr('r', 200)
.attr('fill', '#9c6')
var clippy = d3.select('#svg')
.append('defs')
.append('clipPath')
.attr('id', 'clippy');
clippy.append('text')
.attr('x', 120)
.attr('y', 320)
.attr('font-size', '4em')
.attr('font-weight', 'bold')
.attr('font-family', 'Georgia')
.text('This is a clip');
clippy.append('text')
.attr('x', 120)
.attr('y', 420)
.attr('font-size', '4em')
.attr('font-weight', 'bold')
.attr('font-family', 'Georgia')
.text('Also a clip')
Please help!
EDIT: Here's a Codepen with both examples.
From my reading of the SVG spec, it's not possible to use only a <path>'s stroke as the clipping path:
The raw geometry of each child element exclusive of rendering properties such as ‘fill’, ‘stroke’, ‘stroke-width’ within a ‘clipPath’ conceptually defines a 1-bit mask (with the possible exception of anti-aliasing along the edge of the geometry) which represents the silhouette of the graphics associated with that element. Anything outside the outline of the object is masked out.
However, converting the <clipPath> to a <mask> element produces what I think is your desired effect.
Here's a forked CodePen to demonstrate — the paths have have their strokes set to white, and the <text> elements were also given a fill of white to match the clip-path effect.
I have an existing bar chart which works fine.
But I want to make it horizontal by flipping the axis.
Full code:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var stack = d3.stack;
var dataset = {
"categories": ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
"series": ["Group1", "Group2", "Group3"],
"colors": ["#3498db", "#e74c3c", "#2ecc71"],
"layers": [
[{
"y": 1,
"y0": 20,
"month": "Monday"
},
{
"y": 2,
"y0": 18,
"month": "Tuesday"
},
{
"y": 5,
"y0": 18,
"month": "Wednesday"
},
{
"y": 10,
"y0": 20,
"month": "Thursday"
},
{
"y": 14,
"y0": 23,
"month": "Friday"
},
{
"y": 18,
"y0": 24,
"month": "Saturday"
},
{
"y": 20,
"y0": 24,
"month": "Sunday"
}
],
[{
"y": 12,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 24,
"month": "Tuesday"
},
{
"y": 13,
"y0": 23,
"month": "Wednesday"
},
{
"y": 16,
"y0": 21,
"month": "Thursday"
},
{
"y": 18,
"y0": 23,
"month": "Friday"
},
{
"y": 19,
"y0": 22,
"month": "Saturday"
},
{
"y": 20,
"y0": 22,
"month": "Sunday"
}
],
[{
"y": 8,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 21,
"month": "Tuesday"
},
{
"y": 12,
"y0": 19,
"month": "Wednesday"
},
{
"y": 15,
"y0": 23,
"month": "Thursday"
},
{
"y": 18,
"y0": 21,
"month": "Friday"
},
{
"y": 16,
"y0": 23,
"month": "Saturday"
},
{
"y": 17,
"y0": 24,
"month": "Sunday"
}
]
]
};
n = dataset["series"].length;
m = dataset["layers"].length;
yGroupMax = d3.max(dataset["layers"], function(layer) {
return d3.max(layer, function(d) {
return d.y0;
});
});
yGroupMin = d3.min(dataset["layers"], function(layer) {
return d3.min(layer, function(d) {
return d.y;
});
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xScale = d3.scaleBand()
.domain(dataset["categories"])
.rangeRound([0, width])
.padding(.08);
var yScale = d3.scaleLinear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.axisBottom(xScale)
.tickSize(7)
.tickPadding(6);
var yAxis = d3.axisLeft(yScale).ticks(24);
var svg = d3.select("#groupchart").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 layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("x", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return xScale(d.month) + xScale.bandwidth() / n * k;
})
.attr("width", xScale.bandwidth() / n)
.transition()
.attr("y", function(d) {
return yScale(d.y0);
})
.attr("height", function(d) {
return height - yScale(d.y0 - d.y)
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width / 3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Grouped Bar Chart Test");
var legend = svg.append("g")
.attr("class", "legend")
legend.selectAll('text')
.data(dataset["colors"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", (width - margin.right) / 1.6)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {
return d;
})
legend.selectAll('text')
.data(dataset["series"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", ((width - margin.right) / 1.6) + 9)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'month');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d) {
if (!d.month) return null;
tooltip.select('.month').html("<b>" + d.month + "</b>");
tooltip.select('.tempRange').html(d.y + ":00 Hours to " + d.y0 + ":00 Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.month) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Grouped Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
I tried to do it but I mess it up everytime. When I try to flip the axis by changing the portion below which is just reversing the x and y, it does not appear correctly:
var xAxis = d3.axisBottom(xScale)
.tickSize(7)
.tickPadding(6);
var yAxis = d3.axisLeft(yScale).ticks(24);
I can't figure this out.
Why:
So that I can fit more stuff per group of bars when they are horizontal as they are going to be long and have more space inside.
Here is a reversed (horizontal) version of your chart:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var stack = d3.stack;
var dataset = {
"categories": ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
"series": ["Group1", "Group2", "Group3"],
"colors": ["#3498db", "#e74c3c", "#2ecc71"],
"layers": [
[{
"y": 1,
"y0": 20,
"month": "Monday"
},
{
"y": 2,
"y0": 18,
"month": "Tuesday"
},
{
"y": 5,
"y0": 18,
"month": "Wednesday"
},
{
"y": 10,
"y0": 20,
"month": "Thursday"
},
{
"y": 14,
"y0": 23,
"month": "Friday"
},
{
"y": 18,
"y0": 24,
"month": "Saturday"
},
{
"y": 20,
"y0": 24,
"month": "Sunday"
}
],
[{
"y": 12,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 24,
"month": "Tuesday"
},
{
"y": 13,
"y0": 23,
"month": "Wednesday"
},
{
"y": 16,
"y0": 21,
"month": "Thursday"
},
{
"y": 18,
"y0": 23,
"month": "Friday"
},
{
"y": 19,
"y0": 22,
"month": "Saturday"
},
{
"y": 20,
"y0": 22,
"month": "Sunday"
}
],
[{
"y": 8,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 21,
"month": "Tuesday"
},
{
"y": 12,
"y0": 19,
"month": "Wednesday"
},
{
"y": 15,
"y0": 23,
"month": "Thursday"
},
{
"y": 18,
"y0": 21,
"month": "Friday"
},
{
"y": 16,
"y0": 23,
"month": "Saturday"
},
{
"y": 17,
"y0": 24,
"month": "Sunday"
}
]
]
};
n = dataset["series"].length;
m = dataset["layers"].length;
xGroupMax = d3.max(dataset["layers"], function(layer) {
return d3.max(layer, function(d) {
return d.y0;
});
});
xGroupMin = d3.min(dataset["layers"], function(layer) {
return d3.min(layer, function(d) {
return d.y;
});
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xScale = d3.scaleLinear() //
.domain([xGroupMin, xGroupMax]) //
.range([0, width - margin.left]); //
var yScale = d3.scaleBand() //
.domain(dataset["categories"])
.rangeRound([0, height]) //
.padding(.08);
var xAxis = d3.axisBottom(xScale).ticks(24); //
var yAxis = d3.axisLeft(yScale).tickSize(7).tickPadding(6); //
var svg = d3.select("#groupchart").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 layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("y", function(d, i, j) { //
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return yScale(d.month) + yScale.bandwidth() / n * k; //
})
.attr("height", yScale.bandwidth() / n) //
.transition()
.attr("x", function(d) { //
return xScale(d.y) //
})
.attr("width", function(d) { //
return xScale(d.y0 - d.y); //
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width / 3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Grouped Bar Chart Test");
var legend = svg.append("g")
.attr("class", "legend")
legend.selectAll('text')
.data(dataset["colors"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", (width - margin.right) / 1.6)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {
return d;
})
legend.selectAll('text')
.data(dataset["series"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", ((width - margin.right) / 1.6) + 9)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'month');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d) {
if (!d.month) return null;
tooltip.select('.month').html("<b>" + d.month + "</b>");
tooltip.select('.tempRange').html(d.y + ":00 Hours to " + d.y0 + ":00 Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.month) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Grouped Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
This requires a bit more than just switching x and y axes. You'll also have to modify the w/y/width/height attributes of rectangles, as well as the the position of axes.
I've marked the modified lines with //.
Just for the fun (and if like me, starting from a vertical graph, you're lost doing all these inversions of axes/scales), here is another way of doing using a rotation by 90° of the whole graph!:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var stack = d3.stack;
var dataset = {
"categories": ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
"series": ["Group1", "Group2", "Group3"],
"colors": ["#3498db", "#e74c3c", "#2ecc71"],
"layers": [
[{
"y": 1,
"y0": 20,
"month": "Monday"
},
{
"y": 2,
"y0": 18,
"month": "Tuesday"
},
{
"y": 5,
"y0": 18,
"month": "Wednesday"
},
{
"y": 10,
"y0": 20,
"month": "Thursday"
},
{
"y": 14,
"y0": 23,
"month": "Friday"
},
{
"y": 18,
"y0": 24,
"month": "Saturday"
},
{
"y": 20,
"y0": 24,
"month": "Sunday"
}
],
[{
"y": 12,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 24,
"month": "Tuesday"
},
{
"y": 13,
"y0": 23,
"month": "Wednesday"
},
{
"y": 16,
"y0": 21,
"month": "Thursday"
},
{
"y": 18,
"y0": 23,
"month": "Friday"
},
{
"y": 19,
"y0": 22,
"month": "Saturday"
},
{
"y": 20,
"y0": 22,
"month": "Sunday"
}
],
[{
"y": 8,
"y0": 24,
"month": "Monday"
},
{
"y": 14,
"y0": 21,
"month": "Tuesday"
},
{
"y": 12,
"y0": 19,
"month": "Wednesday"
},
{
"y": 15,
"y0": 23,
"month": "Thursday"
},
{
"y": 18,
"y0": 21,
"month": "Friday"
},
{
"y": 16,
"y0": 23,
"month": "Saturday"
},
{
"y": 17,
"y0": 24,
"month": "Sunday"
}
]
]
};
n = dataset["series"].length;
m = dataset["layers"].length;
yGroupMax = d3.max(dataset["layers"], function(layer) {
return d3.max(layer, function(d) {
return d.y0;
});
});
yGroupMin = d3.min(dataset["layers"], function(layer) {
return d3.min(layer, function(d) {
return d.y;
});
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xScale = d3.scaleBand()
.domain(dataset["categories"])
.rangeRound([0, width])
.padding(.08);
var yScale = d3.scaleLinear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.axisBottom(xScale)
.tickSize(7)
.tickPadding(6);
var yAxis = d3.axisLeft(yScale).ticks(24);
var svg = d3.select("#groupchart").append("svg")
.attr("height", width + margin.left + margin.right) //
.attr("width", height + margin.left + margin.bottom) //
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.left + ") rotate(90) translate(0,-400)"); //
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("x", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return xScale(d.month) + xScale.bandwidth() / n * k;
})
.attr("width", xScale.bandwidth() / n)
.transition()
.attr("y", function(d) {
return yScale(d.y0);
})
.attr("height", function(d) {
return height - yScale(d.y0 - d.y)
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text") //
.attr("transform", "rotate(-90) translate(-10,-18)") //
.style("text-anchor", "end"); //
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("text") //
.attr("transform", "rotate(-90) translate(13,-18)") //
.style("text-anchor", "end"); //
svg.append("text")
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Grouped Bar Chart Test (Rien ne va plus)")
.attr("transform", "rotate(-90) translate(-350,-35)"); //
var legend = svg.append("g")
.attr("class", "legend")
legend.selectAll('text')
.data(dataset["colors"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", (width - margin.right) / 1.6)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {
return d;
})
.attr("transform", "rotate(-90) translate(-600," + (width/2 - 30) + ")"); //
legend.selectAll('text')
.data(dataset["series"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", ((width - margin.right) / 1.6) + 9)
.text(function(d) {
return d;
})
.attr("transform", "rotate(-90) translate(-600," + (width/2 - 30) + ")"); //
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'month');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d) {
if (!d.month) return null;
tooltip.select('.month').html("<b>" + d.month + "</b>");
tooltip.select('.tempRange').html(d.y + ":00 Hours to " + d.y0 + ":00 Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.month) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Grouped Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
Note: this is of course not recommended.
I am currently drawing some arrows and would like them to have different/scaling stroke-widths (some being fatter than others)
I am currently using this code but the stroke width just won't change. If I hard code a value like 5 it does change to that.
I am using exactly the same scaling in another code but there I am scaling the heights of bars (no problems there).
Here is a fiddle of what I'm working with: https://fiddle.jshell.net/42jdw2Lt/
I would like to use the values in series that I marked as "num" to scale my strokewidth with.
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js">
</script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script>
var svg = d3.select("body").append("svg")
.attr("width", 1500)
.attr("height", 1500);
var strwi = d3.scaleLinear()
.domain([100, 400])
.range([7,35])
var group = svg.append("g")
var series = [
[{"x": 360, "y": 250, "num": 100}, {"x": 520, "y": 400, "num":
100}, {"x": 630, "y": 300, "num": 100}],
[{"x": 71, "y": 45, "num": 200}, {"x": 32, "y": 39, "num":
200}, {"x": 43, "y": 70, "num": 200}],
[{"x": 100, "y": 300, "num": 300}, {"x": 200, "y": 200, "num":
300}, {"x": 300, "y": 200, "num": 300}], [{"x": 101, "y": 202,
"num": 400}, {"x": 102, "y": 204, "num": 400}, {"x": 103, "y":
215, "num": 400}]
];
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return d.x; })
.y(function(d) { return d.y; });
svg.append("svg:defs").append("svg:marker")
.attr("id", "triangle")
.attr("refX", 0)
.attr("refY", 5)
.attr("markerWidth", 14)
.attr("markerHeight", 14)
.attr("viewBox", "0 0 20 10")
.attr("orient", "auto")
.append("path")
.attr("d", "M 0,0 L 10,5 L 0,10 z")
.style("fill", "black");
group.selectAll(".line")
.data(series)
.enter().append("path")
.attr("class", "line")
.attr("stroke-width", function(d) {return strwi(d); })
.attr("stroke", "black")
.attr("fill", "none")
.attr("d", line)
.attr("marker-end", "url(#triangle)");
</script>
I just made a couple of changes to the code:
I set stroke-width and some other attibutes as styles
I used the first element of a series, and its num property, to compute the width
The code now looks like this, and has different thicknesses for each series
group.selectAll(".line")
.data(series)
.enter().append("path")
.attr("class", "line")
.style("stroke-width", function(d) {return strwi(d[0].num); })
.style("stroke", "black")
.style("fill", "none")
.attr("d", line)
.attr("marker-end", "url(#triangle)");
There must be something obvious I'm missing here.
I'm trying to draw a simple line and this is my javascript:
// CRASH DATA
var lineData = [
{ "x": 0, "y": 0.5},
{ "x": 2, "y": 0.1},
{ "x": 4, "y": -0.5},
{ "x": 6, "y": -0.8},
{ "x": 8, "y": -0.9},
{ "x": 10, "y": -0.10},
{ "x": 12, "y": -0.10},
{ "x": 14, "y": -0.11},
{ "x": 16, "y": -0.10},
{ "x": 18, "y": -0.9},
{ "x": 20, "y": -0.7},
{ "x": 22, "y": -0.6},
{ "x": 24, "y": -0.5},
{ "x": 26, "y": -0.3},
{ "x": 28, "y": -0.1},
{ "x": 30, "y": 0.2},
{ "x": 32, "y": 0.4},
{ "x": 34, "y": 0.8},
{ "x": 36, "y": 0.8},
{ "x": 38, "y": 0.7},
{ "x": 40, "y": 0.4},
{ "x": 42, "y": 0.4},
{ "x": 44, "y": 0.4},
{ "x": 46, "y": 0.2},
{ "x": 48, "y": 0.1},
{ "x": 50, "y": 0}
];
//DRAW TRAJECTORY
function draw(data){
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
//This is the accessor function we talked about above
var lineFunction = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("linear");
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 + ")");
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain(d3.extent(data, function(d) { return d.y; }));
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
svg.append("path") // Add the lineFunction path.
.attr("class", "line")
.attr("d", lineFunction(data));
};
//PUT EVERYTHING ON SCREEN
$( document ).ready(function() {
draw(lineData);
});
And here is the outcome:
You aren't actually using the scales you define. Your line function should be
var lineFunction = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); })
.interpolate("linear");
Complete example here.