Mathematical Formula for working out font size - math

Can anyone help me I'm not having much luck
I want to try workout the ideal fontsize for my text based on the width of an image it's overlaying and the amount of characters in the text string.
could anyone help me with the formula for this.
I got it semi-working but only due to the Infinite monkey theorem!
// gets text1 count
$charcount = strlen($line1);
// gets text1 size from count
$newsize = ($width / floor($charcount));
$add = ( 20 % $newsize );
$newsize = ($newsize + $add);
// Changes Font Size
$text1->setFontSize( $newsize );

I use something like this based on the width or height of your image:
resize_font = function () {
// then play around with the denominator until the font is the size you want
var fontSize = parseInt($("#your_image_div").width()) / 2 + "%";
//then apply that to your css for that text div element
$(".your_text_class").css('font-size', fontsize);
};
// then hook it to whatever event you want to
$(document).ready(resize);
Hope this helps. This trick is handy for making elements resize in relation to the veiwport too. Hope it helps.

Related

How would I make a color relative to images in the background?

For example, if you go to Twitter and click on an image, you can see they have a nice color that is close to what you see on the image. I tried looking up ways to achieve this as well as trying to figure it out on my own but no luck. I'm not sure if there's a color: relative property or not.
if you want to use the a colour that exists in your image and set it as a background colour you need to use the canvas element in the following manner:
HTML (this is your image)
<img src="multicolour.jpg" id="mainImage">
JS
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let color = context.getImageData(randomX, randomY, 1, 1).data
// use the data to dynamically add a background color extracted from your image
body[0].style.backgroundColor = `rgb(${color[0]},${color[1]},${color[2]})`
}
here is a gif of the code working... hopefully this helps
UPDATE
Here is the code to select two random points and create a css3 background gradient
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let colorOne = context.getImageData(randomX, randomY, 1, 1).data
// THE SAME TO OBTAIN ANOTHER pixel data
let randomX2 = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY2 = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
let colorTwo = context.getImageData(randomX2, randomY2, 1, 1).data
// use the data to dynamically add a background color extracted from your image
//body[0].style.backgroundColor = `rgb(${allColors[0]},${allColors[1]},${allColors[2]})`
body[0].style.backgroundImage = `linear-gradient(to right, rgb(${colorOne[0]},${colorOne[1]},${colorOne[2]}),rgb(${colorTwo[0]},${colorTwo[1]},${colorTwo[2]}))`;
}
The following are your options.
1. Use an svg.
As far as I know there's no way to have javascript figure out what color is being used in a png and set it as a background color. But you can work the other way around. You can have javascript set the background color and an svg image to be the same color.
See this stackoverflow answer to learn more about modifying svgs with javascript.
2. Use a custom font.
There are fonts out there that provide a bunch of icons instead of letters, you can also create your own font if you feel so inclined to do so. With css you just have to set the font-color of that icon to be the same as the background-color of your other element.
Font Awesome provides a bunch of useful custom icons. If the image you need to use happens to be similar to one of theirs, you can just go with them.
3. Use canvas
If you really want to spend the time to code it up you can use a html <canvas/> element and put the image into it. From there you can inspect certain details about the image like its color, then apply that color to other elements. I won't go into too much detail about using this method as it seems like it's probably overkill for what you're trying to do, but you can read up more about from this stackoverflow answer.
4. Just live with it.
Not a fun solution, but this is usually the option I go with. You simply have to hard-code the color of the image into your css and live with it. If you ever need to modify the color of the image, you have to remember to update your css also.

Twitter bootstrap carousel with pictures that are not uniform

