JSPDF : Genearte pdf from object of array and display like Lables - jspdf

I want to generate PDF from object of array and display like this which I have attached in image. .how I can achieve this while my output is in row wise.
htmlStr += '<table id="customers" class="table-wide">';
htmlStr += '<thead ></thead>';
htmlStr += '<tbody ></tbodyid>';
htmlStr += '</table>';
this.html = $(htmlStr);

I think you have to do it on your own. jsPDF-Autotable is not good option for this scenario. Following is something like a scratch it's not a perfect solution. Please work on it further.
Actually we are going to create grid cards until the page width and height.
If height reaches, add new page doc.addPage().
If width reaches, add new row.
var data = [{
"Name": "Ronan",
"Email": "sodales.elit#eratSed.co.uk",
"Company": "Malesuada Malesuada Ltd"
}, {
"Name": "Calvin",
"Email": "amet.nulla#Vestibulumante.ca",
"Company": "Donec Egestas Foundation"
}, {
"Name": "Kane",
"Email": "Duis.mi#consectetueradipiscingelit.net",
"Company": "Arcu Institute"
}, {
"Name": "Kasper",
"Email": "magna.Phasellus.dolor#velconvallisin.co.uk",
"Company": "Tempor LLP"
}];
var doc = new jsPDF('p', 'pt', 'a4');
//Dimension of A4 in pts: 595 × 842
var pageWidth = 595;
var pageHeight = 842;
var pageMargin = 20;
pageWidth -= pageMargin * 2;
pageHeight -= pageMargin * 2;
var cellPadding = 10;
var cellWidth = 180;
var cellHeight = 70;
var lineHeight = 20;
var startX = pageMargin;
var startY = pageMargin;
doc.setFontSize(12);
var page = 1;
function createCard(item) {
//cell projection
var requiredWidth = startX + cellWidth + (cellPadding * 2);
var requiredHeight = startY + cellHeight + (cellPadding * 2);
if (requiredWidth <= pageWidth) {
textWriter(item, startX + cellPadding, startY + cellPadding);
startX = requiredWidth;
// startY += cellHeight + cellPadding;
} else {
if (requiredHeight > pageHeight) {
doc.addPage();
page++;
doc.setPage(page);
startY = pageMargin;
} else {
startY = requiredHeight;
}
startX = pageMargin;
textWriter(item, startX + cellPadding, startY + cellPadding);
startX = startX + cellWidth + (cellPadding * 2);
}
}
function textWriter(item, xAxis, yAxis) {
doc.text(item.Name, xAxis, yAxis);
doc.text(item.Email, xAxis, yAxis + lineHeight);
doc.text(item.Company, xAxis, yAxis + (lineHeight * 2));
}
for (var i = 0; i < data.length; i++) {
createCard(data[i]);
}
doc.save('grid.pdf');
For reference https://jsfiddle.net/Purushoth/jodfkz59/

Related

Zooming in on a UI element causes it to become unsharp/pixelated on iOS

