How to get ScaleX and ScaleY value while resizing a resizable div..? - html

I have set the width as 100px and height as 100px. I need to get the ScaleX and ScaleY value while resizing the resizable div..? I have used Jquery-ui to resize. Please check in chrome first. Please help me. Thanks in Advance.
$("#resize_div").resizable({
resize: function(){
node = $("#resize_div")[0];
var curTransform = new WebKitCSSMatrix(window.getComputedStyle(node).webkitTransform);
$("#scalex").text("Scale X: " + curTransform.a);
$("#scaley").text("Scale Y: " + curTransform.d);
}
});
My code in Jsfiddle.!

can you try this?
$("#resize_div").resizable({
resize: function(){
var width = $(this).width();
var height = $(this).height();
var scalax = width/height;
var scalay = height/width;
node = $("#resize_div")[0];
var curTransform = new WebKitCSSMatrix(window.getComputedStyle(node).webkitTransform);
$("#scalex").text("Scale X: " + scalax);
$("#scaley").text("Scale Y: " + scalay);
}
});

I noticed that, Scale-X value can get by dividing the current width(while resize) divided by the initial width(in this case the initial width is 100px).
Try this..
$("#resize_div").resizable({
resize: function(){
var width = $(this).width();
var height = $(this).height();
var scalax = width/100;
var scalay = height/100;
$("#scalex").text("Scale X: " + scalax);
$("#scaley").text("Scale Y: " + scalay);
}
});

Related

Dynamically change font-size within parent element with no overflow [duplicate]

