表示領域からはみ出した文章を省略したい時はtext-overflowが使えますが、1行しか対応していません。
JavaScriptで複数行の場合でも省略できないかと思い、試してみました。
サンプルコード
対応方法として、以下の2案を考えました。
- 表示領域の高さから行数を調べる
- 各文字のoffset().topから調べる
今回は2番目の「各文字のoffset().topから調べる」方法で実装してみます。
HTML
data-omitで省略した行数を指定するようにします。
<p>■2行</p> <p data-omit="2">各種メディアで提供されるサブカルチャーの一つ。「文化芸術振興基本法」ではメディア芸術、関連法律の「コンテンツの創造、保護及び活用の促進に関する法律」ではコンテンツの一つと定義されており、どちらの法律でもアニメと略されてはおらず、アニメーションと正式表記されている。別定義として、多角的芸術分類観点において、美術(映像を含まない)、映像、音楽、文学、芸能の総合芸術とされるときもある。テレビ放送用の1話30分枠の連続作品(詳細はテレビアニメの標準フォーマットを参照)が主流で、劇場用やDVDなどでの単発作品の比率は低い。取り上げる題材は幅広く、多種多様なものが使用されている(詳細は後述、「Category:アニメのジャンル」も参照)。単に「アニメ」という場合は、セルアニメーション(セルアニメ)のことを指していることが多い。本項では、主に日本で製作された商業用セルアニメーションについて解説する。</p> <hr /> <p>■3行</p> <p data-omit="3">各種メディアで提供されるサブカルチャーの一つ。「文化芸術振興基本法」ではメディア芸術、関連法律の「コンテンツの創造、保護及び活用の促進に関する法律」ではコンテンツの一つと定義されており、どちらの法律でもアニメと略されてはおらず、アニメーションと正式表記されている。別定義として、多角的芸術分類観点において、美術(映像を含まない)、映像、音楽、文学、芸能の総合芸術とされるときもある。テレビ放送用の1話30分枠の連続作品(詳細はテレビアニメの標準フォーマットを参照)が主流で、劇場用やDVDなどでの単発作品の比率は低い。取り上げる題材は幅広く、多種多様なものが使用されている(詳細は後述、「Category:アニメのジャンル」も参照)。単に「アニメ」という場合は、セルアニメーション(セルアニメ)のことを指していることが多い。本項では、主に日本で製作された商業用セルアニメーションについて解説する。</p> <hr /> <p>■4行</p> <p data-omit="4">各種メディアで提供されるサブカルチャーの一つ。「文化芸術振興基本法」ではメディア芸術、関連法律の「コンテンツの創造、保護及び活用の促進に関する法律」ではコンテンツの一つと定義されており、どちらの法律でもアニメと略されてはおらず、アニメーションと正式表記されている。別定義として、多角的芸術分類観点において、美術(映像を含まない)、映像、音楽、文学、芸能の総合芸術とされるときもある。テレビ放送用の1話30分枠の連続作品(詳細はテレビアニメの標準フォーマットを参照)が主流で、劇場用やDVDなどでの単発作品の比率は低い。取り上げる題材は幅広く、多種多様なものが使用されている(詳細は後述、「Category:アニメのジャンル」も参照)。単に「アニメ」という場合は、セルアニメーション(セルアニメ)のことを指していることが多い。本項では、主に日本で製作された商業用セルアニメーションについて解説する。</p> <hr />
JavaScript
1文字ずつspanで括って、省略時は非表示にします。
$(function() {
var omitMark = '…'; // 省略に使うマーク(1文字でない場合はコードの修正が必要)
// 省略したい要素のテキストを加工
for (var i = 0; i < $('[data-omit]').length; i++) {
stringSplit($('[data-omit]').eq(i));
}
// 1文字ずつspanで括る関数
function stringSplit(element) {
var splitArr = element.text().split('');
var joinString = '';
for (var i = 0; i < splitArr.length; i++) {
joinString += '<span>' + splitArr[i] + '</span>';
}
joinString += '<span class="omit-mark">…</span>';
element.html(joinString);
element.children('.omit-mark').hide();
}
// 省略チェック
for (var i = 0; i < $('[data-omit]').length; i++) {
omitCheck($('[data-omit]').eq(i));
}
var resizeTimer = null;
$(window).on('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
for (var i = 0; i < $('[data-omit]').length; i++) {
omitCheck($('[data-omit]').eq(i));
}
}, 200);
});
// 省略チェックの関数
function omitCheck(element) {
var omitLine = element.data('omit');
var thisSpan = element.children('span');
var lineTop = thisSpan.eq(0).offset().top; // 一行目の文字位置取得
var lineCount = 0; // 現在の行数
var omitCount; // 何文字目で省略するか
// data-omitの値が0以下の場合は何もしない
if(omitLine <= 0) {
return;
}
// 非表示にしている文字をいったん表示して、何文字目からを非表示にするかを調べる
thisSpan.show();
for (var i = 0; i < thisSpan.length - 1; i++) {
if(thisSpan.eq(i).offset().top > lineTop) {
lineTop = thisSpan.eq(i).offset().top;
lineCount++;
}
// 省略行まで来たとき
if(lineCount >= omitLine) {
omitCount = i - 2;
break;
}
// 指定行数内に収まりそうなときは省略マーク非表示
if(i >= thisSpan.length - 2) {
element.children('.omit-mark').hide();
return;
}
}
// 該当する文字を非表示にする
for (var i = omitCount; i < thisSpan.length - 1; i++) {
thisSpan.eq(i).hide();
}
}
});
注意点として、省略する要素内のテキストを1文字ずつspanで括るので、要素内はプレーンなテキスト(spanタグなどを使っていない)である必要があります。
あとは、offset().topで各文字の位置を調べるようにしているので、一部だけ文字サイズを変更していたり、positionなどで位置を調整しているとうまくいかない可能性が高いです。
コメントが承認されるまで時間がかかります。