我需要将用户输入的文本显示为固定大小的div.我想要的是自动调整字体大小,以便文本尽可能填充框.
所以 - 如果div是400px x 300px.如果有人输入ABC,那么它真的很大.如果他们输入一个段落,那么它将是一个很小的字体.
我可能想要从最大字体大小开始 - 可能是32px,虽然文本太大而不适合容器,但缩小字体大小直到它适合.
谢谢攻击.我想使用jQuery.
你指出了我正确的方向,这就是我最终的结果:
以下是该插件的链接:https://plugins.jquery.com/textfill/
以及指向源代码的链接: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 }); });
我的HTML是这样的
My Text Here
这是我的第一个jquery插件,所以它可能没有它应该的那么好.指针当然是受欢迎的.
我没有发现任何以前的解决方案由于性能不佳而足够,所以我自己创建了使用简单的数学而不是循环.应该在所有浏览器中都能正常工作.
根据这个性能测试案例,它比这里找到的其他解决方案快得多.
(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);
如果你想贡献我已经把这个添加到Gist.
尽管我喜欢这个答案的偶尔的赞成(谢谢!),但这并不是解决这个问题的最佳方法.请在这里查看一些其他精彩的答案,特别是那些找到没有循环的解决方案的答案.
不过,为了便于参考,这是我原来的答案:
DYNAMIC FONT
这是一个有类的版本:
DYNAMIC FONTANOTHER DYNAMIC FONTAND YET ANOTHER DYNAMIC FONT
大多数其他答案都使用循环来减小字体大小,直到它适合div为止,这非常慢,因为每次字体更改大小时页面都需要重新渲染元素.我最终不得不编写自己的算法,使其以允许我定期更新其内容而不冻结用户浏览器的方式执行.我添加了一些其他功能(旋转文本,添加填充)并将其打包为jQuery插件,您可以在以下位置获取:
https://github.com/DanielHoffmann/jquery-bigtext
简单地打电话
$("#text").bigText();
它很适合你的容器.
在这里看到它:
http://danielhoffmann.github.io/jquery-bigtext/
目前它有一些限制,div必须具有固定的高度和宽度,并且它不支持将文本包装成多行.
我将努力获得一个选项来设置最大字体大小.
编辑:我发现插件有一些问题,它除了标准版之外它不处理其他框模型而且div不能有边距或边框.我会努力的.
Edit2:我现在已经解决了这些问题和限制,并添加了更多选项.您可以设置最大字体大小,也可以选择使用宽度,高度或两者来限制字体大小.我将努力接受包装器元素中的max-width和max-height值.
Edit3:我已将插件更新到1.2.0版.代码和新选项(verticalAlign,horizontalAlign,textAlign)的主要清理以及对span标记内部元素的支持(如换行符或字体很棒的图标).
这是基于GeekyMonkey上面发布的内容,并进行了一些修改.
; (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. multipleelements. 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);
这是一个改进的循环方法,它使用二进制搜索以尽可能少的步骤找到适合父级的最大可能大小(这比步进固定字体大小更快,更准确).代码也以多种方式优化以提高性能.
默认情况下,将执行10个二进制搜索步骤,这将达到最佳大小的0.1%.您可以将numIter设置为某个值N,以获得最佳大小的1/2 ^ N.
使用CSS选择器调用它,例如: 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); } }); };
我已经为AngularJS创建了一个指令 - 受到GeekyMonkey的回答的启发,但没有jQuery依赖.
演示: http ://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p =preview
标记
指示
app.directive('fittext', function() { return { scope: { minFontSize: '@', maxFontSize: '@', text: '=' }, restrict: 'C', transclude: true, template: '', 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(); }); } }; });
我从Marcus Ekwall上面分享了上面的脚本:https://gist.github.com/3945316并根据我的喜好调整它,它现在在窗口调整大小时触发,这样孩子总是适合它的容器.我已粘贴下面的脚本作为参考.
(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);
这是我对OP答案的修改。
简而言之,许多尝试优化此功能的人都抱怨正在使用循环。是的,尽管循环可能很慢,但其他方法可能不准确。
因此,我的方法使用二进制搜索来找到最佳字体大小:
$.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);
这也允许元素指定最小和最大字体:
Text that will fill the container, to the best of its abilities, and it will never have overflow.
此外,该算法是无单位的。您可以指定em
,rem
,%
等,它将使用它的最终结果。
这是小提琴:https : //jsfiddle.net/fkhqhnqe/1/