複数行の文末で省略する

表示領域からはみ出した文章を省略したい時は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などで位置を調整しているとうまくいかない可能性が高いです。
 

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930