How to avoid text overlapping in odoo 10 nvd3 pie chart - odoo

I am using odoo 10. When I go to tree view then charts then click on pie chart icon. Pie Labels are overlapping at some points. I tried to some work around in /web/static/nvd3/nv.d3.js file but it is either giving me errors or n effect. Could anyone help me how to achieve this without text overlapping on piechart?
/*
Overlapping pie labels are not good. What this attempts to do is, prevent overlapping.
Each label location is hashed, and if a hash collision occurs, we assume an overlap.
Adjust the label's y-position to remove the overlap.
*/
var center = labelsArc[i].centroid(d);
var percent = getSlicePercentage(d);
if (d.value && percent >= labelThreshold) {
var hashKey = createHashKey(center);
if (labelLocationHash[hashKey]) {
center[1] -= avgHeight;
}
labelLocationHash[createHashKey(center)] = true;
}
return 'translate(' + center + ').rotateLabels(-45)'
}
Above code giving me all text labels centered in piechart middle/centre overlapped on each other. if I remove .rotateLabels(-45) then labels are outside the pie circle but some text overlapping on each other. Thanks in advance!

This worked for me. Do not apply rotateLabels(-45) as I have applied in the question. set ShowLabels=true and labelSunbeamLayout=true as shown below in nv.d3.js file.
//============================================================
// Public Variables with Default Settings
//------------------------------------------------------------
var margin = {top: 0, right: 0, bottom: 0, left: 0}
, width = 500
, height = 500
, getX = function(d) { return d.x }
, getY = function(d) { return d.y }
, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
, container = null
, color = nv.utils.defaultColor()
, valueFormat = d3.format(',.2f')
, showLabels = true
, labelsOutside = true
, labelType = "key"
, labelThreshold = .02 //if slice percentage is under this, don't show label
, donut = false
, title = false
, growOnHover = true
, titleOffset = 0
, labelSunbeamLayout = true
, startAngle = false
, padAngle = false
, endAngle = false
, cornerRadius = 0
, donutRatio = 0.5
, arcsRadius = []
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
;

Related

how to use mpandroidchart to draw a barchart with intervals

The y-axis of the official case starts from 0
I hope to realize the image function through mpandroidchart
You can accomplish this using a stacked bar chart and setting the color of the bottom bar to transparent.
For example:
// Make some fake data - the first array will be the offset,
// with a transparent color. The second is the height of the bar
val offset = listOf(42f, 55f, 55f, 80f, 55f, 110f)
val amount = listOf(50f, 50f, 50f, 50f, 50f, 55f)
val entries = offset.zip(amount).mapIndexed { i, oa ->
BarEntry(i.toFloat(), listOf(oa.first, oa.second).toFloatArray())
}
// To make the bars different colors, make multiple BarDataSets
// instead of just one
val barDataSet = BarDataSet(entries,"data")
barDataSet.colors = listOf(Color.TRANSPARENT, Color.CYAN)
barDataSet.setDrawValues(false)
barChart.setTouchEnabled(false)
barChart.description.isEnabled = false
barChart.legend.isEnabled = false
val yAxis = barChart.axisLeft
yAxis.isEnabled = true
yAxis.axisMinimum = 40f
yAxis.axisMaximum = 160f
yAxis.granularity = 20f
yAxis.textSize = 24f
yAxis.setLabelCount(6, true)
yAxis.setDrawAxisLine(false)
yAxis.gridLineWidth = 1f
yAxis.setDrawGridLines(true)
barChart.axisRight.isEnabled = false
barChart.xAxis.isEnabled = false
barChart.data = BarData(barDataSet)
The result:

Remove space between name and percentage in pie chart legend (amcharts4)

