What is the css height of the image if the width is for example: 3px?
original image height is 400px;
original image width is 800px;
what I've tried is:
convert the 3px to a percentage of the original image width:
function perwVal(v){
return 100 * v / iow; //img orig width
}
function perhVal(v){
return v / 100 * ioh; // img original height
}
var imgwidthPerc = perwVal(3);
var imgheightPerc = perhVal(imgwidthPerc);
// not correct the height is off
any help will be appreciated.
You get the ratio of the width vs. height:
const ratio = originalWidth / originalHeight;
and then to find the width for a different height:
const newWidth = newHeight * ratio;
In your example:
const originalHeight = 800;
const originalWidth = 400;
const ratio = originalWidth / originalHeight;
const newHeight = 3;
const newWidth = newHeight * ratio;
console.log(newWidth);
But note Sebastian's point that you may not need it, you may be able to use CSS's aspect-ratio.
I am working on a Fabric Grid using Fabric.js and I want to add the dimensions of the shape that is added on the canvas. The new Width and Height is defined but I will need to not only show the dimensions on the screen, but also get it updated when I resize the shape.
Below is the JS function, where newWidth and newHeight are defined:
function snapToGrid() {
let checkBox = document.getElementById("myCheck");
if (checkBox.checked == true) {
//snap only to the grid
const gridSize = 50;
c.on("object:moving", function (options) {
options.target.set({
left: Math.round(options.target.left / gridSize) * gridSize,
top: Math.round(options.target.top / gridSize) * gridSize,
});
});
c.on("object:modified", function (options) {
var newWidth =
Math.round(options.target.getWidth() / gridSize) * gridSize;
var newHeight =
Math.round(options.target.getHeight() / gridSize) * gridSize;
options.target.set({
width: newWidth,
height: newHeight,
scaleX: 1,
scaleY: 1,
});
});
} else {
c.off("object:modified");
c.off("object:moving");
}
}
I am new to Fabric.js and would appreciate if someone helped me on this. Please let me know if I'' have to share more details of the code.
Okay so I've answered my own question, so if anyone needs it, here's the below code that would help to dynamically show your shape's width and height while altered.
function onObjectScaled(e){
var scaledObject = e.target;
var text = document.getElementById("text");
text.value = 'Width = '+scaledObject.getWidth() + ' Height = '+scaledObject.getHeight();
}
I am trying to convert a html div to pdf using jsPDF. With in my div I have a svg file with background image where user can draw rectangle, line, text etc. I am using d3.js for drawing. Now I want to save my div with all drawing to pdf but it only converting my text to pdf. My js code is
function htmlToPdf() {
console.log("--------------- with in demoFromHTML");
var pdf = new jsPDF('p', 'pt', 'letter');
// source can be HTML-formatted string, or a reference
// to an actual DOM element from which the text will be scraped.
source = $('svg.plancontainer')[0];
// we support special element handlers. Register them with jQuery-style
// ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
// There is no support for any other type of selectors
// (class, of compound) at this time.
specialElementHandlers = {
// element with id of "bypass" - jQuery style selector
'#bypassme': function (element, renderer) {
// true = "handled elsewhere, bypass text extraction"
return true
}
};
margins = {
top: 80,
bottom: 60,
left: 40,
width: 522
};
// all coords and widths are in jsPDF instance's declared units
// 'inches' in this case
pdf.fromHTML(
source, // HTML string or DOM elem ref.
margins.left, // x coord
margins.top, { // y coord
'width': margins.width, // max width of content on PDF
'elementHandlers': specialElementHandlers
},
function (dispose) {
// dispose: object with X, Y of the last line add to the PDF
// this allow the insertion of new lines after html
// pdf.autoPrint();
pdf.output('dataurlnewwindow');
}, margins
);
}
and cdn is <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.debug.js"></script>
It print PRINT AREA instead of my image and text with out svg drawing.
It is my sample div's preview that I want to convert to pdf
I did not get any specific informatin that specify where it is possible using jsPDF or not.
Now my questions are
Is it possible using jsPDF or any other js library ?
If possible, would you please suggest me?
Any kind of help are appreciated. Thanks.
I am sharing my solution that may help someone. I could not manage print svg directly using jspdf instead what I have done is first convert svg to image using https://github.com/exupero/saveSvgAsPng then use that image to create pdf. Below is my code
Get base64 image uri using svgAsPngUri method of saveSvgAsPng and pass that image through callback function
svgAsPngUri(#svgObj, options, function (uri, options) {
pdf(uri, options.pdf)
});
where I am getting image uri as uri. With in my pdf function I am using this uri to make pdf
function pdf(b64Image, options) {
console.log("--------------- passing options is ", JSON.stringify(options, null, 4));
var image = new Image();
image.src = b64Image;
console.log('--------- pdf options' + JSON.stringify(options, null, 4));
var pdf = new jsPDF(options.orientation, null, options.format);
margins = {
top: 20,
bottom: 20,
left: 20,
right: 20
};
var pdfWidth = pdf.internal.pageSize.width;
var pdfHeight = pdf.internal.pageSize.height;
var footer_height = options.f_height || 30;
var htmlPageRightOffset = 0;
var outerRacBorder = 2;
var imageDrawableHeight = pdfHeight - margins.top - margins.bottom - footer_height - outerRacBorder;
var imageDrawableWidth = pdfWidth - margins.left - margins.right - outerRacBorder;
footer = {
top: margins.top + imageDrawableHeight + outerRacBorder + 10,
bottom: 20,
left: margins.left,
right: 20,
width: 100,
height: 25,
};
company_text_position = {
x: footer.left+2,
y: footer.top + 6
};
site_text_position = {
x: company_text_position.x,
y: company_text_position.y + 6
};
floor_plan_text_position = {
x: site_text_position.x,
y: site_text_position.y + 6
};
logo_text_position = {
x: pdfWidth - margins.left - 55,
y: pdfHeight - margins.bottom - 4
};
logo_image_position = {
x: logo_text_position.x +35,
y: logo_text_position.y - 4
};
/*
Image drawing on pdf
*/
imageSize = calculateAspectRatioFit(image.width, image.height, imageDrawableWidth, imageDrawableHeight);
pdf.addImage(image, 'JPEG', margins.left + 2, margins.top + 2, imageSize.width, imageSize.height);
/*
Outer rectangle
*/
pdf.rect(margins.left, margins.top, imageDrawableWidth + outerRacBorder, imageDrawableHeight + outerRacBorder);
// pdf.rect(margins.left, imageSize.height + 10, drawableWidth, (drawableWidth - imageSize.height));
pdf.rect(footer.left, footer.top, footer.width, footer.height);
console.log(footer.left);
console.log(footer.company_x);
var footer_data = getFooterInfo();
pdf.text("Company: " + footer_data.client, company_text_position.x, company_text_position.y);
pdf.text("Site: " + footer_data.site, site_text_position.x, site_text_position.y);
pdf.text("Floor Plan: " + footer_data.floor_plan, floor_plan_text_position.x, floor_plan_text_position.y);
pdf.text("Powered by: ", logo_text_position.x, logo_text_position.y);
var logo = new Image();
logo.src = $('#logo_image').val();
console.log(logo);
logoSize = calculateAspectRatioFit(logo.width, logo.height, 20, 10);
pdf.addImage(logo, 'JPEG', logo_image_position.x, logo_image_position.y, logoSize.width, logoSize.height);
pdf.autoPrint();
pdf.save(options.name + '.pdf');
}
/**
* Conserve aspect ratio of the orignal region. Useful when shrinking/enlarging
* images to fit into a certain area.
*
* #param {Number} srcWidth Source area width
* #param {Number} srcHeight Source area height
* #param {Number} maxWidth Fittable area maximum available width
* #param {Number} maxHeight Fittable area maximum available height
* #return {Object} { width, heigth }
*
*/
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
if(srcHeight == 0 || srcWidth == 0){
return {width: maxWidth, height: maxHeight};
}
var ratio = [maxWidth / srcWidth, maxHeight / srcHeight];
ratio = Math.min(ratio[0], ratio[1]);
return {width: srcWidth * ratio, height: srcHeight * ratio};
}
function getFooterInfo() {
var elem = $('.entityselbin .h4');
var info = {};
info.client = elem[0].innerHTML;
info.site = elem[1].innerHTML;
info.floor_plan = elem[2].innerHTML;
return info;
}
You can directly write the SVG to PDF with the latest canvg_context2d method mention in the example
https://github.com/MrRio/jsPDF/blob/master/examples/canvg_context2d/bar_graph_with_text_and_lines.html
This works for most of the svg contents.
Below is the working example of above question.
Need to include these three file refernece
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"),
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.0.272/jspdf.debug.js"),
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/canvg/1.5/canvg.min.js")
function createPDF() {
var svg = '';
// Provide the SVG parent div id
if (document.getElementById("ChartId") != null) {
svg = document.getElementById("ChartId").innerHTML;
}
if (svg)
svg = svg.replace(/\r?\n|\r/g, '').trim();
var pdfData = $('#htmlContainer');//main html div
html2canvas(pdfData, {
onrendered: function(canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//The height of the canvas which one pdf page can show;
var pageHeight = contentWidth / 592.28 * 841.89;
//the height of canvas that haven't render to pdf
var leftHeight = contentHeight;
//addImage y-axial offset
var position = 0;
//a4 format [595.28,841.89]
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;
var ctx = canvas.getContext('2d');
canvg(canvas, svg, {
offsetX: 10,
offsetY: 660,
ignoreMouse: true,
ignoreAnimation: true,
ignoreClear: true,
ignoreDimensions: true
});
var pageData = new Image();
pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new jsPDF('l', 'pt', 'a4', true);
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 100, 20, imgWidth, imgHeight);
} else {
console.log('page 2');
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
//avoid blank page
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save('Test.pdf');
}
});
}
Hope this will be helpful.
I've been using jslint to try see what it says about my code, and i get lots of flags, but i am working through trying improve it. However i am stuck on the error
maxHeight was used before it was defined
My jQuery:
$.fn.thumbSizr = function () { // begin function
"use strict";
return this.each(function () {
var $this = $(this);
maxWidth = $(this).parent().width(); // Max width for the image
minHeight = $(this).parent().height(); // Max height for the image
ratio = 0; // Used for aspect ratio
width = $(this).width(); // Current image width
height = $(this).height(); // Current image height
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height < minHeight){
ratio = minHeight / height; // get ratio for scaling image
$(this).css("height", minHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
var $img = $(this),
css = {
position: 'absolute',
marginLeft: '-' + (parseInt( $img.css('width') ) / 2) + 'px',
left: '50%',
top: '50%',
marginTop: '-' + (parseInt( $img.css('height') ) / 2) + 'px'
};
$img.css( css );
});
};
I'm no jQuery pro so this might be ropey but i really wanted to make it as good as possible. Can anyone explain and suggest why i am getting this message and how to avoid it in the future?
Thanks
You are using semicolon instead of comma when declaring multiple variable with single "var"
This part is wrong:
var $this = $(this);
maxWidth = $(this).parent().width(); // Max width for the image
minHeight = $(this).parent().height(); // Max height for the image
ratio = 0; // Used for aspect ratio
width = $(this).width(); // Current image width
height = $(this).height(); // Current image height
fixed:
var $this = $(this),
maxWidth = $(this).parent().width(), // Max width for the image
minHeight = $(this).parent().height(), // Max height for the image
ratio = 0, // Used for aspect ratio
width = $(this).width(), // Current image width
height = $(this).height(); // Current image height
I am trying to write a JavaScript function that will expand an image to fill a div always (so crop top or sides as needed). It is the JavaScript equivalent of the CSS3 code background-size: cover.
I can't for the life of me figure it out. This is what I have so far:
function full_bleed(box_width, box_height, new_width, new_height)
{
var aspect_ratio=new_width/new_height;
if(new_height<box_height) {
new_height=box_height;
new_width=Math.round(new_height*aspect_ratio);
}
if(new_width<box_width) {
new_width=box_width;
new_height=Math.round(new_width/aspect_ratio);
}
return {
width: new_width,
height: new_height
};
}
I figured one of you guys might have the equation lying around.
Thanks to the comment from Ben, I figured it out.
full_bleed: function(boxWidth, boxHeight, imgWidth, imgHeight)
{
// Calculate new height and width
var initW = imgWidth;
var initH = imgHeight;
var ratio = initH / initW;
imgWidth = boxWidth;
imgHeight = boxWidth * ratio;
if(imgHeight < boxHeight){
imgHeight = boxHeight;
imgWidth = imgHeight / ratio;
}
// Return new size
return {
width: imgWidth,
height: imgHeight
};
}
I made some changes on Drew's solution to better fit my needs.
function calculateCover(frame, sides) {
var ratio = sides[1] / sides[0],
cover = {
width: frame.width,
height: Math.ceil(frame.width * ratio)
};
if (cover.height <= frame.height) {
cover.height = frame.height;
cover.width = Math.ceil(frame.height / ratio);
}
return cover;
}
calculateCover({width: 1280, height: 822}, [16,9]);
The idea is the same, but the point here is to calculate the scaled up size without having an initial size of the media, instead using a given aspect ratio. I use it for video embeds, rather than images, where I load the video via YouTube API, for example, and I don't have any initial size, but I know the ratio and I want to stretch the video across the available space. (Of course, it can be changed back to calculate the ratio from the actual dimensions of the video or image.)
Also made some code simplifications.