I am using Xamarin.Forms.
On iOS, when using the pinch gesture below to zoom in on a Label (for example), the Label turns pixelated instead of updating and staying sharp.
On Android, this doesn't happen and the Label stays sharp and visible, no matter how much I zoom in on it.
Is there a way to make behave on iOS as it does with Android?
Edit: this behaviour can also be observed simply by raising the scale of a visual element, on Android it looks good but on iOS it turns pixelated. I assume my problem lies here but I'm not sure how to tackle it yet.
The pinch gesture implementation I use to zoom in with:
public class ZoomWithPinch : ContentView
{
public ZoomWithPinch()
{
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
}
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
Content.TranslationX = Math.Min(0, Math.Max(targetX, -Content.Width * (currentScale - 1)));
Content.TranslationY = Math.Min(0, Math.Max(targetY, -Content.Height * (currentScale - 1)));
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
public void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (Content.Scale == 1)
{
return;
}
switch (e.StatusType)
{
case GestureStatus.Running:
double newX = (e.TotalX * Scale) + xOffset;
double newY = (e.TotalY * Scale) + yOffset;
double width = (Content.Width * Content.Scale);
double height = (Content.Height * Content.Scale);
bool canMoveX = width > Application.Current.MainPage.Width;
bool canMoveY = height > Application.Current.MainPage.Height;
if (canMoveX)
{
double minX = (width - (Application.Current.MainPage.Width / 2)) * -1;
double maxX = Math.Min(Application.Current.MainPage.Width / 2, width / 2);
if (newX < minX)
{
newX = minX;
}
if (newX > maxX)
{
newX = maxX;
}
}
else
{
newX = 0;
}
if (canMoveY)
{
double minY = (height - (Application.Current.MainPage.Height / 2)) * -1;
double maxY = Math.Min(Application.Current.MainPage.Width / 2, height / 2);
if (newY < minY)
{
newY = minY;
}
if (newY > maxY)
{
newY = maxY;
}
}
else
{
newY = 0;
}
Content.TranslationX = newX;
Content.TranslationY = newY;
break;
case GestureStatus.Completed:
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
break;
}
}
}
<ZoomWithPinch>
<Grid>
<Label Text="Test" HorizontalOptions="Center" VerticalOptions="Center"/>
</Grid>
</ZoomWithPinch>

How do I layout elements in a circle without rotating the element?

Currently, I'm using offset and rotation to position elements in KonvaJS in a circle. Is there another method that would still layout the elements in a circle without rotating the text (eg like a clock.)
Output looks like this:
Code looks like this:
function drawNumber(radius, number, step) {
var segmentDegree = 360/16
var rotation = -90 + step * segmentDegree
var label = new Konva.Text({
x: patternOriginX,
y: patternOriginY,
text: number.toString(),
fontSize: 12,
fill: '#636363',
rotation: rotation
});
label.offsetX(-radius)
return label
}
You can use trigonometry to find the position of the text on its angle:
var centerX = stage.width() / 2;
var centerY = stage.height() / 2;
var QUANTITY = 10;
var RADIUS = 50;
var dAlhpa = Math.PI * 2 / QUANTITY;
for (var i = 0; i < QUANTITY; i++) {
var alpha = dAlhpa * i;
var dx = Math.cos(alpha) * RADIUS;
var dy = Math.sin(alpha) * RADIUS;
layer.add(new Konva.Text({
x: centerX + dx,
y: centerY + dy,
text: i.toString()
}))
}
Demo: https://jsbin.com/fizucotaxe/1/edit?html,js,output

Highcharts arc with arrow

