How do I align tick values/label properly below the tick line - svg

I am working on continuous color legend using d3.interpolateViridis. I have problem in aligning the legend tick values. I want to display my domain values horizontally(below tick but in straign line and not slant).
Here is my code snippet for tick label:
const margin = { top: 10, right: 60, bottom: 10, left: 2 };
const legendaxis = axisRight(legendscale)
.scale(legendscale)
.tickSize(16)
.tickValues(legendscale.domain());
//other code
svg.append("g")
.attr("class", "axis")
.style("font-size", "14px")
.style("font-weight", "700")
.attr(
"transform",
"translate(" +
(80 - margin.left - margin.right + 3) +"," +margin.top +")")
.call(legendaxis);
I have also shared Fiddle link :
https://jsfiddle.net/shru90/j8hLq1b2/10/

Related

SVG g hides when parent g is set to a height

I am relatively new to SVG. I am plotting a chart which will dynamically plot temperature or wind value on x,y axis respectively. I am good with x-axis positioning.
But when it comes to Y-Axis, position come right but if the value is higher than parent chart height, it get cut off as you can see in the picture.
Need help on how to force visible the circle/element even it exceeds the parent element width or height?
Here is how mark up gets generated
I am using d3.js for this.
Here is the code for generating circle with text
let svg = container
.append("svg")
.attr("width", width)
.attr("height", height+(height*0.7));
const chart = svg
.append("g")
.attr('class','chartwind')
.attr("transform", "translate(" + padding.left + "," + (padding.top) + ")")
chart.append("path")
.data(datapoints)
.attr("class", "line wind-line")
.style("stroke", colorScale("wind"))
.style('stroke-width', '2px')
.attr("d", windLine)
let windPoint = chart.selectAll('g.windpoint').data(datapoints).enter().append('g').attr('class', 'windpoint').attr('transform', function (d) {
return 'translate(' + (Math.round(xScale(d.parsedUtcDateTimeNow)) - 10) + ',' + yScale(d.windSpeed) + ')';
})
chart.selectAll('.windcircle')
.data(Infos)
.enter().append('circle')
.attr("class", "windcircle")
.style("stroke", colorScale("wind"))
.style('stroke-width', '2px')
.attr("cx", (d) => xScale(d.parsedUtcDateTimeNow))
.attr("cy", (d) => {
return yScale(d.windSpeed);
})
.attr('r', 3)
.style("fill", colorScale("wind"))
windPoint
.append('circle')
.attr("cx", 0)
.attr("cy", 0)
.attr("r", function (d) {
return 8;
})
.attr("fill", "green")
.attr("transform", "translate(0,-23)")
windPoint
.append('text')
.attr("fill", "white")
.attr("transform", "translate(0,-19)")
.attr("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "600")
.text((d) => {
return d.windGust;
});
windPoint
.append('text')
.attr('text-anchor', 'middle')
//.attr("transform","translate(0,5)")
.text((d) => {
return d.windSpeed;
});
Update
This is how I am constructing SVG height and width
function getSizesById(id) {
const container = document.querySelector(`#${id}`)
if (!container)
return null
return {
height: container.clientHeight,
width: container.clientWidth,
}
}
const { width, height } = (() => {
return getSizesById(containerID)
})()
const { width, height } = (() => {
return getSizesById(containerID)
})(),
padding = {
...size.padding,
top: 20,
bottom: 20
},
chartHeight = height - padding.bottom - padding.top,
chartWidth = width - padding.left - padding.right
const container = d3.select(`#${containerID}`)
let svg = container
.append("svg")
.attr("width", width)
.attr("height", height);
Note: SVG height (or chart) should look with in the DIV and only when the data points go over the scale, then we need data to be visible over the div height.
<g> elements do not have any inherent size. They are only a logical wrapper for a group of markup tags, and a place to give them some common properties. What restricts the visible parts of your chart is the <svg> element.
Your code shows that each datapoint is represented by grafic elements that span a bounding box of (-8 -31 16 35) (left - top - width - height). This is how much space you need to show all of it.
Remove the transform attribute from your .chartwind group. The space you need to show the complete graph is
left: lower boundary of your xScale range minus 8
top: lower boundary of your yScale range minus 31 (in the downward coordinate system)
width: extent of your xScale range plus 16
height: extent of your yScale range plus 35
Add some padding if you like.
Add a viewBox attribute with these four numbers to the <svg> element: viewbox="<left> <top> <width> <height>". The area described like this will then be fitted inside the available space of the <svg> element, without you having to do any further figuring out of transformations.

PIXI.Text as a hole but keeping stroke

I am trying to add text to a PIXI Application as a hole, cutting through the canvas showing what's underneath it, but need to keep the stroke around each letter. I am using a blendMode to cut the text through, but it removes the stroke as well. Is it even possible?
//hacked clearing blendmode
app.renderer.state.blendModes[20] = [0,
WebGLRenderingContext.ONE_MINUS_SRC_ALPHA];
//Adding text
var style = new PIXI.TextStyle({
fontFamily: 'din-condensed',
fontSize: '400px',
fontWeight: 400,
stroke: '#25556f',
strokeThickness: 5
});
var invertedText = new PIXI.Text(text, style);
invertedText.x = 0;
invertedText.y = (height / 2) - ($(heading).height() / 2);
invertedText.blendMode = 20;
app.stage.addChild(invertedText);

Is there any way to create rounded corners for SVG ARC?

I would like to create rounded corners for svg arc.
Here is my code for above arc
(function()
{
var svg = d3.select('#pieChart').append("svg:svg").attr('width', 300).attr('height', 300).attr('fill', '#123456').append("g").attr("transform", "translate(" + 300 / 2 + "," + 300 / 2 + ")");
var arc = d3.svg.arc().innerRadius(100).outerRadius(140).startAngle(0).endAngle(190 * (Math.PI)/180);
svg.append("path").attr('d', arc);
}());
All you need to do is specify a corner radius. However, cornerRadius is only a recent addition to d3, so it won't work in any of the versions currently available in the SO snippet editor.
You can see it working below, using the latest version of d3 imported directly from d3js.org:
(function(theta) {
var svg = d3.select('#pieChart')
.append("svg:svg")
.attr('width', 300)
.attr('height', 300)
.attr('fill', '#123456')
.append("g")
.attr("transform", "translate(" + 300 / 2 + "," + 300 / 2 + ")");
var arc = d3.svg.arc()
/*************************************************/
/* This only works in the latest version (3.5.5) */
.cornerRadius(20)
/*************************************************/
.innerRadius(100)
.outerRadius(140)
.startAngle(0)
.endAngle(theta * (Math.PI)/180)
svg.append("path")
.attr('d', arc)
}(240));
<!-- Import the latest version of d3 directly: -->
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<div id="pieChart"></div>
If you add a stroke then you can set the properties appropriately on the stroke to render rounded corners - here's the rough idea:
(function()
{
var svg = d3.select('#pieChart').append("svg:svg").attr('width', 300).attr('height', 300).append("g").attr("transform", "translate(" + 300 / 2 + "," + 300 / 2 + ")");
var arc = d3.svg.arc().innerRadius(100).outerRadius(100).startAngle(0).endAngle(190 * (Math.PI)/180);
svg.append("path").attr('stroke-width','60px').attr('stroke-linejoin','round').attr('d', arc).attr('fill', '#123456').attr('stroke','#123456');
}());
Demo fiddle here

.style of child nodes in d3js

I'm trying to make a simple graph with nodes and links. I have "g" elements containing a circle and its text, and links on their own. I have, for example, this bit on code called on a mouseover event:
//check if circle is connected to current "viewed" (mouseover-ed)
//circle via a link referenced by "that" and paint it green if so
circles.filter(function() {
return d3.select(this).attr("index") == d3.select(that).attr("src");
}).attr("viewed",1).style("stroke", "green");
});
This was really a long shot as nodes is the 'g' element container and I wasn't sure what calling .style would do, but to my surprise it did change the color - but only for the text!
Is there a way to make it change the stroke style of the circle as well?
The declaration code:
var circles = svg.append("g")
.attr("class","nodes")
.selectAll("circle")
.data(graph.nodes)
.enter()
.append("g")
.attr("transform",function(d,i){d.x = getX(i);d.y=getY(i);return "translate(" + d.x + "," + d.y + ")";})
.attr("name", function(d){return d.name;})
.attr("viewed", 0)
.attr("focused", 0)
.attr("index", function(d, i) {return i;});
circles.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", node_radius_wo_pad)
.on("mouseover", function(){...};
circles.append("text")
.attr("text-anchor","middle")
.text(function(d){return d.name});
The reason this is working is that you haven't explicitly declared a stroke colour for the text and so it inherits what you set for the parent g element. To make this work for the circles, you have to select them explicitly:
var toChange = circles.filter(function() {
return d3.select(this).attr("index") == d3.select(that).attr("src");
});
toChange.attr("viewed", 1);
toChange.selectAll("circle").style("stroke", "green");
toChange.selectAll("text").style("stroke", "green");

How to translate svg g elements to cozy up with siblings?

var boxes = [[30, 45], [50, 30], [40, 30]]; // [w, h]
//Should i calculate `translate` value here, adding all heights?
var secs = wrapper.selectAll('g.section')
.data(data)
.enter()
.append('g')
.attr('class', 'section')
.attr("transform", "translate(" + 0 + "," + 'unknown' + ")");
//could be many sub-secs by a lot of data transformation before appending rect to the last one of them.
secs.append('rect')
.datum(function(d){return d;})
.attr('class', 'fragment')
.attr('x', 0)
.attr('y', 0)
.attr('width', function(d){return d[0];})
.attr('height', function(d){return d[1];})
// or here, not from data but from elem's dimensions?
secs.each(function(sec, i){
var prev = this.previousSibling?this.previousSibling.getBBox():'';
var ty = prev?prev.height+ prev.y:0;
d3.select(this).attr("transform", "translate(" + 0 + "," + ty + ")");
});
Is this how you translate g elements to fit their childrens, at any level of depth?
And i'll have to translate them manually when child expands?
i'm new at svg and d3.
Thank you.
It looks like you would need to keep track of the sum of heights and translate by that. That is, for each rectangle that you add add its height to a total which you can then use to offset subsequent elements.

Resources