I am trying to implement interactive data visualization using DC,D3 and CrossFilter JS. But I am facing three issue.
Width of the bar in the bar chart
Brush is solid black
X,Y-Axis lines are too thick.
I would like to increase width of the bar and like to have Brush on feature with transparent color.
code:
dateChart.width(750)
.margins({top: 10, right: 50, bottom: 30, left: 40})
.elasticY(true)
.dimension(timeDim)
.group(dates)
.brushOn(true)
.gap(65)
.transitionDuration(500)
.centerBar(true)
// .xUnits(function(){return 10;})
.round(d3.time.day.round)
// .renderlet(colorRenderlet)
.x(d3.time.scale()
.domain([new Date(2016, 0, 1), new Date(2016, 0, 31)])
.rangeRound([0, 1 * 90]))
.renderHorizontalGridLines(true)
.filter([new Date(2016, 0, 1), new Date(2016, 0, 1)])
.xAxis().tickFormat();
//.fluctuationChart.yAxis().ticks(5);
Related
D3JS Is it possible to draw Vertical set of Bubbles based on the size
I am very new to Java script framework especially visualization like D3JS. For basic chart I can get the samples from web. But these kind of manipulated charts, I dont how to create like this one. Please help.
data json:
[{Total: 750, left: 250, rigth: 500},
{Total: 75, left: 25, rigth: 50}
]
Total: Total No of Employee
Left: Total No of Female Employee
Right: Total No of Male Employee
The circles are drawn with the following snippet.
The horizontal lines and numbers are left as an exercise.
var svgWidth = 700, svgHeight = 700;
var svg = d3.select('body').append('svg').attr('width', svgWidth).attr('height', svgHeight);
var data = [
{Total: 750, left: 250, right: 500},
{Total: 75, left: 25, right: 50},
{Total: 1000, left: 750, right: 250},
{Total: 125, left: 25, right: 100}
];
var yScale = d3.scaleBand().domain(d3.range(data.length)).rangeRound([0,svgHeight]);
var radius = d3.scaleLinear().domain([0,1200]).range([10, yScale.bandwidth()*0.5]);
var bars = svg.selectAll('.bar')
.data(data)
.enter()
.append('g')
.attr('class', 'bar')
.attr('transform', (d,i) => `translate(${svgWidth * 0.5},${yScale(i)+yScale.bandwidth()*0.5})`)
;
bars.append('circle')
.attr('r', d => radius(d.Total));
bars.append('text')
.text( d => d.Total)
.attr('text-anchor', 'middle')
.attr('dy', '0.3em');
.bar circle {
fill:none;
stroke:steelblue;
stroke-width: 2;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
I have a fabric ellipse object which is scaled and skewed. I want to recreate the same ellipse with no scaling and skewing. I assume this could be achieved by calculating new values for rx,ry and angle by offseting the scaling and skewing values. I managed to offset the scaling values, but I am not able to figure out the calculations to offset the skew values.
Thanks in advance for any help.
Jsfiddle - https://jsfiddle.net/jwp2yysh/
Please see the sample code. I want the blue ellipse to alligned inline with the red ellipse.
var canvas = new fabric.Canvas('c');
var redEllipse = new fabric.Ellipse({
rx: 80,
ry: 50,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'red',
strokeWidth: 1,
top: 180,
left: 240,
angle: 30,
scaleX: 1.23,
scaleY: 1.4,
skewX: 25,
skewY: 0
});
canvas.add(redEllipse);
var blueEllipse = new fabric.Ellipse({
rx: redEllipse.rx * redEllipse.scaleX,
ry: redEllipse.ry * redEllipse.scaleY,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'blue',
strokeWidth: 1,
top: redEllipse.top,
left: redEllipse.left,
angle: redEllipse.angle * redEllipse.scaleY / redEllipse.scaleX,
scaleX: 1,
scaleY: 1,
skewX: 0,
skewY: 0
});
canvas.add(blueEllipse);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
I assume you are looking for something like this JSFiddle.
var canvas = new fabric.Canvas('c');
var redEllipse = new fabric.Ellipse({
rx: 80,
ry: 50,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'red',
strokeWidth: 1,
top: 180,
left: 240,
angle: 30,
scaleX: 1.23,
scaleY: 1.4,
skewX: 0,
skewY: 0
});
canvas.add(redEllipse);
var blueEllipse = new fabric.Ellipse({
rx: redEllipse.rx * redEllipse.scaleX - 10,
ry: redEllipse.ry * redEllipse.scaleY - 10,
// rx:80*1.23,
//ry:50*1.4,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'blue',
strokeWidth: 1,
top: redEllipse.top,
left: redEllipse.left,
angle: redEllipse.angle,
//angle:30,
scaleX: 1,
scaleY: 1,
skewX: 0,
skewY: 0
});
canvas.add(blueEllipse);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
From what I could understand, your calculation of rx and ry is correct. The problem with calculating the angle using the formula you have mentioned in the code is probably not taking into account the skew-ness of the original ellipse.
A simpler way would be to replicate the angle redEllipse.angle to make the new ellipse inline.
To make it inside the original one, you just need to reduce the rx and ry values by some common factor (I have used 10).
I am new to HTML5 Canvas, and have searched a few top sites and other questions here about this issue I am having. All I am wanting to do create a clear 0 pixel stroke on this custom shape cloud I am practicing with.
But is this possible? With my current codes, my cloud has a mini black outline in Google Chrome.
How do I fix this?
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 0;
context.fillStyle = 'pink';
context.fill();
context.strokeStyle = 'none';
context.stroke();
</script>
I am plotting a dc composite chart with one bar chart and two line charts.I am using the following code:
compositeChart1.width(600)
.height(250)
.margins({top: 10, right: 100, bottom: 70, left:80})
.transitionDuration(800)
.dimension(mvValue)
.elasticY(true)
**.x(d3.scale.ordinal().domain(["AFFILIATES","CSE","DISPLAYADS","EMAIL","MOBILEWEB","ORGANIC","OTHERS","SEM","SEO" ]))**
.xUnits(dc.units.ordinal)
.renderHorizontalGridLines(true)
.title(function(d) { return [d.key+"(TY)" + ":"+ myFormat(d3.round(d.value.avgIndex,2)),
d.key+"(LW)" + ":"+ myFormat(d3.round(d.value.avgIndex2,2)),
d.key+"(LY)"+":"+ myFormat(d3.round(d.value.avgIndex1,2)),
d.key+"(WoW)"+":"+ myFormat(d3.round(((d.value.avgIndex/d.value.avgIndex2 -1)*100),2))+"%",
d.key+"(YoY)"+":"+ myFormat(d3.round(((d.value.avgIndex/d.value.avgIndex1 -1)*100),2))+"%"]
.join("\n") })
.compose([
dc.barChart(compositeChart1)
.width(600)
.height(250)
.group(mvValueGroupSum,"This Year")
.valueAccessor(function (p) {return p.value.avgIndex;})
.barPadding(0.5)
.brushOn(false)
.elasticY(true)
// .x(d3.scale.ordinal().domain(["SEM","SEO", "CSE","AFFILIATES","MOBILEWEB","EMAIL","OTHERS","ORGANIC", "DISPLAYADS"]))
.margins({top: 10, right: 100, bottom: 70, left:80})
.gap(10),
dc.lineChart(compositeChart1)
.width(600)
.height(250)
.group(mvValueGroupSum,"Last Year")
.valueAccessor(function (p) {return p.value.avgIndex1;})
// .x(d3.scale.ordinal().domain(["SEM","OTHERS","SEO", "CSE","ORGANIC","MOBILEWEB", "AFFILIATES","EMAIL", "DISPLAYADS"]))
.margins({top: 10, right: 100, bottom: 70, left:80})
.yAxisLabel($('#metric').val()+'(TY)')
.brushOn(false)
.elasticY(true)
.colors('orange'),
dc.lineChart(compositeChart1)
.width(600)
.height(250)
.group(mvValueGroupSum,"Last Year")
.valueAccessor(function (p) {return p.value.avgIndex2;})
// .x(d3.scale.ordinal().domain(["SEM","OTHERS","SEO", "CSE","ORGANIC","MOBILEWEB", "AFFILIATES","EMAIL", "DISPLAYADS"]))
.margins({top: 10, right: 100, bottom: 70, left:80})
.yAxisLabel($('#metric').val()+'(TY)')
.brushOn(false)
.elasticY(true)
.colors('#663300')
])
.yAxisLabel($('#metric').val()+'(TY)')
.rightYAxisLabel($('#metric').val()+'(LY)')
.renderHorizontalGridLines(true)
.renderlet(function (chart) {
chart.selectAll("g._0").attr("transform", "translate(" + -2 + ", 0)");
chart.selectAll("g._1").attr("transform", "translate(" + 22 + ", 0)");
chart.selectAll("g._2").attr("transform", "translate(" + 22 + ", 0)");
});
compositeChart1.renderlet(function(chart){
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
});
I want to change the order of my chart elements, which I tried doing by changing the order in the line highlighted above, but somehow, only my barchart picks up the order I specify and the line charts, irrespective of the order follow an alphabetical trend which results in the line chart being twisted weirdly.Is there some way, I can fix it or does it have to be alphabetical always?
The vertical alignment of text seems to be different in different browsers when working with KineticJS. I created two JSFiddles that illustrate the problem: In the first, the text is rendered to a raw HTML5 canvas without the use of KineticJS (see Raw HTML5 Example). In this case, the text is aligned the same way in Chrome and FF. Here's the JS-code for raw HTML5 canvas:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
xOrigin = 10;
context.beginPath();
context.rect(xOrigin, 90, 107, 12);
context.fillStyle = 'yellow';
context.fill();
context.lineWidth = 2;
context.strokeStyle = 'black';
context.stroke();
context.font = '11px Calibri';
context.fillStyle = 'black';
context.fillText('Hello World! Calibri', xOrigin + 9, 100);
xOrigin = 141;
context.beginPath();
context.rect(xOrigin, 90, 103, 12);
context.fillStyle = 'cyan';
context.fill();
context.lineWidth = 2;
context.strokeStyle = 'black';
context.stroke();
context.font = '11px Arial';
context.fillStyle = 'black';
context.fillText('Hello World! Arial', xOrigin + 9, 100);
However, when KineticJS is used, the text in Arial is placed one pixel higher in FF than in Chrome (see KineticJS Example). Here's the code for the KineticJS example:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var xOrigin = 10;
var rect = new Kinetic.Rect({
x: xOrigin,
y: 90,
width: 107,
height: 12,
fill: 'yellow',
stroke: 'black',
strokeWidth: 2
});
var simpleText = new Kinetic.Text({
x: xOrigin + 9,
y: 90,
text: 'Hello World! Calibri',
fontSize: 11,
fontFamily: 'Calibri',
fill: 'black'
});
layer.add(rect);
layer.add(simpleText);
xOrigin = 141
var rect = new Kinetic.Rect({
x: xOrigin,
y: 90,
width: 103,
height: 12,
fill: 'cyan',
stroke: 'black',
strokeWidth: 2
});
var simpleText = new Kinetic.Text({
x: xOrigin + 9,
y: 90,
text: 'Hello World! Arial',
fontSize: 11,
fontFamily: 'Arial',
fill: 'black'
});
layer.add(rect);
layer.add(simpleText);
stage.add(layer);
Is there a way to render text consistently across FF and Chrome with KineticJS? Unfortunately, there seems to be no text-baseline property in KineticJS (see here). And why is it rendered correctly when working on the raw HTML5 canvas? Is this a KineticJS bug or did I miss something?