Let me start with i am sorry for the long post.
I'm attempting to use the bootstrap carousel and unfortunately the pictures i have been given are NOT uniform. for example some are 100x200, doe are 150x100, etc. The aspect ratios are different, letter vs landscape. Ive attempted a number of things, including the using the following helper function on load of each of my images in the Carousel:
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
result.targetleft = Math.floor((targetwidth - result.width) / 2);
result.targettop = Math.floor((targetheight - result.height) / 2);
return result;
}
function OnImageLoad(evt) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).prop('naturalWidth');
var h = $(img).prop('naturalHeight');
//var tw = $(img).parent().width();
//var th = $(img).parent().height();
var tw = $(img).parent().parent().parent().parent().width();
var th = $(img).parent().parent().parent().parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, true);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
and using the following for each of my images for the carousel
<img src="~/Images/Img1_Tall.jpg" alt="Tall" id="firstImage" onload="OnImageLoad(event);" />
and for the FIRST image in the carousel it works great, but each one after that they seem to just end up their natural size and are horizontally centered but are just against the top boarder of the carousel.
I've even changed the "onload" to pass the values of the length and width of the image but that didn't work either, in debug it seems only the first image kicks off the "onload" event.
the effect i am going for is if the ratio of the container is 3:4 and the ratio of the image is 1:2, the image stretch to meet the left and right edges and would center vertically and have letter box above and below, but the container does not change so that the navigation buttons of the carousel do not move. if the image is 2:1, the image would stretch to meet the top and bottom centered horizontally with letterboxes on the right and left, again keeping the navigation buttons unmoved.
any help would be appreciated... including:
what you are trying to do is crazy
do you want to do something like http://jsbin.com/zotelasa/1 . With that code I can get the active items w,h or any other variables you used in your code to run scale image. Because of parent.parent codes it applies to carousels main divs but you can set your own container.
The quick and dirty solution would be to resize the images using an image editor, and save the properly-sized images to a folder named eg carousel_images. Then whenever you get new content you simply run the image through your editor. With a carousel you're most likely dealing with a number of images in the several to dozens range and not hundreds or thousands.
A more complicated solution is explain to your image provider that you need everything one size. The images aren't going to look right if you're stretching and skewing them on the fly, and you can show them an image with the aspect ratios wrong to explain what you mean.
Finally, as a technical solution, I would try to find out why your image resizer is only being run on the first image. From the sound of it, other images just aren't being run through your function. I think that the technical solution should be a last resort in this case because, like I said, the end results are just not going to be as good. You should at a minimum, if possible, handle each image by hand to make sure the result is adequate.
...And the answer is a little long too...
• I assume that the width’s image’s parent is a constant, and while you don’t change the width’s viewport that must remain.
A-. Get the width’s image’s parent…
(Because the id attribute I took the grand parent’s parameter, that is (must be) the same than the parent’s one).
B-. With the below value deduce the height’s image’s parent, including the preferred ratio (in this case 16x9…
C-. … And with this, set the images’ parents height collection (all the elements with class=”item”).
D-. In order to conserve your carousel’s responsive characteristic, you must add the $F_getAdjustImagesParents function to the window resize event.
E-. Set the slide’s images position to absolute (Note: That must be via JQuery because if you do it in Css the bootstrap carousel will not display correctly. I did it with a new class for the images ('myCarouselImgs').
• Bootstrap carousel’s event 'slide.bs.carousel' and 'slid.bs.carousel'.
As you know, after the ‘click’ event, the slide.bs.carousel event is one of the firsts events that imply the change from the present slide to the next one; while the 'slid.bs.carousel' one is the end of the process.
F-. In the first one (slide.bs.carousel event), using the ‘relatedTarget’ variable of the Bootstrap’s plugin, the item’s id attribute and a item’s data attribute, get the number of the next item (ensure that these last ones -id attribute and data attribute- be present).
G-. In the second one, 'slid.bs.carousel', get the image’s size. For that you need to identify the implied image. I gave an id to each one. With this and the value obtained in previus step, it can do it.
H-. Well, now you already have the four values required for the ScaleImage function. You can call it…
I-. … And apply the result with some effect
var $parentImgW = ' '
var $parentImgH = ' ';
var $myCarousel = $('#myCarousel')
var $carouseItems = $('.item');
function $F_getAdjustImagesParents(){
$parentImgW = $myCarousel.width(); // A
$parentImgH = ($parentImgW*9)/16; // B
$carouseItems.height($parentImgH+'px').css('max-height',$parentImgH+'px'); //C
console.log('$parentImgW ====> '+$parentImgW);
console.log('$parentImgH ====> '+$parentImgH)
};
$F_getAdjustImagesParents();
$(window).on('resize',function(){ // D
$F_getAdjustImagesParents();
});
$('.myCarouselImgs').css('position','absolute'); // E
$myCarousel.on('slide.bs.carousel', function(event) {// The slide’s change process starts
var $slideNum = $("#"+event.relatedTarget.id).data('slide_num'); // F
console.log('$lideNum ====> '+$slideNum)
$myCarousel.on('slid.bs.carousel', function(event) {//The slide’s change process ends
var $imgW = $('#myCarouselSlideImage'+$slideNum).width(); //G
var $imgH = $('#myCarouselSlideImage'+$slideNum).height(); //G
console.log('$imgW ====> '+$imgW);
console.log('$imgH ====> '+$imgH);
var $result = '';
$result = ScaleImage($imgW, $imgH, $parentImgW, $parentImgH, true); //H
console.log('$result.width ====> '+$result.width);
console.log('$result.height ====> '+$result.height);
console.log('$result.targetleft ====> '+$result.targetleft);
console.log('$result.targettop ====> '+$result.targettop);
$('#myCarouselSlideImage'+$slideNum).animate({ // I
width:$result.width+'px',
height:$result.height+'px',
left:$result.targetleft+'px',
top:$result.targettop+'px' },
300);
});
});
See it runnig at https://jsfiddle.net/nd90r1ht/57/ or at https://jsfiddle.net/omarlin25/nd90r1ht/59/

How can I autoscale the font size to fit the contents of a div?

I have a div with some text:
<div style="white-space:nowrap;overflow:none;width:50px;">
With some text in it
</div>
How can I scale the font size of the text so all of the text is visible?
Contrary-wise. You could wrap the text in an interior DIV, measure its width with JavaScript. Test if that width is wider than the parent DIV. Get the current font size, and incrementally move it down 1px at a time until inner DIV's width is less than or equal to the outer DIV's width.
I've been doing something like this, to set the text scale relative to the parent (or window) width / height. You can avoid jQuery by using offsetWidth and offsetHeight instead of width.
var setBodyScale = function () {
var scaleSource = $(window).width(), // could be any div
scaleFactor = 0.055,
maxScale = 500,
minScale = 75; //Tweak these values to taste
var fontSize = (scaleSource * scaleFactor) - 8; //Multiply the width of the body by the scaling factor:
if (fontSize > maxScale) fontSize = maxScale;
if (fontSize < minScale) fontSize = minScale; //Enforce the minimum and maximums
$('html').css('font-size', fontSize + '%'); // or em
}
Short Answer: You don't.
You would have to try a size, render it, see if it fits, try another size, render it see if it fits, etc. Then you have to handle the case where the calculated font size is so small no one can read the text.
There are other options, if the text doesn't fit, add an ellipsis (...) to the end of the text, when you mouse over it, the div could expand, you could use a popup window or tooltip with the full text, or put the full text in a larger area of the screen.
Find another way.
Came across this JQuery plugin in my quest to find the same.
Github
Demo
Also came across this Jquery script when I was looking for the same thing. It has the added benefit over the others, as far as I quickly tell, is that it also adjusts for height as well as width.
Comes from here: http://www.metaltoad.com/blog/resizing-text-fit-container
function adjustHeights(elem) {
var fontstep = 2;
if ($(elem).height()>$(elem).parent().height() || $(elem).width()>$(elem).parent().width()) {
$(elem).css('font-size',(($(elem).css('font-size').substr(0,2)-fontstep)) + 'px').css('line-height',(($(elem).css('font-size').substr(0,2))) + 'px');
adjustHeights(elem);
}
}

Calculating Text Width In ActionScript And Flex

I'm trying to calculate how WIDE to make my button, based on the text that it will contain, and when I try to google for how to calcuate something as simplistic as the WIDTH OF SOME TEXT, I go cross-eyed just trying to wade through apparently nonsensical esoteric counter-intuitive voodoo. Can anyone out there help simplify for me how I would write a function like this:
public function HowWideWouldThisTextBeIfItWereInThisButton(Text:String,Container:Button):int {
...
}
Thanks in advance.
So long as you're in a UIComponent, you can use the measureText function.
public function howWideWouldThisTextBeIfItWereInThisButton(text:String,container:Button):int {
var lineMetrics:TextLineMetrics = container.measureText(text);
return lineMetrics.width;
}
That being said, the flex button component should automatically size to the width of the text, if you don't set a width on it. That way if you need the text width, you can just call use the textWidth property.
This works any format, size, font type. Don't forget properties "autoSize" and "wordWrap"!
var tf:TextField = new TextField();
addChild(tf);
tf.autoSize = TextFieldAutoSize.LEFT;
tf.wordWrap = false;
tf.text = "Whatever here";
tf.width = tf.textWidth + 4; // add 2 pixels-gutters left & right
Your button will need to be "tf.width" wide...
Here's how you do it in Spark:
I've modified - simplified - his example a bit here:
var textMetrics:TextLineMetrics = label.measureText( label.text );
var textWidth:int = textMetrics.width;
Here's a way that works also:
var tempText:Text = new Text();
tempText.regenerateStyleCache(false);
var textWidth:int = tempText.measureText(*yourstring*).width;
as I think, textField.textWidth construction works fine... until you change the font size.
It seems it calculates width based on 12px font.
So, if you have embedded font and global styling you can try fast solution:
var realWidth = myLabel.textField.textWidth * (fontSize / 12);
I've tried this on long and short strings and the result is correct.
Joshua, it really helps to be clear. Are you talking TextField, MX Label, Spark Label, RichText, etc? Different text components use different text engines, such as FTE and TLF and may have different solutions. I certainly wish Adobe had a good set of utilities or sample code which could predict what the size of font rendered onto the controls would be, before you actually do it. But, the good news is that in certain cases - like, a good old fashioned TextField, you can predict this pretty well. You just make a TextField, set it's textFormat field, auto size method and the text. You should be able to get it's size before adding it anywhere. I don't remember what the order was, but, I remember the order you set those properties matters. If you can't figure out how to do it, I can provide a code example. Now, for the new, "improved", components such as Spark Labels - I'll be buggered if I can find a damn way... spent a number of hours on this and haven't found a way.. or someone who knows a way :P.
Following up my comment on quoo's answer, here's the code for same purpose, but just grabbing the width out of a TextField, using TextLineMetrics as well:
public function mtxtWidth(container:TextField):int {
var lineMetrics:TextLineMetrics = container.getLineMetrics(0);
return lineMetrics.width;
}
Sounds like you could use textWidth

How to Auto-resize font size to fit text box height / width?

I am trying to have text automatically size its font to fill an entire text component.
My current approach is to set font size as a function of the number of text characters and the text components height and width but I can't find the right coefficients to make this work nicely.
Is there a simpler or more elegant way?
Does truncateToFit work on Text? I read somewhere that it doesn't work well.
Edit: I forgot to mention that I would like it to scale beyond the max font size (which is 127 i believe). How is this done? scaleX?
AS3 sample function. You should call it anytime your TextField's content changes
function Autosize(txt:TextField):void
{
//You set this according to your TextField's dimensions
var maxTextWidth:int = 145;
var maxTextHeight:int = 30;
var f:TextFormat = txt.getTextFormat();
//decrease font size until the text fits
while (txt.textWidth > maxTextWidth || txt.textHeight > maxTextHeight) {
f.size = int(f.size) - 1;
txt.setTextFormat(f);
}
}

Resources