I am trying to come up with solution which will help me drawing arrow on the end of arc (drawn by chart.renderer.arc function). I have seen solution like this How to draw arrows on a line-chart with Highcharts? when you have series but in arc I do not have information about points (except last one).
Now I am trying to draw arrow depending on angle but that looks a bit miserable.
What I am trying to achieve:
arc with arrow
Code sample: https://jsfiddle.net/49hL72pw/1/
chart: {
polar: true,
events: {
load: function() {
var chart = this;
var center = [(chart.plotBox.width) / 2, (chart.plotBox.height) / 2];
var ren = chart.renderer;
var angle = 175;
var result = ren.arc(center[0] + chart.plotBox.x, center[1] + chart.plotBox.y, 50, 50, (Math.PI / 180) * (-90), (Math.PI / 180) * angle).attr({
fill: '#FCFFC5',
stroke: 'black',
'stroke-width': 1,
dashStyle: 'dash'
}).add();
var dValues = result.element.attributes.d.value.split(" ");
var kx = +dValues[9];//203.99829144870202;
var ky = +dValues[10];//280.94598600742796;
var leftArrowX = 7;
var leftArrowY = 5;
var rightArrowX = 5;
var rightArrowY = 10;
if(angle <= 270 && angle >= 250) {
leftArrowX = leftArrowX * -1;
leftArrowY = leftArrowY * -1;
rightArrowX = rightArrowX * -1;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 249 && angle >= 230) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 5;
rightArrowX = (rightArrowX * -1) + 3;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 229 && angle >= 210) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 5;
rightArrowX = (rightArrowX * -1) + 7;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 209 && angle >= 200) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 8;
rightArrowX = (rightArrowX * -1) + 7;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 199 && angle >= 190) {
leftArrowX = (leftArrowX * -1) - 2;
leftArrowY = (leftArrowY * -1) + 10;
rightArrowX = (rightArrowX * -1) + 10;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 189 && angle >= 180) {
leftArrowX = (leftArrowX * -1) - 1;
leftArrowY = (leftArrowY * -1) + 14;
rightArrowX = (rightArrowX * -1) + 12;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 179 && angle >= 170) {
leftArrowX = (leftArrowX * -1) + 1;
leftArrowY = (leftArrowY * -1) + 14;
rightArrowX = (rightArrowX * -1) + 12;
rightArrowY = (rightArrowY) + -2;
} else if(angle <= 89 && angle > 20) {
//leftArrowX = leftArrowX * -1;
//leftArrowY = leftArrowY * -1;
//rightArrowX = rightArrowX * -1;
rightArrowY = rightArrowY * -1;
} else if (angle <= 20 && angle >= -90) {
leftArrowX = leftArrowX * -1;
leftArrowY = leftArrowY * -1;
//rightArrowX = rightArrowX * -1;
rightArrowY = rightArrowY * -1;
}
ren.path([
'M', kx, ky,
'L', kx + leftArrowX, ky + leftArrowY,
'M', kx, ky,
'L', kx + rightArrowX, ky + rightArrowY,
'Z'
])
.attr({
'stroke-width': 1,
stroke: 'black'
})
.add();
}
}
}
Thanks Paweł but I managed to solve it myself (drawing basic arrow and then rotating it):
ren.path([
'M', kx, ky,
'L', kx - 6, ky - 6,
'M', kx, ky,
'L', kx - 6, ky + 6,
'Z'
]).attr({
transform: 'rotate(' + angle + ')',
'stroke-width': 1,
stroke: '#2ecafa'
}).css({
'transform-origin': kx + 'px' + ' ' + ky + 'px'
}).add();

Center image doc.addImage jspdf

