Is it possible to draw lines, circles and other shapes with pdfmake? If yes, is there a documentation or are there any samples? I would like to replace jsPDF with pdfmake.
Yes, its possible. pdfmake calls them vectors. See
pdfMake Vector examples for more possibilities.
An example for drawing a line followed by a polygon:
{
canvas:
[
{
type: 'line',
x1: 40, y1: 60,
x2: 260, y2: 60,
lineWidth: 3
},
{
type: 'polyline',
lineWidth: 3,
closePath: true,
points: [{ x: 10, y: 10}, { x: 35, y: 40 }, { x: 100, y: 40 }, { x: 125, y:10 }]
}
]
}
I answered an issue in pdfMake at GitHub like this:
Create a table with layout headeronly you must define an empty body, otherwise the line would not appear:
var dd = {
content: [
{
table : {
headerRows : 1,
widths: [200],
body : [
[''],
['']
]
},
layout : 'headerLineOnly'
}
] }
The width defines the length of the line
canvas: [
{
type: 'rect',
x: 198,
y: -186,
w: 198,
h: 188,
r: 8,
lineWidth: 4,
lineColor: '#276fb8',
},
]
As far as I know, pdfmake does not provide an drawing API. Despite this, pdfmake provides you some methods to insert images at your pdf.
Best regards!
Related
I'm exploring Highcharts and it seems like a very comprehensive package! I have a question regarding legend colors.
I notice that when I use a linear color gradient for a line, the color next to the legend (I believe it's called the symbolColor) may or may not show up, depending on the format I use:
1) symbolColor works fine: linearGradient: [ 00, 00, 00, 350 ]
2) symbolColor doesn't show up: linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }
I'd rather use the second format; it's easier and the first is not responsive.
Should the symbolColor always show up and this is an obscure issue/bug? Or am I doing something wrong? I also just noticed that if the marker is enabled in the plotOptions for series, symbolColor works fine with the second format. But I have many data points and don't want to use markers.
The fiddle graph has two lines -- purple and green -- and while the purple symbolColor using method (1) looks fine, you'll notice that the green symbolColor using method (2) doesn't show up.
https://jsfiddle.net/jwinkle/s6d9ah17/6/
In your HTML file, add:
<script src="https://code.highcharts.com/maps/modules/map.src.js"></script>
Above your chart code add:
Highcharts.addEvent(Highcharts.Chart.prototype, 'render', function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
});
The fix is in adding a smidge to your path definition (you can test this by going into the svg path element in dev tools and changing the last number in the 'd' attribute to a float:
<path fill="none" d="M 0 11 L 16 11" ... ></path>
becomes:
<path fill="none" d="M 0 11 L 16 11.1" ... ></path>
The function above goes through each series and massages the line data adding the fractional value in the right place. Total hack. However why the line does not appear if it does have this fractional value, I don't know. I would also test this across browsers to see that it works consistently as it may not (I tested in Chrome).
Here is a somewhat related issue where I cribbed the fix: https://www.highcharts.com/forum/viewtopic.php?t=38588
(Most of it is addressing a completely different problem, but the legend lines did show up so I investigated why).
If you don't want to use the extra library, you could probably write a native js function to find the legend lines and manipulate them in the same way.
Here, you can find a nice explanation of the problem.
The difference results from the fact that Highcharts uses 'userSpaceOnUse' as a default value for gradientUnits if a gradient is defined as an array.
Highcharts source code:
// Keep < 2.2 kompatibility
if (isArray(gradAttr)) {
(colorOptions as any)[gradName] = gradAttr = {
x1: gradAttr[0] as number,
y1: gradAttr[1] as number,
x2: gradAttr[2] as number,
y2: gradAttr[3] as number,
gradientUnits: 'userSpaceOnUse'
};
}
As a possible solution, you can set gradientUnits also for linearGradient defined as an object:
color: {
linearGradient: {
...,
gradientUnits: 'userSpaceOnUse'
},
...
}
Live demo: http://jsfiddle.net/BlackLabel/yz6sagxj/
Or modify the paths very slightly so that they are not perfectly horizontal
chart: {
events: {
render: function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/L1kzg0cn/
Github thread: https://github.com/highcharts/highcharts/issues/1936
In addition to #Katharine's solution, here's another I discovered.
If I enable the marker in one series (setting the radius to 0) and then put the data in a second series which is linked to the previous, it works. (If I do it all in one series, there is again no legend color.)
series: [{
name: 'purple', lineWidth: 3, color: {
linearGradient: [ 00, 00, 00, 350 ],
//linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'purple'], // start
[1, 'black'] // end
],
},
data: [ 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, 40, ],
},{
marker: {
enabled: true,
radius: 0,
},
name: 'green', color: 'green', lineWidth: 3,
},{
linkedTo: ':previous',
lineWidth: 3, color: {
//linearGradient: [ 00, 00, 00, 350 ],
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'green'], // start
[1, 'black'] // end
],
},
data: [ 100, 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, ],
}],
Here's the "fixed" fiddle: https://jsfiddle.net/jwinkle/wztq78n1/6/
I reported the original issue as a possible bug to Highcharts, and they confirmed that it's an SVG rendering problem out of their control.
New to dart, with origin from python. One thing I cannot find native support for is to be able to group an Iterable by a defined key. In python there is a very nice support from the itertools package (https://docs.python.org/3.8/library/itertools.html#itertools.groupby). What I want to achieve can be described in pseudo code.
a = [
{
x: 1,
y: 1,
},
{
x: 1,
y: 2,
},
{
x: 2,
y: 3,
},
{
x: 2,
y: 4,
}
]
for group, items in groupby(a, key: item['x']):
print('$group : $items')
Expected output:
1 : {x:1, y: 1}, {x:1, y:2}
2 : {x:2, y: 3}, {x:2, y:4}
KonvaJS is a excellent canvas plugin,it's easy to use ,a lot of demos,and detailed api document.
But i have a problem about Konva.Text, When I want to display fraction number like "7/8",it's show as a plain text <sup>7</sup>/<sub>8</sub> , how can i do?
As far as I know fabric has analogous method called setSuperscript and setSubscript, can our Konva.Text be achieved?
I suggest to draw it manually with three shapes:
function createFraction(sup, sub) {
const group = new Konva.Group();
group.add(new Konva.Text({
align: 'right',
width: 100,
x: -100,
text: sup
}));
group.add(new Konva.Text({
text: sub,
y: 13,
x: 2
}));
group.add(new Konva.Line({
stroke: 'black',
strokeWidth: 1,
points: [5, 4, -5, 20],
text: sub,
}));
return group;
}
const fraction = createFraction('7', '8');
fraction.position({ x: 50, y: 50});
layer.add(fraction);
https://jsbin.com/vahavimowa/edit?html,js,output
Looking at this example: http://www.highcharts.com/stock/demo/candlestick-and-volume
Is there a way that I can lay these two series side-by-side rather than stacked on top?
You can use axis.width and axis.left. You will not find them in axis official API, so you may encounter some issues with it, e.g. problem with a tooltip - issue on github.
The basic config for using two x axis next to each other:
xAxis: [{
width: 200,
left: 50
}, {
width: 200,
left: 300,
linkedTo: 0,
offset: 0
}],
Workaround for a tooltip position (shared tooltip does not seem to work correctly)
tooltip: {
shared: false,
shape: 'rect',
positioner: function(w, h, p) {
return {
x: p.plotX + this.chart.hoverSeries.xAxis.left - w / 2,
y: p.plotY
}
}
},
example: http://jsfiddle.net/fqc5np5g/
As shown in the picture (which is not the same code as the fiddle, but exhibits the problem), with Highcharts new bubble charts it seems like dataLabels like to sit on top of each other. Is there an easy workaround for this? I'd be happy to manually change the z-index on a per label basis, but this doesn't seem to work for bubble charts. Here's some sample code that fails to work as expected (try it in a fiddle):
series: [{
data: [{
x: 99,
y: 36,
z: 50
}, {
x: 99,
y: 74,
z: 55,
dataLabels: {
zIndex:15,
enabled: true,
}
}, {
x: 99,
y: 76,
z: 55,
dataLabels: {
zIndex: 1,
enabled: true
}
}
]
}],
You can set useHTML: true flag, and then set z-index: x property for dataLabels, see: http://jsfiddle.net/ZLmU8/4/
Apparently there is a labelrank property on the Highcharts point objects that can be used to dictate which point labels are on top. It can be used when you're creating your data like this:
data: [{
x: 1, y: 1, labelrank: 1, name: 'A'
},{
x: 1, y: 1, labelrank: 2, name: 'B'
}]
Or it can be updated on an individual point to bring that point's dataLabel to the front by doing something like this: chart.series[0].points[0].update({labelrank: 3});
I had a similar issue and created this question on SO that just was answered.
Edit
They have added info regarding series.data.labelrank to their docs as well: http://api.highcharts.com/highcharts#series.data.labelrank