I need to display user entered text into a fixed size div. What i want is for the font size to be automatically adjusted so that the text fills the box as much as possible.
So - If the div is 400px x 300px. If someone enters ABC then it's really big font. If they enter a paragraph, then it would be a tiny font.
I'd probably want to start with a maximum font size - maybe 32px, and while the text is too big to fit the container, shrink the font size until it fits.
This is what I ended up with:
Here is a link to the plugin: https://plugins.jquery.com/textfill/
And a link to the source: http://jquery-textfill.github.io/
;(function($) {
$.fn.textfill = function(options) {
var fontSize = options.maxFontPixels;
var ourText = $('span:visible:first', this);
var maxHeight = $(this).height();
var maxWidth = $(this).width();
var textHeight;
var textWidth;
do {
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
fontSize = fontSize - 1;
} while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
return this;
}
})(jQuery);
$(document).ready(function() {
$('.jtextfill').textfill({ maxFontPixels: 36 });
});
and my HTML is like this
<div class='jtextfill' style='width:100px;height:50px;'>
<span>My Text Here</span>
</div>
I didn't find any of the previous solutions to be adequate enough due to bad performance, so I made my own that uses simple math instead of looping. Should work fine in all browsers as well.
According to this performance test case it is much faster then the other solutions found here.
(function($) {
$.fn.textfill = function(maxFontSize) {
maxFontSize = parseInt(maxFontSize, 10);
return this.each(function(){
var ourText = $("span", this),
parent = ourText.parent(),
maxHeight = parent.height(),
maxWidth = parent.width(),
fontSize = parseInt(ourText.css("fontSize"), 10),
multiplier = maxWidth/ourText.width(),
newSize = (fontSize*(multiplier-0.1));
ourText.css(
"fontSize",
(maxFontSize > 0 && newSize > maxFontSize) ?
maxFontSize :
newSize
);
});
};
})(jQuery);
If you want to contribute I've added this to Gist.
As much as I love the occasional upvotes I get for this answer (thanks!), this is really not the greatest approach to this problem. Please check out some of the other wonderful answers here, especially the ones that have found solutions without looping.
Still, for the sake of reference, here's my original answer:
<html>
<head>
<style type="text/css">
#dynamicDiv
{
background: #CCCCCC;
width: 300px;
height: 100px;
font-size: 64px;
overflow: hidden;
}
</style>
<script type="text/javascript">
function shrink()
{
var textSpan = document.getElementById("dynamicSpan");
var textDiv = document.getElementById("dynamicDiv");
textSpan.style.fontSize = 64;
while(textSpan.offsetHeight > textDiv.offsetHeight)
{
textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
}
}
</script>
</head>
<body onload="shrink()">
<div id="dynamicDiv"><span id="dynamicSpan">DYNAMIC FONT</span></div>
</body>
</html>
And here's a version with classes:
<html>
<head>
<style type="text/css">
.dynamicDiv
{
background: #CCCCCC;
width: 300px;
height: 100px;
font-size: 64px;
overflow: hidden;
}
</style>
<script type="text/javascript">
function shrink()
{
var textDivs = document.getElementsByClassName("dynamicDiv");
var textDivsLength = textDivs.length;
// Loop through all of the dynamic divs on the page
for(var i=0; i<textDivsLength; i++) {
var textDiv = textDivs[i];
// Loop through all of the dynamic spans within the div
var textSpan = textDiv.getElementsByClassName("dynamicSpan")[0];
// Use the same looping logic as before
textSpan.style.fontSize = 64;
while(textSpan.offsetHeight > textDiv.offsetHeight)
{
textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
}
}
}
</script>
</head>
<body onload="shrink()">
<div class="dynamicDiv"><span class="dynamicSpan">DYNAMIC FONT</span></div>
<div class="dynamicDiv"><span class="dynamicSpan">ANOTHER DYNAMIC FONT</span></div>
<div class="dynamicDiv"><span class="dynamicSpan">AND YET ANOTHER DYNAMIC FONT</span></div>
</body>
</html>
Most of the other answers use a loop to reduce the font-size until it fits on the div, this is VERY slow since the page needs to re-render the element each time the font changes size. I eventually had to write my own algorithm to make it perform in a way that allowed me to update its contents periodically without freezing the user browser. I added some other functionality (rotating text, adding padding) and packaged it as a jQuery plugin, you can get it at:
https://github.com/DanielHoffmann/jquery-bigtext
simply call
$("#text").bigText();
and it will fit nicely on your container.
See it in action here:
http://danielhoffmann.github.io/jquery-bigtext/
For now it has some limitations, the div must have a fixed height and width and it does not support wrapping text into multiple lines.
I will work on getting an option to set the maximum font-size.
Edit: I have found some more problems with the plugin, it does not handle other box-model besides the standard one and the div can't have margins or borders. I will work on it.
Edit2: I have now fixed those problems and limitations and added more options. You can set maximum font-size and you can also choose to limit the font-size using either width, height or both. I will work into accepting a max-width and max-height values in the wrapper element.
Edit3: I have updated the plugin to version 1.2.0. Major cleanup on the code and new options (verticalAlign, horizontalAlign, textAlign) and support for inner elements inside the span tag (like line-breaks or font-awesome icons.)
This is based on what GeekyMonkey posted above, with some modifications.
; (function($) {
/**
* Resize inner element to fit the outer element
* #author Some modifications by Sandstrom
* #author Code based on earlier works by Russ Painter (WebDesign#GeekyMonkey.com)
* #version 0.2
*/
$.fn.textfill = function(options) {
options = jQuery.extend({
maxFontSize: null,
minFontSize: 8,
step: 1
}, options);
return this.each(function() {
var innerElements = $(this).children(':visible'),
fontSize = options.maxFontSize || innerElements.css("font-size"), // use current font-size by default
maxHeight = $(this).height(),
maxWidth = $(this).width(),
innerHeight,
innerWidth;
do {
innerElements.css('font-size', fontSize);
// use the combined height of all children, eg. multiple <p> elements.
innerHeight = $.map(innerElements, function(e) {
return $(e).outerHeight();
}).reduce(function(p, c) {
return p + c;
}, 0);
innerWidth = innerElements.outerWidth(); // assumes that all inner elements have the same width
fontSize = fontSize - options.step;
} while ((innerHeight > maxHeight || innerWidth > maxWidth) && fontSize > options.minFontSize);
});
};
})(jQuery);
Here's an improved looping method that uses binary search to find the largest possible size that fits into the parent in the fewest steps possible (this is faster and more accurate than stepping by a fixed font size). The code is also optimized in several ways for performance.
By default, 10 binary search steps will be performed, which will get within 0.1% of the optimal size. You could instead set numIter to some value N to get within 1/2^N of the optimal size.
Call it with a CSS selector, e.g.: fitToParent('.title-span');
/**
* Fit all elements matching a given CSS selector to their parent elements'
* width and height, by adjusting the font-size attribute to be as large as
* possible. Uses binary search.
*/
var fitToParent = function(selector) {
var numIter = 10; // Number of binary search iterations
var regexp = /\d+(\.\d+)?/;
var fontSize = function(elem) {
var match = elem.css('font-size').match(regexp);
var size = match == null ? 16 : parseFloat(match[0]);
return isNaN(size) ? 16 : size;
}
$(selector).each(function() {
var elem = $(this);
var parentWidth = elem.parent().width();
var parentHeight = elem.parent().height();
if (elem.width() > parentWidth || elem.height() > parentHeight) {
var maxSize = fontSize(elem), minSize = 0.1;
for (var i = 0; i < numIter; i++) {
var currSize = (minSize + maxSize) / 2;
elem.css('font-size', currSize);
if (elem.width() > parentWidth || elem.height() > parentHeight) {
maxSize = currSize;
} else {
minSize = currSize;
}
}
elem.css('font-size', minSize);
}
});
};
I've created a directive for AngularJS - heavely inspired by GeekyMonkey's answer but without the jQuery dependency.
Demo: http://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p=preview
Markup
<div class="fittext" max-font-size="50" text="Your text goes here..."></div>
Directive
app.directive('fittext', function() {
return {
scope: {
minFontSize: '#',
maxFontSize: '#',
text: '='
},
restrict: 'C',
transclude: true,
template: '<div ng-transclude class="textContainer" ng-bind="text"></div>',
controller: function($scope, $element, $attrs) {
var fontSize = $scope.maxFontSize || 50;
var minFontSize = $scope.minFontSize || 8;
// text container
var textContainer = $element[0].querySelector('.textContainer');
angular.element(textContainer).css('word-wrap', 'break-word');
// max dimensions for text container
var maxHeight = $element[0].offsetHeight;
var maxWidth = $element[0].offsetWidth;
var textContainerHeight;
var textContainerWidth;
var resizeText = function(){
do {
// set new font size and determine resulting dimensions
textContainer.style.fontSize = fontSize + 'px';
textContainerHeight = textContainer.offsetHeight;
textContainerWidth = textContainer.offsetWidth;
// shrink font size
var ratioHeight = Math.floor(textContainerHeight / maxHeight);
var ratioWidth = Math.floor(textContainerWidth / maxWidth);
var shrinkFactor = ratioHeight > ratioWidth ? ratioHeight : ratioWidth;
fontSize -= shrinkFactor;
} while ((textContainerHeight > maxHeight || textContainerWidth > maxWidth) && fontSize > minFontSize);
};
// watch for changes to text
$scope.$watch('text', function(newText, oldText){
if(newText === undefined) return;
// text was deleted
if(oldText !== undefined && newText.length < oldText.length){
fontSize = $scope.maxFontSize;
}
resizeText();
});
}
};
});
I forked the script above from Marcus Ekwall: https://gist.github.com/3945316 and tweaked it to my preferences, it now fires when the window is resized, so that the child always fits its container. I've pasted the script below for reference.
(function($) {
$.fn.textfill = function(maxFontSize) {
maxFontSize = parseInt(maxFontSize, 10);
return this.each(function(){
var ourText = $("span", this);
function resizefont(){
var parent = ourText.parent(),
maxHeight = parent.height(),
maxWidth = parent.width(),
fontSize = parseInt(ourText.css("fontSize"), 10),
multiplier = maxWidth/ourText.width(),
newSize = (fontSize*(multiplier));
ourText.css("fontSize", maxFontSize > 0 && newSize > maxFontSize ? maxFontSize : newSize );
}
$(window).resize(function(){
resizefont();
});
resizefont();
});
};
})(jQuery);
Here's my modification of the OP's answer.
In short, many people who tried to optimize this complained that a loop was being used. Yes, while loops can be slow, other approaches can be inaccurate.
Therefore, my approach uses Binary Search to find the best Font Size:
$.fn.textfill = function()
{
var self = $(this);
var parent = self.parent();
var attr = self.attr('max-font-size');
var maxFontSize = parseInt(attr, 10);
var unit = attr.replace(maxFontSize, "");
var minFontSize = parseInt(self.attr('min-font-size').replace(unit, ""));
var fontSize = (maxFontSize + minFontSize) / 2;
var maxHeight = parent.height();
var maxWidth = parent.width();
var textHeight;
var textWidth;
do
{
self.css('font-size', fontSize + unit);
textHeight = self.height();
textWidth = self.width();
if(textHeight > maxHeight || textWidth > maxWidth)
{
maxFontSize = fontSize;
fontSize = Math.floor((fontSize + minFontSize) / 2);
}
else if(textHeight < maxHeight || textWidth < maxWidth)
{
minFontSize = fontSize;
fontSize = Math.floor((fontSize + maxFontSize) / 2);
}
else
break;
}
while(maxFontSize - minFontSize > 1 && maxFontSize > minFontSize);
self.css('font-size', fontSize + unit);
return this;
}
function resizeText()
{
$(".textfill").textfill();
}
$(document).ready(resizeText);
$(window).resize(resizeText);
This also allows the element to specify the minimum and maximum font:
<div class="container">
<div class="textfill" min-font-size="10px" max-font-size="72px">
Text that will fill the container, to the best of its abilities, and it will <i>never</i> have overflow.
</div>
</div>
Furthermore, this algorithm is unitless. You may specify em, rem, %, etc. and it will use that for its final result.
Here's the Fiddle: https://jsfiddle.net/fkhqhnqe/1/
I had exactly the same problem with my website. I have a page that is displayed on a projector, on walls, big screens..
As I don't know the max size of my font, I re-used the plugin above of #GeekMonkey but incrementing the fontsize :
$.fn.textfill = function(options) {
var defaults = { innerTag: 'span', padding: '10' };
var Opts = jQuery.extend(defaults, options);
return this.each(function() {
var ourText = $(Opts.innerTag + ':visible:first', this);
var fontSize = parseFloat(ourText.css('font-size'),10);
var doNotTrepass = $(this).height()-2*Opts.padding ;
var textHeight;
do {
ourText.css('font-size', fontSize);
textHeight = ourText.height();
fontSize = fontSize + 2;
} while (textHeight < doNotTrepass );
});
};
The proposed iterative solutions can be sped up dramatically on two fronts:
1) Multiply the font size by some constant, rather than adding or subtracting 1.
2) First, zero in using a course constant, say, double the size each loop. Then, with a rough idea of where to start, do the same thing with a finer adjustment, say, multiply by 1.1. While the perfectionist might want the exact integer pixel size of the ideal font, most observers don't notice the difference between 100 and 110 pixels. If you are a perfectionist, then repeat a third time with an even finer adjustment.
Rather than writing a specific routine or plug-in that answers the exact question, I just rely on the basic ideas and write variations of the code to handle all kinds of layout issues, not just text, including fitting divs, spans, images,... by width, height, area,... within a container, matching another element....
Here's an example:
var nWindowH_px = jQuery(window).height();
var nWas = 0;
var nTry = 5;
do{
nWas = nTry;
nTry *= 2;
jQuery('#divTitle').css('font-size' ,nTry +'px');
}while( jQuery('#divTitle').height() < nWindowH_px );
nTry = nWas;
do{
nWas = nTry;
nTry = Math.floor( nTry * 1.1 );
jQuery('#divTitle').css('font-size' ,nTry +'px');
}while( nWas != nTry && jQuery('#divTitle').height() < nWindowH_px );
jQuery('#divTitle').css('font-size' ,nWas +'px');
Here is a version of the accepted answer which can also take a minFontSize parameter.
(function($) {
/**
* Resizes an inner element's font so that the inner element completely fills the outer element.
* #author Russ Painter WebDesign#GeekyMonkey.com
* #author Blake Robertson
* #version 0.2 -- Modified it so a min font parameter can be specified.
*
* #param {Object} Options which are maxFontPixels (default=40), innerTag (default='span')
* #return All outer elements processed
* #example <div class='mybigdiv filltext'><span>My Text To Resize</span></div>
*/
$.fn.textfill = function(options) {
var defaults = {
maxFontPixels: 40,
minFontPixels: 10,
innerTag: 'span'
};
var Opts = jQuery.extend(defaults, options);
return this.each(function() {
var fontSize = Opts.maxFontPixels;
var ourText = $(Opts.innerTag + ':visible:first', this);
var maxHeight = $(this).height();
var maxWidth = $(this).width();
var textHeight;
var textWidth;
do {
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
fontSize = fontSize - 1;
} while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > Opts.minFontPixels);
});
};
})(jQuery);
You can use FitText.js (github page) to solve this problem. Is really small and efficient compared to TextFill. TextFill uses an expensive while loop and FitText don't.
Also FitText is more flexible (I use it in a proyect with very special requirements and works like a champ!).
HTML:
<div class="container">
<h1 id="responsive_headline">Your fancy title</h1>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
<script>
jQuery("#responsive_headline").fitText();
</script>
You also can set options to it:
<script>
jQuery("#responsive_headline").fitText(1, { minFontSize: '30px', maxFontSize: '90px'});
</script>
CSS:
#responsive_headline {
width: 100%;
display: block;
}
And if you need it, FitText also has a no-jQuery version.
EDIT: This code was used to show notes on top of a HTML5 video. It changes the font-size on the fly when the video is resized (when the browser window is resized.) The notes was connected to the video (just like notes on YouTube), which is why the code uses instances instead of a DOM handle directly.
As per request I'll throw in some code that I used to achieve this. (Text boxes over an HTML5 video.) The code was written a long time ago, and I quite frankly think it's pretty messy. Since the question is already answered and an answer is already accepted a long time ago I don't bother rewriting this. But if anyone wants to simplify this a bit, you're more than welcome!
// Figure out the text size:
var text = val['text'];
var letters = text.length;
var findMultiplier = function(x) { // g(x)
/* By analysing some functions with regression, the resulting function that
gives the best font size with respect to the number of letters and the size
of the note is:
g(x) = 8.3 - 2.75x^0.15 [1 < x < 255]
f(x) = g(letters) * (x / 1000)^0.5
Font size = f(size)
*/
return 8.3 - 2.75 * Math.pow(x, 0.15);
};
var findFontSize = function(x) { // f(x)
return findMultiplier(letters) * Math.pow(x / 1000, 0.5);
};
val.setFontSizeListener = function() {
p.style.fontSize = '1px'; // So the text should not overflow the box when measuring.
var noteStyle = window.getComputedStyle(table);
var width = noteStyle.getPropertyValue('width');
var height = noteStyle.getPropertyValue('height');
var size = width.substring(0, width.length - 2) * height.substring(0, height.length - 2);
p.style.fontSize = findFontSize(size) + 'px';
};
window.addEventListener('resize', val.setFontSizeListener);
You'll probably need to tweak these numbers from font-family to font-family. A good way to do this is download a free graph visualizer called GeoGebra. Change the length of the text and the size of the box. Then you manually set the size. Plot the manual results into the coordinate system. Then you enter the two equations I've posted here and you tweak the numbers until "my" graph fits your own manually plotted points.
Just wanted to add my version for contenteditables.
$.fn.fitInText = function() {
this.each(function() {
let textbox = $(this);
let textboxNode = this;
let mutationCallback = function(mutationsList, observer) {
if (observer) {
observer.disconnect();
}
textbox.css('font-size', 0);
let desiredHeight = textbox.css('height');
for (i = 12; i < 50; i++) {
textbox.css('font-size', i);
if (textbox.css('height') > desiredHeight) {
textbox.css('font-size', i - 1);
break;
}
}
var config = {
attributes: true,
childList: true,
subtree: true,
characterData: true
};
let newobserver = new MutationObserver(mutationCallback);
newobserver.observe(textboxNode, config);
};
mutationCallback();
});
}
$('#inner').fitInText();
#outer {
display: table;
width: 100%;
}
#inner {
border: 1px solid black;
height: 170px;
text-align: center;
display: table-cell;
vertical-align: middle;
word-break: break-all;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="outer">
<div id="inner" contenteditable=true>
TEST
</div>
</div>
This uses binary search, doing 10 iterations. The naive way was to do a while loop and increase the font size by 1 until the element started to overflow. You can determine when an element begins to overflow using element.offsetHeight and element.scrollHeight. If scrollHeight is bigger than offsetHeight, you have a font size that is too big.
Binary search is a much better algorithm for this. It also is limited by the number of iterations you want to perform. Simply call flexFont and insert the div id and it will adjust the font size between 8px and 96px.
I have spent some time researching this topic and trying different libraries, but ultimately I think this is the easiest and most straightforward solution that will actually work.
Note if you want you can change to use offsetWidth and scrollWidth, or add both to this function.
// Set the font size using overflow property and div height
function flexFont(divId) {
var content = document.getElementById(divId);
content.style.fontSize = determineMaxFontSize(content, 8, 96, 10, 0) + "px";
};
// Use binary search to determine font size
function determineMaxFontSize(content, min, max, iterations, lastSizeNotTooBig) {
if (iterations === 0) {
return lastSizeNotTooBig;
}
var obj = fontSizeTooBig(content, min, lastSizeNotTooBig);
// if `min` too big {....min.....max.....}
// search between (avg(min, lastSizeTooSmall)), min)
// if `min` too small, search between (avg(min,max), max)
// keep track of iterations, and the last font size that was not too big
if (obj.tooBig) {
(lastSizeTooSmall === -1) ?
determineMaxFontSize(content, min / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall) :
determineMaxFontSize(content, (min + lastSizeTooSmall) / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall);
} else {
determineMaxFontSize(content, (min + max) / 2, max, iterations - 1, obj.lastSizeNotTooBig, min);
}
}
// determine if fontSize is too big based on scrollHeight and offsetHeight,
// keep track of last value that did not overflow
function fontSizeTooBig(content, fontSize, lastSizeNotTooBig) {
content.style.fontSize = fontSize + "px";
var tooBig = content.scrollHeight > content.offsetHeight;
return {
tooBig: tooBig,
lastSizeNotTooBig: tooBig ? lastSizeNotTooBig : fontSize
};
}
I got the same problem and the solution is basically use javascript to control font-size.
Check this example on codepen:
https://codepen.io/ThePostModernPlatonic/pen/BZKzVR
This is example is only for height, maybe you need to put some if's about the width.
try to resize it
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
<style>
</style>
</head>
<body>
<div style="height:100vh;background-color: tomato;" id="wrap">
<h1 class="quote" id="quotee" style="padding-top: 56px">Because too much "light" doesn't <em>illuminate</em> our paths and warm us, it only blinds and burns us.</h1>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
var multiplexador = 3;
initial_div_height = document.getElementById ("wrap").scrollHeight;
setInterval(function(){
var div = document.getElementById ("wrap");
var frase = document.getElementById ("quotee");
var message = "WIDTH div " + div.scrollWidth + "px. "+ frase.scrollWidth+"px. frase \n";
message += "HEIGHT div " + initial_div_height + "px. "+ frase.scrollHeight+"px. frase \n";
if (frase.scrollHeight < initial_div_height - 30){
multiplexador += 1;
$("#quotee").css("font-size", multiplexador);
}
console.log(message);
}, 10);
</script>
</html>
I did like
let name = "Making statements based on opinion; back them up with references or personal experience."
let originFontSize = 15;
let maxDisplayCharInLine = 50;
let fontSize = Math.min(originFontSize, originFontSize / (name.length / maxDisplayCharInLine));
I have found a way to prevent the use of loops to shrink the text. It adjusts the font-size by multiplying it for the rate between container's width and content width. So if the container's width is 1/3 of the content, the font-size will be reduced by 1/3 and will container's width. To scale up, I have used a while loop, until content is bigger than container.
function fitText(outputSelector){
// max font size in pixels
const maxFontSize = 50;
// get the DOM output element by its selector
let outputDiv = document.getElementById(outputSelector);
// get element's width
let width = outputDiv.clientWidth;
// get content's width
let contentWidth = outputDiv.scrollWidth;
// get fontSize
let fontSize = parseInt(window.getComputedStyle(outputDiv, null).getPropertyValue('font-size'),10);
// if content's width is bigger than elements width - overflow
if (contentWidth > width){
fontSize = Math.ceil(fontSize * width/contentWidth,10);
fontSize = fontSize > maxFontSize ? fontSize = maxFontSize : fontSize - 1;
outputDiv.style.fontSize = fontSize+'px';
}else{
// content is smaller than width... let's resize in 1 px until it fits
while (contentWidth === width && fontSize < maxFontSize){
fontSize = Math.ceil(fontSize) + 1;
fontSize = fontSize > maxFontSize ? fontSize = maxFontSize : fontSize;
outputDiv.style.fontSize = fontSize+'px';
// update widths
width = outputDiv.clientWidth;
contentWidth = outputDiv.scrollWidth;
if (contentWidth > width){
outputDiv.style.fontSize = fontSize-1+'px';
}
}
}
}
This code is part of a test that I have uploaded to Github https://github.com/ricardobrg/fitText/
I went with geekMonkey solution, but it's too slow. What he does, is he adjusts the font size to maximum (maxFontPixels) and then checks if it fits inside the container. else it reduces the font size by 1px and checks again. Why not simply check the previous container for the height and submit that value? (yes, I know why, but I now made a solution, that only works on the height and also has a min/max option)
Here is a much quicker solution:
var index_letters_resize;
(index_letters_resize = function() {
$(".textfill").each(function() {
var
$this = $(this),
height = Math.min( Math.max( parseInt( $this.height() ), 40 ), 150 );
$this.find(".size-adjust").css({
fontSize: height
});
});
}).call();
$(window).on('resize', function() {
index_letters_resize();
);
and this would be the HTML:
<div class="textfill">
<span class="size-adjust">adjusted element</span>
other variable stuff that defines the container size
</div>
Again: this solution ONLY checks for the height of the container. That's why this function does not has to check, if the element fits inside. But I also implemented a min/max value (40min, 150max) so for me this works perfectly fine (and also works on window resize).
Here is another version of this solution:
shrinkTextInElement : function(el, minFontSizePx) {
if(!minFontSizePx) {
minFontSizePx = 5;
}
while(el.offsetWidth > el.parentNode.offsetWidth || el.offsetHeight > el.parentNode.offsetHeight) {
var newFontSize = (parseInt(el.style.fontSize, 10) - 3);
if(newFontSize <= minFontSizePx) {
break;
}
el.style.fontSize = newFontSize + "px";
}
}

Html2Canvas image is getting cut

I use Html2Canvas and then jsPdf to export the image.
This is the function:
function exportPdf() {
content = $("#print");
var useWidth = content.prop('scrollWidth');
var useHeight = content.prop('scrollHeight');
debugger;
html2canvas((content), { width: useWidth, height: useHeight}).then(function (canvas) {
debugger;
var img = canvas.toDataURL("image/png");
var doc = new jsPDF({
unit:'px',
format:'a4'
});
debugger;
doc.addImage(img, 'JPEG', 0, 0);
doc.save('test.pdf');
});
}
I think is taking in consideration the viewport, is like doing a printscreen, of course whatever is below the scroll it doesn't take it into consideration.
Any ideas?
Call
window.scrollTo(0,0)
Before calling html2canvas, its seems its a bug but the window needs to be at the top for html2canvas to capture the entire DOM passed to it
It happens when window is scrolled. To work around this problem you can pass negative of whatever window is scrolled by.
html2canvas(htmlSource, {scrollY: -window.scrollY}).then(function(canvas) {
// Do Something here
});
One of the reason is already mentioned above that is window might be scrolled, so always add this line before u capture image using html2canvas
window.scrollTo(0,0)
Another problem can be the resolution of image is more than a pdf page, for that you need to get the width and height of PDF document.
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
Use it for your image to fit the PDF document.
doc.addImage(imgData, 'JPEG', 0, 0, width, height);
If you want a dynamic sized image not to be distorted and keep the image width/height ratio
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
let widthRatio = width / canvas.width;
let heightRatio = height / canvas.height;
let ratio = widthRatio > heightRatio ? heightRatio : widthRatio
Followed by
doc.addImage(imgData, "PNG", 0, 0, canvas.width * ratio, canvas.height * ratio,);
You can try something with the responsive way like :
if (screen.width < 1024) {
document
.querySelector("meta[name=viewport]")
.setAttribute("content", "width=1200px");
}
let generatedPDFB64;
//used the Printable HOC for capturing printable component with print-id attribute
const printElement = document.querySelector(`div[print-id=${selector}]`);
// convert the html to canvase
const convertedCanvas = await html2canvas(printElement, {
allowTaint: true,
removeContainer: true,
backgroundColor: null,
imageTimeout: 15000,
logging: true,
scale: 2,
scrollY: window.scrollTo({
top: 0,
behavior: 'smooth'
}),
useCORS: true
});
const contentDataURL = convertedCanvas.toDataURL("image/png");
const imgWidth = 205;
const pageHeight = 300;
const imgHeight = (convertedCanvas.height * imgWidth) / convertedCanvas.width;
let heightLeft = imgHeight;
const shouldCompress = true
let pdf = new jsPDF("p", "mm", "a4", shouldCompress); // A4 size page of PDF
let position = 0;
pdf.addImage(
contentDataURL,
"PNG",
0,
position,
imgWidth,
imgHeight,
"print",
"FAST"
);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(
convertedCanvas,
0,
position,
imgWidth,
imgHeight,
"print",
"FAST"
);
heightLeft -= pageHeight;
}
pdf.save("resume.pdf"); // Generated PDF
if (screen.width < 1024) {
document
.querySelector("meta[name=viewport]")
.setAttribute("content", "width=device-width, initial-scale=1");
}
Setting windowHeight and height worked for me:
Try like this:
html2canvas(htmlSource, {
height: window.outerHeight + window.innerHeight,
windowHeight: window.outerHeight + window.innerHeight,
scrollY: -window.scrollY
}).then(function(canvas) {
// Do Something here
});
The only thing that worked for me, was to add the following code into my css.
This style code is used to prevent html2canvas limit the rendering to the viewable area.
.html2canvas-container {
width: 3000px;
height: 3000px;
}
For my case, I added a class to make it fixed:
$("#print").addClass('ready-fix');
CSS:
.ready-fix {
position: fixed !important;
top: 0;
left: 50%;
z-index: 9999;
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
Then called "html2canvas", the image was no longer cropped:
html2canvas(document.querySelector("#print"), { scale: window.devicePixelRatio, allowTaint: true }).then(canvas => {
//code here
$("#print").removeClass('ready-fix');
})
Finally removed the fixed class.

how to calculate browser body width and height

how can i calculate body width and height for all browser in java query...
$(document).ready(function () {
$(document).ready(sizeContent01);
function sizeContent01() {
var totHeight = ($("body").height());
var hdrHeight = $("#header").outerHeight(true);
var ftrHeight = $("#footer").outerHeight(true);
var bdyHeight1 = totHeight - hdrHeight - 10;
var outputHeight = bdyHeight1 - $(".input_content").outerHeight(true) - 10;
$("#body").css("height", bdyHeight1);
$(".output_content").css("height", (outputHeight - 5));
};
$(window).resize(sizeContent02);
function sizeContent02() {
var totHeight = ($("body").height());
var hdrHeight = $("#header").outerHeight(true);
var ftrHeight = $("#footer").outerHeight(true);
var bdyHeight1 = totHeight - hdrHeight - 10;
var outputHeight = bdyHeight1 - $(".input_content").outerHeight(true) - 10;
$("#body").css('height', bdyHeight1);
$(".output_content").css('height', (outputHeight - 5));
};
});
please any one help me....
In jQuery : $( window ).height();
and in pure js : window.innerHeight;
Atleast ive done godly with these. Then if you want the height off whole html document (includes scrolling) you can use this with jQuery : $( document ).height();
$(window).height();
$(window).width();
More info
http://api.jquery.com/height/
http://api.jquery.com/width/
If you think the scroll bar will be a problem you can try hiding them then taking your measurement
document.body.style.overflow = "hidden";
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
document.body.style.overflow = "";
Duplicate of Get the height and width of the browser viewport without scrollbars using jquery?

How Does This Background Image Work?

So This website:
http://www.atomicdust.com/
They have a background image on every page but when zooming, it doesn't change - ever. Not to mention how fast it loads. How is that possible to have content zoom without the background image? I could understand if it was a repeated image but this is not.
On that site it looks as though it's done by a script, as #rownage observes, but I've done it successfully in modern browsers using the (CSS3) "cover" property, i.e. background-size: cover; According to my notes (hurrah for comments!) this A List Apart article is where I got my information from.
On my (very much still-in-progress!) photo site, it looks like this at the moment. The background stays the same size when zooming in the browsers I've tried. Though it wouldn't surprise me if Internet Explorer couldn't cope with it.
As to how fast the images on that site load, the trick is simply a good choice of compressible image, well-compressed. The background that loaded when I visited their site is 1024x680 pixels, but because it's mostly black and white with large areas of plain colour, it compresses down to a pretty tiny 74KB.
It uses jQuery and this:
$.fn.bgResize = function(options) {
var defaults = {
imageWidth: 800,
imageHeight: 600
};
var options = $.extend(defaults, options);
var obj = $(this);
var initHtml = obj.html();
var windowHeight = $(window).height();
var windowWidth = $(window).width();
obj.height(windowHeight);
obj.width(windowWidth);
$('#work-wrapper').height(windowHeight);
$('#work-wrapper').width(windowWidth);
obj.html('<div id="inner-bg">'+initHtml+'</div>');
$('#inner-bg img').each(function(){
$(this).css({'display' : 'block', 'width' : '100%', 'height' : '100%'})
});
function doResize(){
var screenheight = $(window).height();
var screenwidth = $(window).width();
var imageheight = options.imageheight;
var imagewidth = options.imagewidth;
var ratio = imagewidth/imageheight;
var testwidth = screenheight * ratio;
var testheight = screenwidth / ratio;
obj.height(screenheight);
obj.width(screenwidth);
$('#work-wrapper').height(screenheight);
$('#work-wrapper').width(screenwidth);
if (testheight < screenheight){
obj.children('#inner-bg').width(testwidth);
obj.children('#inner-bg').height(testwidth/ratio);
var finalheight = Math.round(testwidth/ratio);
var finalwidth = testwidth;
var topoffset = (finalheight - screenheight)/2;
var leftoffset = (finalwidth - screenwidth)/2;
}
else if (testheight > screenheight){
obj.children('#inner-bg').height(testheight);
obj.children('#inner-bg').width(testheight * ratio);
var finalwidth = Math.round(testheight * ratio);
var finalheight = testheight;
var topoffset = (finalheight - screenheight)/2;
var leftoffset = (finalwidth - screenwidth)/2;
}
else {}
obj.children('#inner-bg').css("top", -topoffset);
obj.children('#inner-bg').css("left", -leftoffset);
}
doResize();
$(window).resize(function(){
doResize();
});
return this;
};

Snap draggable cloned element to <div> section

Can anyone check this sample code and can help me in fixing the clone for the dragged element and it should snap to the nearest white block when interchanging the positions
as without cloning it is snapping and I would like to how to do with a cloned element.
And if I am able to clone then i am unable to snap.So I will be grateful if anyone helps me out this issue.
Here is the sample code for snapping:
http://jsfiddle.net/kiran/qWPAH/7/
And this is how I did the cloning:
$(function() {
$(".draggable").draggable();
$(".item").droppable({
drop: function(event, ui) {
var $this = $(this);
$this.append(ui.draggable);
var width = $this.width();
var height = $this.height();
var cntrLeft = (width / 2) - (ui.draggable.width() / 2);
var cntrTop = (height / 2) - (ui.draggable.height() / 2);
ui.draggable.css({
left: cntrLeft + "px",
top: cntrTop + "px"
});
}
});
});
$(function() {
$(".draggable").draggable();
$(".item").droppable({
drop: function(event, ui) {
var $this = $(this);
$this.append(ui.draggable);
var width = $this.width();
var height = $this.height();
var cntrLeft = (width / 2) - (ui.draggable.width() / 2);
var cntrTop = (height / 2) - (ui.draggable.height() / 2);
ui.position.left = cntrLeft;
ui.position.top = cntrTop ;
}
});
});