I am using html2canvas to take screenshot of my page and creating pdf of the images using jspdf. Now, my images are left aligned in the pdf document, I want it to be centered, how can I achieve it?
function pdfmaker() {
var element = $("#timesheet");
document.getElementById("message").style.display = "block";
document.getElementById("logo").style.display = "block";
var firstName = "<?php echo $fname?>";
var lastName = "<?php echo $lname ?>";
var startDate = "<?php echo $startDate?>";
var endDate = "<?php echo $endDate ?>";
html2canvas(element, {
useCORS: true,
onrendered: function(canvas) {
var imgData = canvas.toDataURL("image/png");
var imgWidth = 297; //297
var pageHeight = 297; //297
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
// var doc = new jsPDF('l', 'mm',[1350, 1350]);
var doc = new jsPDF('l', 'mm', [420, 297]); //420,297
var position = 5; //0
margins = {
top: 20,
bottom: 10,
left: 45,
width: 522
};
doc.addImage(imgData, 'PNG', 5, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
while (heightLeft >= 5) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 5, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save(firstName + '_' + lastName + '_Summary_report_' + startDate + '_' + endDate + ".pdf");
}
});
document.getElementById("message").style.display = "none";
document.getElementById("logo").style.display = "none";
}
You need to define inside the addImage() method, using the coordinate parameters, see: http://raw.githack.com/MrRio/jsPDF/master/docs/module-addImage.html
This is the only way you can do it. For this, I suggest you use the following method doc.internal.pageSize.getWidth(); to calculate the excess values ​​about the image width, which will be centered.

Convert Lat Long to X Y having lat/lon of corners of a map image

I've map image (1816 x 8160) having following lat/lon of corners.
TopLeft: (-73.9308,40.8883)
TopRight: (-73.8584,40.858)
BottomLeft: (-74.0665,40.7024)
BottomRight: (-73.9944,40.6718)
Map is not true north and rotated at 28.34, also its UTM Zone 18N (78W to 72W). Here are further details about this map taken from PDF Maps iOS app.
Size (pixels): 1816 x 6160
Pixel Resolution: 3.829 meters
Bounds (pixels): (-1624, -3518) x (7866, 7719)
PROJCS["WGS 84 / UTM zone 18N",
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-75],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],
AXIS["Northing",NORTH],
AUTHORITY["EPSG","32618"]]
How to convert lat/lon to x y and vice versa?
Any help will be much appreciated.
Thanks in advance.
var dot_size = 15;
var longitude_shift = 0; //-28.34; // number of pixels your map's prime meridian is off-center.
var x_pos = 0; //54;
var y_pos = 0; //19;
var map_width = 1380; //1816; //430;
var map_height = 4682; //6160; //332;
var half_dot = Math.floor(dot_size / 2);
// Converts from degrees to radians.
Math.radians = function(degrees) {
return degrees * Math.PI / 180;
};
// Converts from radians to degrees.
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
/* N 40.88839 -73.93071 //-73.9308
E 40.85789 -73.85843 //40.858 -73.8584
W 40.70228 -74.06652 //40.7024 -74.0665
S 40.67185 -73.99437 //40.6718 -73.9944 */
var bottomX = 40.67185;
var bottomY = -73.99437;
var topX = 40.88839; //-73.9308; //-73.9308,40.8883
var topY = -73.93071;
var degreesPerPixelX = (bottomX - topX) / map_width; //0.07225 / map_width;
var degreesPerPixelY = (bottomY - topY) / map_height; //0.18605/ map_height;
// These should roughly box Germany - use the actual values appropriate to your image
var minLat = bottomX;
var minLong = bottomY;
var maxLat = topX;
var maxLong = topY;
// Map image size (in points)
var mapSize = {'width': map_width, 'height': map_height};
// Determine the map scale (points per degree)
var xScale = mapSize.width / (maxLong - minLong);
var yScale = mapSize.height / (maxLat - minLat);
var south = Math.radians(40.67185); //lat 47.2
var north = Math.radians(40.88839); //lat 55.2
var west = Math.radians(-74.06652); //long 5.8
var east = Math.radians(-73.85843); //long 15.2
// Formula for mercator projection y coordinate:
function mercY(lat) { return Math.log(Math.tan(lat/2 + Math.PI/4)); }
// Some constants to relate chosen area to screen coordinates
var ymin = mercY(south);
var ymax = mercY(north);
var xFactor = mapSize.width/(east - west);
var yFactor = mapSize.height/(ymax - ymin);
var mapLonLeft = -74.06652; //9.8;
var mapLonRight = -73.85843; //10.2;
var mapLonDelta = mapLonRight - mapLonLeft;
mapLatBottom = 40.67185; //53.45;
mapLatBottomRadian = mapLatBottom * Math.PI / 180;
function convertGeoToPixel(lat, lon)
{
pX = (lon - mapLonLeft) * (mapSize.width / mapLonDelta);
lat1 = lat * Math.PI / 180;
worldMapWidth = ((mapSize.width / mapLonDelta) * 360) / (2 * Math.PI);
mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomRadian)) / (1 - Math.sin(mapLatBottomRadian))));
pY = mapSize.height - ((worldMapWidth / 2 * Math.log((1 + Math.sin(lat1)) / (1 - Math.sin(lat1)))) - mapOffsetY);
return 'x:'+pX+', y:'+pY;
}
function convertPixelToGeo(tx, ty)
{
/* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI */
var worldMapRadius = mapSize.width / mapLonDelta * 360/(2 * Math.PI);
var mapOffsetY = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian)) ));
var equatorY = mapSize.height + mapOffsetY;
var a = (equatorY-ty)/worldMapRadius;
var lat = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
var long = mapLonLeft+tx/mapSize.width*mapLonDelta;
return 'lat:'+lat+', lng:'+long;
}
function draw_point(x, y) {
dot = '<div style="position:absolute;width:' + dot_size + 'px;height:' + dot_size + 'px;top:' + y + 'px;left:' + x + 'px;background:#00ff00"></div>';
document.body.innerHTML += dot;
}
function plot_point(lat, lng) {
spotLat = lat;
spotLong = lng;
// Mercator projection
// longitude: just scale and shift
x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;
// latitude: using the Mercator projection
lat1 = lat * Math.PI / 180; // convert from degrees to radians
y = Math.log(Math.tan((lat1/2) + (Math.PI/4))); // do the Mercator projection (w/ equator of 2pi units)
y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos; // fit it to our map
x -= x_pos;
y -= y_pos;
// position of map image for point
//var newXY = 'x:' (spotLong - minLong) * xScale + ', y:' + (spotLat - minLat) * yScale +'<br/>';
//var y = (spotLat - minLat) * yScale;
//alert('x: ' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y: ' + kavraY(Math.radians(lat),Math.radians(lng)));
strText = 'kavra x:' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y:' + kavraY(Math.radians(lat),Math.radians(lng)) + '<br/>';
strText += 'x:' + x + ', y:' + y + '<br/>';
strText += 'x:'+(spotLong - minLong) * xScale +', y:' + (spotLat - minLat) * yScale +'<br/>';
strText += 'x:'+((Math.radians(lng) - west)*xFactor)+' ,y:'+((ymax - mercY(Math.radians(lat)))*yFactor)+'<br/>';
strText += convertGeoToPixel(lat,lng)+'<br/>' ;
//floatingDiv = '<div style="position:fixed;top:10px;left:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#leftDiv').html(strText);
draw_point(x - half_dot, y - half_dot);
}
function kavraX (latitude, longitude) // Kavra for Kavrayskiy
// formula from http://en.wikipedia.org/wiki/Kavrayskiy_VII_projection
{
return ((3 * longitude) / 2 * Math.PI)*Math.sqrt(Math.pow(Math.PI, 2)/3 - Math.pow(latitude, 2));
}
function kavraY (latitude, longitude)
{
return latitude*-1;
}
$(document).ready(function() {
//-73.949321, 40.796997
plot_point(40.764296, -73.973027);
$('img').click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLon = topX + relativeX * degreesPerPixelX;
var clickedLat = bottomY + relativeY * degreesPerPixelY;
alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
});
$('#parentDiv').mousemove(function(e) {
var offset = $('img').offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLat = topX + relativeX * degreesPerPixelX;
var clickedLon = topY + relativeY * degreesPerPixelY;
//alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
var strText = relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon+'<br/>';
strText += 'lat:'+(relativeY / yScale + minLat)+', long:'+(relativeX / xScale + minLong)+'<br/>';
strText += convertPixelToGeo(relativeX,relativeY)+'<br/>';
//floatingDiv = '<div style="position:fixed;top:10px;right:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#rightDiv').html(strText);
});
});
/*$(function() {
$("#test").click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
alert(relativeX+':'+relativeY);
$(".position").val("afaf");
});
});*/
function onClick (evt) {
alert(evt.pageX +' '+ evt.pageY);
var x = getEventOffsetFromImageLeft(evt);
var y = getEventOffsetFromImageTop(evt);
var clickedLon = topX + x * degreesPerPixelX;
var clickedLat = bottomY + y * degreesPerPixelY;
}
</script>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<!-- onload="plot_point(40.756, -73.986)" -->
<body >
<div id='parentDiv'>
<!-- image found at http://i.stack.imgur.com/BXgSw.jpg -->
<img src="http://i.stack.imgur.com/BXgSw.jpg" style="position:absolute;top:0px;left:0px" >
<div id="leftDiv" style="position:fixed;top:10px;left:10px;"></div>
<div id="rightDiv" style="position:fixed;top:10px;right:10px;"></div>
</div>
</body>
</html>

Resources