I want to get rid of that space in the legend between the name and the percentage. In the pic, I have highlighted the space in yellow.
For example, I want the first legend item to be "Lithuania (30.5%)". That extra space between "Lithuania" and "30.5%" spoils my UI.
My code for the legend is the following:
// Add and configure Series
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
pieSeries.ticks.template.disabled = true;
pieSeries.labels.template.disabled = true;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
pieSeries.legendSettings.labelText = '{category}';
pieSeries.legendSettings.valueText = null;
pieSeries.labels.template.text = "{category}: {value}";
pieSeries.slices.template.tooltipText = "{category}: {value}";
chart.legend = new am4charts.Legend();
chart.legend.fontSize = 5;
chart.legend.markers.template.width = 5;
chart.legend.markers.template.height = 5;
What change must I make in order to get this done?
You can move the value to the "labelText":
pieSeries.legendSettings.labelText = "{category}: {value.percent.formatNumber('#.0')}%";
And disable value labels altogether:
chart.legend.valueLabels.template.disabled = true;

Corona SQL pass row ID in tableView to new Scene

I've found a similair question to my problem and so far its working for me, Im getting the row ID printed with a print statement.
I am displaying data from my Database in a tableView. With the onTouch function I want the data showed in a new Scene in a scrollView that gets that data specifically to that clicked row. So for example I am clikcing on the tableView on Capital_NL, it has to show Amsterdam in the scrollView (Scene 2).
This is my code so far:
Scene 1:
local count = 0
local baslikRow = {}
for row in db:nrows("SELECT dua_id, baslik FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
end
local function tableViewListener( event )
print(event.phase)
end
local function onRowRender( event )
local row = event.row
local rowHeight = row.contentHeight
local rowWidth = row.contentWidth
local options =
{
parent = row,
text = baslikRow[row.index].baslik,
x = 20,
y = 0,
font = native.systemFont,
fontSize = 16
}
local rowTitle = display.newText(options)
rowTitle:setFillColor( 0, 0, 0 )
rowTitle.anchorX = 0
rowTitle.x = 15
rowTitle.y = rowHeight * 0.5
end
local function onRowTouch( event )
local row = event.row
if event.phase == 'tap' then
print("Pressed rowNR: " .. row.index )
print("Pressed rowID: " .. event.target.params.paramID)
composer.gotoScene("scene2")
end
end
local tableView = widget.newTableView{
left = 0,
top = 0,
height = display.contentHeight,
width = display.contentWidth,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
}
for i = 1, count do
tableView:insertRow
{
rowHeight = 50,
rowid = baslikRow[count].dua_id,
params = { paramID = baslikRow[i].dua_id }
}
end
sceneGroup:insert(tableView)
Scene 2:
---------------------
-- CREATE SCROLLVIEW
---------------------
local scrollView = widget.newScrollView
{
left = 0,
top = 0,
width = display.contentWidth,
height = display.contentHeight,
topPadding = 0,
bottomPadding = 0,
horiontalScrollDisabled = true,
verticalScrollDisable = false,
listener = scrollListener,
}
sceneGroup:insert(scrollView)
---------------------
-- GET DATA FROM DB
---------------------
for row in db:nrows("SELECT metni FROM dua") do
local rowParams =
{
duaID = row.dua_id,
Metni = row.metni,
}
local options =
{
text = row.metni,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 18,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
end
What I have right now is, whenever I click on, for example Capital_NL or Capital_USA or Capital_Germany, I always get the result Amsterdam back.
How do I pass the data thats in the same Row in the database from Scene 1 to Scene 2
I think you want to display the (metni) data based on the row number tapped on the previuos scene ..
Try this inside scene1 ..
for row in db:nrows("SELECT dua_id, baslik, metni FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
baslikRow[count].metni = row.metni
inside the onRowTouch event handler:
composer.gotoScene("scene2",{params = baslikRow[row.index].metni})
This way you can pass the data you want to use .. I guess you don't need to use the database code inside scene2 ..
to access the data passed from scene1 to scene2
local selectedRow = event.params
Then ..
local options =
{
text = selectedRow,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 50,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
I think thats what you asked for .. If NOT, please explain more and give us a screenshot of your "dua" table ..

Dimple Stacked Bar Chart - adding label for aggregate total

I'm trying to add a label to the aggregate total for a stacked bar chart above each bar. I used this example (http://dimplejs.org/advanced_examples_viewer.html?id=advanced_bar_labels) to add the totals for each section of the bar, but I'm not sure how to add the total above. I've also been able to add total labels above each bar for a single series (not stacked). I just can't get it to work with a stacked bar chart.
My current workaround is plotting an additional null series line, but making the line and markers transparent so you can still see the total value in the tooltip. However, I'd really like to just have the totals displayed above each bar.
Here's the code:
var svg = dimple.newSvg("#chartContainer", 590, 400);
var myChart = new dimple.chart(svg, data);
myChart.setBounds(80, 30, 510, 305);
var x = myChart.addCategoryAxis("x", "Month");
x.addOrderRule(Date);
var y = myChart.addMeasureAxis("y", "Calls");
y.showGridlines = true;
y.tickFormat = ',6g';
y.overrideMin = 0;
y.overrideMax = 800000;
var s = myChart.addSeries("Metric", dimple.plot.bar);
s.afterDraw = function (shape, data) {
var s = d3.select(shape),
rect = {
x: parseFloat(s.attr("x")),
y: parseFloat(s.attr("y")),
width: parseFloat(s.attr("width")),
height: parseFloat(s.attr("height"))
};
if (rect.height >= 1) {
svg.append("text")
.attr("x", rect.x + rect.width / 2)
.attr("y", rect.y + rect.height / 2 + 3.5)
.style("text-anchor", "middle")
.style("font-size", "9px")
.style("font-family", "sans-serif")
.style("opacity", 0.8)
.text(d3.format(",.1f")(data.yValue / 1000) + "k");
}
};
myChart.addLegend(60, 10, 510, 20, "right");
myChart.draw();
Here is the JSFiddle: http://jsfiddle.net/timothymartin76/fusaqyhk/16/
I appreciate any assistance on this.
Thanks!
You can add them after drawing by calculating the bar totals and deriving the y position from that:
// Iterate every value on the x axis
x.shapes.selectAll("text").each(function (d) {
// There is a dummy empty string value on the end which we want to ignore
if (d && d.length) {
// Get the total y value
var total = d3.sum(data, function (t) { return (t.Month === d ? t.Calls : 0); });
// Add the text for the label
var label = svg.append("text");
// Set the x position
// x._scale(d) is the tick position of each element
// (myChart._widthPixels() / x._max) / 2 is half of the space allocated to each element
label.attr("x", x._scale(d) + (myChart._widthPixels() / x._max) / 2)
// Vertically center the text on the point
label.attr("dy", "0.35em")
// Style the text - this can be better done with label.attr("class", "my-label-class")
label.style("text-anchor", "middle")
.style("font-size", "9px")
.style("font-family", "sans-serif")
.style("opacity", 0.8)
// Set the text itself in thousands
label.text(d3.format(",.1f")(total / 1000) + "k");
// Once the style and the text is set we can set the y position
// y._scale(total) gives the y position of the total (and therefore the top of the top segment)
// label.node().getBBox().height gives the height of the text to leave a gap above the bar
label.attr("y", y._scale(total) - label.node().getBBox().height)
}
});
Here is your updated fiddle: http://jsfiddle.net/fusaqyhk/17/

issue with different type of axes for storyboard example of dimplejs

I'm trying to create a storyboard very similar to the one in dimpleJS examples. My data looks like below.
[{"Date":"2014-05-05T19:03:23Z","Liters":0.23,"Soda":"Coke","Day":"2014-05-05","Time of Day":"15:03","Day-Time":"2014-05-05 15:03"},{"Date":"2014-05-05T19:37:27Z","Liters":0.35,"Soda":"Coke","Day":"2014-05-05","Time of Day":"15:37","Day-Time":"2014-05-05 15:37"},{"Date":"2014-05-05T20:33:33Z","Liters":0.21,"Soda":"Coke","Day":"2014-05-05","Time of Day":"16:33","Day-Time":"2014-05-05 16:33"},{"Date":"2014-05-05T21:11:37Z","Liters":0.21,"Soda":"Coke","Day":"2014-05-05","Time of Day":"17:11","Day-Time":"2014-05-05 17:11"},{"Date":"2014-05-06T13:55:09Z","Liters":0.22,"Soda":"Coke","Day":"2014-05-06","Time of Day":"9:55","Day-Time":"2014-05-06 9:55"},{"Date":"2014-05-06T14:27:13Z","Liters":0.27,"Soda":"Coke","Day":"2014-05-06","Time of Day":"10:27","Day-Time":"2014-05-06 10:27"},{"Date":"2014-05-06T15:42:21Z","Liters":0.14,"Soda":"Coke","Day":"2014-05-06","Time of Day":"11:42","Day-Time":"2014-05-06 11:42"},{"Date":"2014-05-06T16:16:24Z","Liters":0.24,"Soda":"Coke","Day":"2014-05-06","Time of Day":"12:16","Day-Time":"2014-05-06 12:16"},{"Date":"2014-05-05T19:13:24Z","Liters":0.59,"Soda":"Diet Coke","Day":"2014-05-05","Time of Day":"15:13","Day-Time":"2014-05-05 15:13"},{"Date":"2014-05-05T20:33:33Z","Liters":0.01,"Soda":"Diet Coke","Day":"2014-05-05","Time of Day":"16:33","Day-Time":"2014-05-05 16:33"},{"Date":"2014-05-05T21:04:36Z","Liters":0.39,"Soda":"Diet Coke","Day":"2014-05-05","Time of Day":"17:04","Day-Time":"2014-05-05 17:04"},{"Date":"2014-05-05T21:11:37Z","Liters":0.21,"Soda":"Diet Coke","Day":"2014-05-05","Time of Day":"17:11","Day-Time":"2014-05-05 17:11"},{"Date":"2014-05-05T21:57:42Z","Liters":0.17,"Soda":"Diet Coke","Day":"2014-05-05","Time of Day":"17:57"},{"Date":"2014-05-06T11:11:53Z","Liters":0.42,"Soda":"Diet Coke"},{"Date":"2014-05-06T12:54:03Z","Liters":0.49,"Soda":"Diet Coke"},{"Date":"2014-05-06T12:55:03Z","Liters":0.48,"Soda":"Diet Coke"},{"Date":"2014-05-06T13:07:04Z","Liters":0.27,"Soda":"Diet Coke"},{"Date":"2014-05-06T13:34:07Z","Liters":0.41,"Soda":"Diet Coke"},{"Date":"2014-05-06T13:55:09Z","Liters":0.19,"Soda":"Diet Coke"},{"Date":"2014-05-06T14:27:13Z","Liters":0.01,"Soda":"Diet Coke"},{"Date":"2014-05-06T15:42:21Z","Liters":0.02,"Soda":"Diet Coke"},{"Date":"2014-05-06T16:01:23Z","Liters":0.45,"Soda":"Diet Coke"},{"Date":"2014-05-06T16:05:23Z","Liters":0.52,"Soda":"Diet Coke"},{"Date":"2014-05-06T16:35:27Z","Liters":0.65,"Soda":"Diet Coke"},{"Date":"2014-05-06T16:49:28Z","Liters":0.4,"Soda":"Diet Coke"},{"Date":"2014-05-06T16:50:29Z","Liters":0.14,"Soda":"Diet Coke"},{"Date":"2014-05-05T18:10:18Z","Liters":0.24,"Soda":"Powerade"},{"Date":"2014-05-05T19:03:23Z","Liters":0.01,"Soda":"Powerade"},{"Date":"2014-05-05T19:37:27Z","Liters":0.01,"Soda":"Powerade"},{"Date":"2014-05-05T20:39:34Z","Liters":0.39,"Soda":"Powerade"},{"Date":"2014-05-05T21:04:36Z","Liters":0.01,"Soda":"Powerade"},{"Date":"2014-05-06T10:32:49Z","Liters":0.18,"Soda":"Powerade"},{"Date":"2014-05-06T11:11:53Z","Liters":0.01,"Soda":"Powerade"},{"Date":"2014-05-06T12:54:03Z","Liters":0.01,"Soda":"Powerade"},{"Date":"2014-05-06T14:27:13Z","Liters":0.02,"Soda":"Powerade"},{"Date":"2014-05-06T15:42:21Z","Liters":0.02,"Soda":"Powerade"},{"Date":"2014-05-06T16:01:23Z","Liters":0.03,"Soda":"Powerade"},{"Date":"2014-05-06T16:05:23Z","Liters":0.03,"Soda":"Powerade"},{"Date":"2014-05-06T16:23:25Z","Liters":0.12,"Soda":"Powerade"},{"Date":"2014-05-06T16:50:29Z","Liters":0.01,"Soda":"Powerade"}]
I've category and time axes. The problem is that the bubbles do not show up at the correct y(time) axis. My code looks like below and it also shows too many 0 values although there is no 0 value in dataset.
var series, charts, lastDate = null, sodas = dimple.getUniqueValues(data, "Soda");
charts = [new dimple.chart(svg, null)],
charts.push(myChart);
charts.forEach(function (chart, i) {
var x, y, z;
chart.setBounds(this.attributes.left, this.attributes.top, this.attributes.width - 225, this.attributes.height - 225);
x = chart.addCategoryAxis("x", "Soda");
x.overrideMax = 3;
x.hidden = (i === 0);
y = chart.addTimeAxis("y", "Day-Time", "%Y-%m-%d %H:%M", "%d-%m %H:%M");
// y.overrideMax = "17:00";
y.hidden = (i === 0);
z = chart.addMeasureAxis("z", "Liters");
z.overrideMax = 1;
// Ensure the same colors for every owner in both charts
// differing by opacity
sodas.forEach(function (soda, k) {
chart.assignColor(
soda,
charts[0].defaultColors[k].fill,
"white",
(i === 0 ? 0.3 : 1));
}, this);
}, this);
charts[1].addLegend(850, 100, 60, 300, "Right");
charts[1].setStoryboard("Time of Day", function (d) {
// Use the last date variable to manage the previous tick's data
if (lastDate !== null) {
// Pull the previous data
var lastData = dimple.filterData(data, "Time of Day", lastDate);
// Add a series to the background chart to display old position
var lastSeries = charts[0].addSeries("Soda", dimple.plot.bubble);
// Average suits these measures better
lastSeries.aggregate = dimple.aggregateMethod.avg;
// Give each series its own data at different periods
lastSeries.data = lastData;
// Draw the background chart
charts[0].draw();
// Class all shapes as .historic
lastSeries.shapes.attr("class", "historic");
// Reduce all opacity and remove once opacity drops below 5%
d3.selectAll(".historic").each(function () {
var shape = d3.select(this),
opacity = shape.style("opacity") - 0.02;
// shape.style("opacity", opacity);
if (opacity < 0.1) {
shape.remove();
} else {
shape.style("opacity", opacity);
}
});
}
lastDate = d;
});
series = charts[1].addSeries("Soda", dimple.plot.bubble)
series.aggregate = dimple.aggregateMethod.avg;
// Draw the main chart
charts[1].draw();
Here is the screenshot.
Thanks for adding the fiddles. If you remove the x.hidden = (i === 0); and y.hidden = (i === 0); lines (so that the back chart's axes are displayed) you can see the issue. Unlike measure axes where you can fix the max and min to make sure that the charts are identically proportioned, category axes will only draw for the elements in the data, so a frame with a single category will only draw a single point in the centre of the axis. Also the ordering will change by default.
To get your case working you need to fix ordering for the x axis.
x.addOrderRule(["Coke", "Diet Coke", "Powerade"]);
Define a max and min value for the y axis:
y.overrideMin = d3.time.format("%Y-%m-%d").parse("2014-05-05");
y.overrideMax = d3.time.format("%Y-%m-%d").parse("2014-05-07");
And stick some dummy rows in for any missing categories.
lastData = lastData.concat([
{
"Date": "2014-05-06T00:00:00Z",
"Liters": 0,
"Soda": "Coke"
},
{
"Date": "2014-05-06T00:00:00Z",
"Liters": 0,
"Soda": "Diet Coke"
},
{
"Date": "2014-05-06T00:00:00Z",
"Liters": 0,
"Soda": "Powerade"
}
]);
This results in this output: http://jsfiddle.net/4qBqJ/9/