Dynamic font sizing - javascript

I have a div tag inside a TD element that must be under a certain size (in characaters). This is the code I have setup to shrink the font size to maintain the width.
I wondered if it would be possible to have it look at the max characters, 60 in this case, then for every 10 characters above 60, it would reduce to font size by .1em.
NOTE: I am using the numbers 10 and .1 as examples. I would of course play with the two numbers to achieve exactly what I need.
This the code I have right now: http://jsfiddle.net/Hn46H/31/.
A short version is:
var varCarrier1 = document.getElementById('DivCarrier1').innerHTML;
// Check Carrier 1 length to determine the font size.
if (varCarrier1.length >= 60) {
DIVCarrier1.style.fontSize = ".55em";
}
if (varCarrier1.length >= 97) {
DIVCarrier1.style.fontSize = ".45em";
}

Related

How to map a dynamic value to a range with a min and max

Within my IntersectionObserver I am storing the Y position of each target element:
const targetPosition = entry.target.getBoundingClientRect().y;
And when the target is in view, I am applying a translateX() synced with that changing Y position. It essentially works, but I am trying to take that dynamic Y position of the target and map it to a range defined by me so I can more easily control the translateX() (and in both left and right directions).
I thought it might be as simple as
const transformRange = Math.max(Math.min(targetPosition,90),0);
but I understand why that doesn't do what I want (see edit below).
I also have the following working...
function scale (number, inMin, inMax, outMin, outMax) {
return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
const num = targetPosition;
const transformRange = scale(num, -100, 1000, 0, 90);
but I don't want to be required to set a range for the source value as well (inMin and inMax) as that is changing.
The intent is to take that dynamic Y position* of the target element (*user scrolls, Y position decreases as the element approaches top of viewport) and convert that changing value to a range that I define.
EDIT
To provide more clarity, Math.max(Math.min(targetPosition,90),0) does not work because it is only limiting the stored Y position of the target element. I am trying to convert the entire scroll range of that element to an output range I define. For example, as the user scrolls, that element could be at say 658px as it enters the phone's viewport and will continue to decrease until it is out of view at the top of the viewport per the IntersectionObserver which would be somewhere around -103px (but obv will be a different set of numbers for different screens).
That 658px to -103px I need to convert/map/chain to a range I define such as 0-90. So 658 to -103 would be 1:1 with 0 to 90. That 0-90 I will then apply as the translateX().

Decrease element size by a factor then increase by same factor to original size

First of all, I know the root of my problem here is rounding in Javascript, I just don't know how to mitigate for it in this particular instance.
I have an element which I want to allow the user to decrease in height by clicking a 'zoom out' button. The decrease in height will be as a proportion of the element's current height - for example, if the element is 100px high, zooming out with the zoom factor set to 0.3 once would reduce its height to 70px. Zooming out again would reduce its height to 49px, and so on.
There is also a 'zoom in' button on the page. After zooming out, the user should be able to use the 'zoom in' button to increase the element's height again. Critically, each increment of the element's height on zooming back in should match the increments seen when zooming out. For example, if the element's heights on zooming out were: 100, 70, 49, 34.3, 24.01 then when zooming back in again, the element's heights would be 24.01, 34.3, 49, 70 100.
I've created a fiddle demonstrating this functionality here. You'll notice that if you run it and initially click the 'zoom out' button (labelled '-') seven times in a row, then click the 'zoom in' button seven times in a row, rather than returning the element's height to 100px, it ends up as 95.7142...px, and the other heights on zooming in don't match those on zooming out either.
$(function() {
var zoomAmount = 0.3;
var $el = $("#testDiv");
$("#zoomIn").click(function() {
var currentHeight = $el.height();
var newHeight = currentHeight * (1 / (1 - zoomAmount));
//newHeight = Math.round(newHeight * 10000 / 10000);
$el.height(newHeight);
$el.html(newHeight);
if (newHeight >= 100) {
$("#zoomIn").prop("disabled", true);
}
});
$("#zoomOut").click(function() {
$("#zoomIn").prop("disabled", false);
var currentHeight = $el.height();
var newHeight = currentHeight * (1 - zoomAmount);
//newHeight = Math.round(newHeight * 10000 / 10000);
$el.height(newHeight);
$el.html(newHeight);
});
});
I understand that this is caused by an accumulation of rounding in the calculation used to zoom out and then back in, but I don't know how to avoid it. You can see that I've commented out a couple of lines which were attempting to round the element's height to 2 decimal places each time, but they don't help. With them uncommented, the element's height ends up as 96px, which suggests to me that even though I'm rounding to 2dp before setting the value as the element's height, it's still aware of the full, unrounded number somehow and is using it when calculating the next new height.
The only solution I can think of is to store the values of the element's height in an array as I zoom in and out, so that when I zoom in the opposite direction the new height is looked up from the array rather than re-calculated, but that doesn't feel very elegant. Additionally, in my actual application there are dozens of the elements on page at a time, each with a different height, so I'd have to track the height of each one in its own array, which seems even less elegant.
Is there a way to calculate the height of the element as I zoom out and in (in practice you could zoom in then out too, but that requires more code so I simplified it) which will ensure that at each 'zoom increment' the height of the element is always the same?
Use an exponential function, and keep your zoomAmount as an integer (a better name would then be something like zoomLevel). So, instead of modifying a float which will accumulate rounding error, you can simply do zoomAmount++ or zoomAmount-- , and then get the real scale of your elements by elevating a floating-point number to zoomAmount (typically the numbere, you can then adjust your graphics with some constants as you see fit).
For example:
$el.height = base_height * pow(2.7182, zoomAmount)
Make sure you start with zoomAmount = 0, since e^0 = 1.
As no rounding errors exist with integers, you are guaranteed to have consistent zoom levels. Another advantage of this solution is that it has a low memory footprint, since you only need to save a single base height for every element of your document.
You could store the previous values and pop back on zoom in (fiddle).
$(function() {
var values = [];
$("#zoomIn").click(function() {
var newHeight = values.pop();
// ...
});
$("#zoomOut").click(function() {
var currentHeight = $el.height(); // this value gets stored
values.push(currentHeight);
// ...
});
});

Programmatically calculate width and height given area and ratio in JavaScript

OK, so I need to create an "auto fit" feature when a button is clicked.
Pretend you have an area, which is variable in size due to the responsive nature of the page.
This area can contain a number of rectangles (specified by how many logged in clients there are).
What I need to calculate, programmatically in JavaScript, is the appropriate width and height of each client in order to "fit" them all within that area.
var area = $('.client-container').width() * $('.client-container').height();
var noOfClients = 3; // normally calculated dynamically
// Ratio (1.25:1)
var r1 = 1.25;
var r2 = 1;
How can I work out what width and height I should apply to each client rectangle?
I assume you have full freedom to resize the N clients and that their natural aspect ratio can simply reflect that of the screen. You won't always be able to make all clients the same size without wasting space. Take the square root of N, round it down, and that's your number of rows R. It's also your number of columns except that X=N-R*R clients don't fit. X is less than R. Just choose the bottom X rows and divide them into R+1 columns instead.

Javascript - Get real letter width and height (without line-height)

In Adobe Illustrator (or Photoshop)
Letter A
Font-family: Arial
Font-Size: 396.55pt
Measures:
- Width: 93.8mm (266px)
- Height: 100.2mm (284px)
Measuring in Javascript:
- Width: 265px (matches, is correct)
- Height: 456px (NOT match, grabs the line height, and it is wrong)
How I can get the EXACT height of the letter?
// 6pt ---------------- 8px
// 96px --------------- 25.4mm
var arial_A_upper_pt = jQuery("#arial_A_upper_pt").html();
jQuery("#arial_A_upper").html("A");
jQuery("#arial_A_upper").css("font-size", arial_A_upper_pt + "px");
var arial_A_upper_width_on_px = jQuery("#arial_A_upper").width(); // on PX
// var arial_A_upper_width_on_mm = ((arial_A_upper_width_on_px * 25.4) / 96);
// arial_A_upper_width_on_mm = arial_A_upper_width_on_mm.toFixed(2);
jQuery("#arial_A_upper_width").html(arial_A_upper_width_on_px + "px");
var arial_A_upper_height_on_px = jQuery("#arial_A_upper").height(); // on PX
// var arial_A_upper_height_on_mm = ((arial_A_upper_height_on_px * 25.4) / 96);
// arial_A_upper_height_on_mm = arial_A_upper_height_on_mm.toFixed(2);
jQuery("#arial_A_upper_height").html(arial_A_upper_height_on_px + "px");
Example: http://jsfiddle.net/7Cunp/6/
I need this: http://www.javiscript.es/desarrollo/letrascortadas/img/letter_size.jpg
That is a question, that is not easily answered. I can pretty much guarantee that there isn't a property you can call to get the value.
First off, the data is embedded in the font-file, and is probably not accessible by JS (please correct me if i'm wrong). Second the value differs in just about every font-file.
However, you can use a little math to get a close approximation on the size.
The size of a letter is measured from the ascenders top to the descenders bottom. Also called the EM. This is both used horizontally and vertically. The size of the uppercase letters are sometimes generalized as being 2/3 of the EM.
So, since jQuery returns the height wrongly, but the width correctly.(the EM-size, not the actual width of the letter, if you measure it :D) I would do something like this:
var EM_height = jQuery("#arial_A_upper").width()
var uppercase_height = Math.floor(EM_height / 3 * 2)
JS isn't my strong side, so someone can probably tell, if there is a better way.
You can get a better value, if you know it will only be used on a specific font such as Arial.
For example. 72pt Arial measures 51.37pt on the uppercase A on my computer.
51,37/72 = 0,713472222 so that is the ratio you need to come up with. so 7/10 is probably a good suggestion.
Hope that helps a bit.
Actually you'll never get the exact results in browser as in Photoshop or Illustrator.
Every browser renders fonts in its own way. (http://css-tricks.com/font-rendering-differences-firefox-vs-ie-vs-safari).
In your case the most closer variant will be to put the line height the same as the font size.
jQuery("#arial_A_upper").css("line-height", arial_A_upper_pt + "px");
Because browser sets by default "normal" line height that is bigger than the font size so the height is much more bigger than it should be. But even if you'll put the line-height the same as font size you'll get the bigger result then it should be. (397px)

Set height of an element on multiples of a number?

Is there any way via jquery or javascript to make an element stretch its height to a certain set of numbers? I mean, as it accommodates more content, its height would only follow a pattern of numbers (multiples of a number).
Let's say in multiples of 100... a div's height as it extends taller would only be in this series -- 200px, 300px, 400px, etc. Hence, if it exceeds by just even 1 pixel off 200, it would automatically resize to 300.
It's hard to explain.
I need this because I made a vertically seamless pattern with torn edges and it would totally look perfect if it shows each tile completely.
I only know basic jquery and I don't have a bit of an idea on how to work this out.
My sincerest gratitude to whoever tends to my query!
var h = $('div').height();
$('div').height( Math.ceil(h/100) * 100 );
something like:
$('element').css({ height : (0|(targetHeight + 99) / 100) * 100 });
if you want it automatic:
$(function(){
var $elem = $('#element')
$elem.css({ height : (0|($(elem).height() + 99) / 100) * 100 });
});
This function will take the current height and the unit number you want it to snap to, rounding to the nearest multipleOf.
function snapHeight(height, multipleOf) {
return multipleOf * Math.round(height / multipleOf);
}
Examples:
snapHeight(930, 100); // returns 900
snapHeight(930, 50); // returns 950
$('#element').height(snapHeight($('#element').height(), 100)); // in jQuery

Categories

Resources