是否可以让 jQuery/javascript 检测字符串在哪里损坏(为了适应 CSS 宽度约束),以便在新行的开头之前插入 DOM 元素?
用jQuery检测换行符?
我想出了一种方法,但对于您的目的来说可能有点矫枉过正,所以请考虑到这一点。
您需要创建元素的副本,清空原始元素,然后将每个单词移回原始元素。如果高度在任何时候发生变化,则在该词之前会有一个换行符。使用 这样做会相当简单$(el).text()
,但如果内部可以有其他标签,而不仅仅是文本,则会变得更加复杂。我尝试在这个答案框中解释如何按节点分解它,但发现在 jsFiddle 中创建一个 jQuery 插件更容易。链接在这里:http : //jsfiddle.net/nathan/qkmse/(要点)。
它不会很好地处理浮动元素,并且还有其他一些情况它会倒下。如果您想要更多选择,或者它不能完全满足您的目的,或者您不确定如何应用它,请告诉我,我会尽力提供帮助。
这是一种方法。注意:如果不使用等宽字体,我看不到理想的解决方案。与字符相等使此任务更容易。
- 等宽字符
- 计算一个字符的大小
- 计算容器的大小
- 查找每行字符
- 查找行将中断的位置(即空格、破折号等)
- 获取所有破坏索引。
查看相关 html 的 jsfiddle。我还没有完成这个功能。在计算断裂指数时需要进行更多的检查。现在它正在使用 lastIndexOf(' '),但这忽略了下一个索引可能是一个空格或当前索引。此外,我不考虑其他换行字符。然而,这应该是一个很好的起点。
var text = $('#text').text(), // "lorem ipsum ... "
len = text.length, // total chars
width = $('#text').width(), // container width
span = $('<span />').append('a').appendTo('#sandbox'),
charWidth = span.width(), // add single character to span and test width
charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row
var breakingIndexes = [], // will contain indexes of all soft-breaks
gRowStart = 0, // global row start index
gRowEnd = charsPerRow;// global row end index
while(gRowEnd < len){
var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
breakingIndexes.push(gRowStart + rowEnd); // add breaking index to array
gRowStart = gRowStart + rowEnd + 1; // next start is the next char
gRowEnd = gRowStart + charsPerRow; // global end inxex is start + charsperrow
}
var text2 = $('#text2').text(); // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
start = breakingIndexes[i]; // update start
}
$('#text2').html(newText); // output with breaks
这是我的脚本,它需要文本,然后使每一行成为一个跨度
CSS:
margin: 0;
padding: 0;
}
.title{
width: 300px;
background-color: rgba(233,233,233,0.5);
line-height: 20px;
}
span{
color: white;
background-color: red;
display: inline-block;
font-size: 30px;
}
a{
text-decoration: none;
color: black;
}
html
<div class="title">
<a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
</div>
JS
$(function(){
$(".title").find("a").each(function(){
var $this = $(this);
var originalText = $this.text();
$this.empty();
var sections = [];
$.each( originalText.split(" "), function(){
var $span = $("<span>" + this + "</span>");
$this.append($span);
var index = $span.position().top;
if( sections[index] === undefined ){
sections[index] = "";
}
sections[index] += $span.text() + " ";
});
$this.empty();
for(var i = 0; i< sections.length; i++){
if( sections[i] !== undefined ){
var spanText = $.trim(sections[i]);
$this.append("<span>" + spanText + "</span>");
}
}
});
});
您必须包含 jQuery。
我不知道有任何内置 jQuery 的 javascript 函数可以做到这一点。但是,您可以自己完成,但是如果您有很多文本,它可能会很慢。
理论上,您可以确保将高度设置为自动,删除文本,然后逐字重新插入。在高度发生变化时,删除最后一个单词,然后插入 dom 元素。同样,如果有很多文本,这会很慢,更好的方法是不更改原始元素,而是在另一个可以隐藏的元素中执行,然后在完成时替换原始元素。这样,您的用户就不会看到内容消失然后一个字一个字地回来。
另一种方法是使用类似的原则,从一个高度为 auto 的相同大小的空元素开始,然后插入一个新字符和一个空格,直到你得到一个新行。从那里,您可以将其用作上述技术的近似值,或者您可以盲目地将每个字符串的长度相加,直到找到一个新行,同时考虑到 dom 元素的宽度。不过,这种技术对等宽字体效果更好,这只是将其用作近似值的地方。
也就是说,有一种使用画布测量文本的方法,但这可能是极端的。理论上它会是,创建一个画布元素,获取上下文,设置所有字体属性,然后使用该context.measureText()
方法。可以在此处找到它的使用示例。
不确定您的用例究竟是什么,但http://code.google.com/p/hyphenator/可能是您问题的解决方案,或者如果您深入研究 hyphenator.js 源代码,您可能能够找到代码你正在寻找。