너비와 높이가 고정 된 줄임표가 추가 된 크로스 브라우저 멀티 라인 텍스트 오버 플로우``
이해하기 쉽도록이 질문에 대한 이미지를 만들었습니다.
<div>
고정 너비와 여러 줄로 줄임표를 만들 수 있습니까?
여기저기서 jQuery 플러그인을 시도했지만 원하는 플러그인을 찾을 수 없습니다. 어떤 추천? 아이디어?
간단한 기본 아이디어입니다.
다음 마크 업으로 테스트하고있었습니다.
<div id="fos">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin nisi ligula, dapibus a volutpat sit amet, mattis et dui. Nunc porttitor accumsan orci id luctus. Phasellus ipsum metus, tincidunt non rhoncus id, dictum a lectus. Nam sed ipsum a lacus sodales eleifend. Vestibulum lorem felis, rhoncus elementum vestibulum eget, dictum ut velit. Nullam venenatis, elit in suscipit imperdiet, orci purus posuere mauris, quis adipiscing ipsum urna ac quam.</p>
</div>
그리고 CSS :
#fos { width: 300px; height: 190px; overflow: hidden; }
#fos p { padding: 10px; margin: 0; }
이 jQuery를 적용하면 원하는 결과를 얻을 수 있습니다.
var $p = $('#fos p');
var divh = $('#fos').height();
while ($p.outerHeight() > divh) {
$p.text(function (index, text) {
return text.replace(/\W*\s(\S)*$/, '...');
});
}
원하는 크기에 도달 할 때까지 텍스트의 마지막 단어를 반복적으로 제거하려고 시도합니다. 오버플로로 인해 : hidden; 프로세스는 보이지 않으며 JS가 꺼져도 결과는 "시각적으로 정확"합니다 (물론 "..."없이).
이것을 서버 측에서 적절한 잘림과 결합하면 (작은 오버 헤드 만 남음) 빨리 실행됩니다. :).
다시 말하지만 이것은 완벽한 솔루션이 아니라 아이디어 일뿐입니다.
업데이트 : jsFiddle 데모가 추가되었습니다 .
jQuery.dotdotdot 플러그인을 사용해보십시오 .
$(".ellipsis").dotdotdot();
"라인 클램핑"을위한 자바 스크립트 라이브러리
"라인 클램핑"은 "다중 라인 블록의 줄임표"또는 "수직 줄임표"라고도합니다.
github.com/BeSite/jQuery.dotdotdot
- 장점 : 2.5Kb (최소화 및 gzipped), 리포지토리에서 큰 활동은 없지만 나쁘지 않습니다.
- 단점 : jQuery 의존성, 상업적 사용을 위해 지불 됨 (CC-BY-NC-4.0 라이센스)
- 내 2 센트 : stackoverflow.com/questions/25187774/dotdotdot-jquery/29118739#29118739
- 유용한 stackoverflow.com/questions/19015945/jquery-dotdotdot-expand-truncate-text-onclick
- 유용한 gist.github.com/chiragparekh/c7e33dc749ed25544bde
github.com/josephschmitt/Clamp.js
- 단점 : 코드 저장소가 거의 활성화되지 않음
- 유익한 reusablebits.com/post/2980974411/clamp-js-v0-2- 설명 및 성능
내가 아직 조사하지 않은 몇 가지 더 있습니다 :
- github.com/ftlabs/ftellipsis
- github.com/micjamking/Succinct
- github.com/pvdspek/jquery.autoellipsis 및 pvdspek.github.io/jquery.autoellipsis
- github.com/rviscomi/trunk8
- github.com/dobiatowski/jQuery.FastEllipsis
- github.com/theproductguy/ThreeDots
- github.com/tbasse/jquery-truncate
- github.com/kbwood/more
라인 클램핑을위한 CSS 솔루션
CSS 솔루션이 있지만 -webkit-line-clamp
브라우저 지원이 좋지 않은 가장 간단한 용도 가 있습니다 . jsfiddle.net/AdrienBe/jthu55v7/에서 라이브 데모보기
많은 사람들이 CSS 만 사용하여 이런 일이 일어나도록 노력했습니다. 그것에 관한 기사와 질문을보십시오 :
- css-tricks.com/line-clampin : 캠린 라인에 별 5 개 기사
- mobify.com/blog/multiline-ellipsis-in-pure-css : CSS 전용
- cssmojo.com/line-clamp_for_non_webkit-based_browsers/ : 웹킷이 아닌 브라우저에서 "mimic"-webkit-line-clamp
- CSS에서 오버플로 된 여러 줄 블록에 "..."을 사용하십시오.
- 너비와 높이가 고정 된`<div>`안에 줄임표가 추가 된 브라우저 간 다중 행 텍스트 오버 플로우
- div의 처음 몇 줄만 표시하는 방법 (클램핑)?
- 단락의 jquery 제한 줄과 끝에 세 개의 마침표를 적용합니다
- CSS를 사용하여 텍스트 길이를 n 줄로 제한
내가 추천하는 것
간단하게 유지하십시오. 이 기능에 많은 시간을 할애하지 않는 한 가장 단순하고 테스트 된 솔루션 : 간단한 CSS 또는 잘 테스트 된 자바 스크립트 라이브러리로 이동하십시오.
공상 / 복잡한 / 높은 주문형을 찾으십시오.
다른 사람들이하는 일
에어 비앤비처럼 희미 해지는 것이 좋은 해결책 일 수 있습니다. 아마도 기본 jQuery와 결합 된 기본 CSS 일 것입니다. 실제로 CSSTricks 의이 솔루션 과 매우 유사합니다.
아, 그리고 당신이 디자인 영감을 찾으면 :
- 2009 년부터 smashingmagazine.com/2009/07/designing-read-more-and-continue-reading-links/ ...
- Dribbble은 아마도 흥미로운 디자인을 가지고 있습니다 ... 검색 또는 태그를 통해 수집 할 수있는 방법을 찾지 못했습니다. 관련 링크를 자유롭게 공유하십시오
HTML에는 그러한 기능이 없으므로 매우 실망 스럽습니다.
이 문제를 해결하기 위해 라이브러리 를 개발했습니다 .
- 여러 줄로 된 텍스트 오버플로 : 줄임표
- 이를 지원하지 않는 기술이 포함 된 여러 줄 텍스트 : SVG, Canvas 등
- 예를 들어 SVG 텍스트, HTML 렌더링 및 PDF 내보내기에서 정확히 동일한 줄 바꿈이 있어야합니다.
스크린 샷, 튜토리얼 및 dowload 링크는 내 사이트 를 확인하십시오 .
bažmegakapa의 솔루션을 기반으로 한 순수 JS 솔루션 및 요소의 행보다 작은 높이 / 최대 높이를 제공하려는 사람들을 설명하기 위해 정리하십시오.
var truncationEl = document.getElementById('truncation-test');
function calculateTruncation(el) {
var text;
while(el.clientHeight < el.scrollHeight) {
text = el.innerHTML.trim();
if(text.split(' ').length <= 1) {
break;
}
el.innerHTML = text.replace(/\W*\s(\S)*$/, '...');
}
}
calculateTruncation(truncationEl);
잘 작동하는 솔루션이 있지만 대신 타원을 사용하여 그라디언트를 사용합니다. 장점은 JavaScript 계산을 수행 할 필요가 없으며 테이블 셀을 포함하여 가변 너비 컨테이너에서 작동한다는 것입니다. 두 개의 추가 div를 사용하지만 구현하기가 매우 쉽습니다.
http://salzerdesign.com/blog/?p=453
편집 : 죄송합니다. 링크가 충분하지 않다는 것을 몰랐습니다. 해결책은 텍스트 주위에 div를 배치하고 div 스타일을 지정하여 오버플로를 제어하는 것입니다. div 안에 CSS 또는 이미지 (이전 IE의 경우)를 사용하여 만들 수있는 "페이드"그라디언트로 다른 div를 넣으십시오. 그라디언트는 표 셀의 투명에서 배경색으로 진행되며 줄임표보다 약간 넓습니다. 텍스트가 길고 넘치면 텍스트는 "fade"div 아래로 가고 "faded out"으로 보입니다. 텍스트가 짧으면 페이드가 보이지 않으므로 아무런 문제가 없습니다. 컨테이너의 높이를 텍스트 선 높이의 배수로 설정하여 하나 또는 여러 개의 선이 보이도록 두 컨테이너를 조정할 수 있습니다. "fade"div는 마지막 줄만 덮을 수 있습니다.
이를 달성하는 순수한 CSS 방법은 다음과 같습니다. http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/
요약은 다음과 같습니다.
<html>
<head>
<style>
html, body, p { margin: 0; padding: 0; font-family: sans-serif;}
.ellipsis {
overflow: hidden;
height: 200px;
line-height: 25px;
margin: 20px;
border: 5px solid #AAA; }
.ellipsis:before {
content:"";
float: left;
width: 5px; height: 200px; }
.ellipsis > *:first-child {
float: right;
width: 100%;
margin-left: -5px; }
.ellipsis:after {
content: "\02026";
box-sizing: content-box;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
float: right; position: relative;
top: -25px; left: 100%;
width: 3em; margin-left: -3em;
padding-right: 5px;
text-align: right;
background: -webkit-gradient(linear, left top, right top,
from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white); }
</style>
</head>
<body>
<div class="ellipsis">
<div>
<p>Call me Ishmael.....</p>
</div>
</div>
</body>
</html>
핀치에 사용할 수있는 바닐라 JavaScript 솔루션은 다음과 같습니다.
// @param 1 = element containing text to truncate
// @param 2 = the maximum number of lines to show
function limitLines(el, nLines) {
var nHeight,
el2 = el.cloneNode(true);
// Create clone to determine line height
el2.style.position = 'absolute';
el2.style.top = '0';
el2.style.width = '10%';
el2.style.overflow = 'hidden';
el2.style.visibility = 'hidden';
el2.style.whiteSpace = 'nowrap';
el.parentNode.appendChild(el2);
nHeight = (el2.clientHeight+2)*nLines; // Add 2 pixels of slack
// Clean up
el.parentNode.removeChild(el2);
el2 = null;
// Truncate until desired nLines reached
if (el.clientHeight > nHeight) {
var i = 0,
imax = nLines * 35;
while (el.clientHeight > nHeight) {
el.innerHTML = el.textContent.slice(0, -2) + '…';
++i;
// Prevent infinite loop in "print" media query caused by
// Bootstrap 3 CSS: a[href]:after { content:" (" attr(href) ")"; }
if (i===imax) break;
}
}
}
limitLines(document.getElementById('target'), 7);
#test {
width: 320px;
font-size: 18px;
}
<div id="test">
<p>Paragraph 1</p>
<p id="target">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Paragraph 3</p>
</div>
아래의 코드 펜에서 놀 수 있습니다. CSS 패널에서 글꼴 크기를 변경하고 HTML 패널에서 약간의 수정 (예 : 공간을 추가)하여 결과를 업데이트하십시오. 글꼴 크기에 관계없이 가운데 단락은 항상 limitLines ()에 전달 된 두 번째 매개 변수의 줄 수로 잘 려야합니다.
코덱 : http://codepen.io/thdoan/pen/BoXbEK
질문에 대한 정확한 대답은 아니지만 매우 유사한 작업을 시도 할 때이 페이지를 보았지만 간단한 생략 대신 "더보기"에 대한 링크를 추가하려고합니다. 컨테이너에 넘친 텍스트에 "추가"링크를 추가하는 jQuery 함수입니다. 개인적으로 나는 이것을 Bootstrap과 함께 사용하고 있지만 물론 작동하지 않습니다.
사용하려면 다음과 같이 텍스트를 컨테이너에 넣으십시오.
<div class="more-less">
<div class="more-block">
<p>The long text goes in here</p>
</div>
</div>
다음 jQuery 함수가 추가되면 adjustheight 값보다 큰 div가 잘리고 "More"링크가 추가됩니다.
$(function(){
var adjustheight = 60;
var moreText = '+ More';
var lessText = '- Less';
$(".more-less .more-block").each(function(){
if ($(this).height() > adjustheight){
$(this).css('height', adjustheight).css('overflow', 'hidden');
$(this).parent(".more-less").append
('<a style="cursor:pointer" class="adjust">' + moreText + '</a>');
}
});
$(".adjust").click(function() {
if ($(this).prev().css('overflow') == 'hidden')
{
$(this).prev().css('height', 'auto').css('overflow', 'visible');
$(this).text(lessText);
}
else {
$(this).prev().css('height', adjustheight).css('overflow', 'hidden');
$(this).text(moreText);
}
});
});
이를 기반으로하지만 업데이트 됨 : http://shakenandstirredweb.com/240/jquery-moreless-text
언급 된 dotdotdot jQuery 플러그인 은 각도와 잘 작동합니다.
(function (angular) {
angular.module('app')
.directive('appEllipsis', [
"$log", "$timeout", function ($log, $timeout) {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
// let the angular data binding run first
$timeout(function() {
element.dotdotdot({
watch: "window"
});
});
}
}
}
]);
})(window.angular);
해당 마크 업은 다음과 같습니다.
<p app-ellipsis>{{ selectedItem.Description }}</p>
순수 JS 데모 (jQuery 및 'while'루프 없음)
여러 줄 줄임표 문제의 해결책을 검색했을 때 jQuery가 없으면 좋은 것이 없다는 것에 놀랐습니다. 또한 'while'루프를 기반으로 한 몇 가지 솔루션이 있지만 무한 루프에 들어갈 가능성으로 인해 효과적이고 위험하지 않다고 생각합니다. 그래서 나는이 코드를 썼다 :
function ellipsizeTextBox(el) {
if (el.scrollHeight <= el.offsetHeight) {
return;
}
let wordArray = el.innerHTML.split(' ');
const wordsLength = wordArray.length;
let activeWord;
let activePhrase;
let isEllipsed = false;
for (let i = 0; i < wordsLength; i++) {
if (el.scrollHeight > el.offsetHeight) {
activeWord = wordArray.pop();
el.innerHTML = activePhrase = wordArray.join(' ');
} else {
break;
}
}
let charsArray = activeWord.split('');
const charsLength = charsArray.length;
for (let i = 0; i < charsLength; i++) {
if (el.scrollHeight > el.offsetHeight) {
charsArray.pop();
el.innerHTML = activePhrase + ' ' + charsArray.join('') + '...';
isEllipsed = true;
} else {
break;
}
}
if (!isEllipsed) {
activePhrase = el.innerHTML;
let phraseArr = activePhrase.split('');
phraseArr = phraseArr.slice(0, phraseArr.length - 3)
el.innerHTML = phraseArr.join('') + '...';
}
}
let el = document.getElementById('ellipsed');
ellipsizeTextBox(el);
편집 : Shave 를 가로 질러 주어진 최대 높이를 기반으로 여러 줄 텍스트 잘림을 수행하는 JS 플러그인입니다. 이진 검색을 사용하여 최적의 중단 점을 찾습니다. 조사 할만한 가치가 있습니다.
원래 답변 :
이 문제에 대한 바닐라 JS 솔루션을 생각해 내야했습니다. 내가 작업 한 경우에는 긴 제품 이름을 제한된 너비와 두 줄로 맞추어야했습니다. 필요한 경우 줄임표로 잘립니다.
나는 다양한 SO 게시물의 답변을 사용하여 내 요구에 맞는 것을 요리했습니다. 전략은 다음과 같습니다.
- 원하는 글꼴 크기에 대한 글꼴 변형의 평균 문자 너비를 계산하십시오.
- 컨테이너의 너비를 계산
- 컨테이너의 한 줄에 맞는 문자 수를 계산하십시오.
- 줄에 맞는 문자 수와 텍스트를 줄 바꿈해야하는 줄 수를 기준으로 문자열을자를 문자 수를 계산하십시오.
- 이전 계산을 기반으로 입력 텍스트를 자르고 (줄임표로 추가 된 추가 문자를 고려하여) 끝에 "..."를 추가하십시오.
코드 샘플 :
/**
* Helper to get the average width of a character in px
* NOTE: Ensure this is used only AFTER font files are loaded (after page load)
* @param {DOM element} parentElement
* @param {string} fontSize
*/
function getAverageCharacterWidth(parentElement, fontSize) {
var textSample = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()";
parentElement = parentElement || document.body;
fontSize = fontSize || "1rem";
var div = document.createElement('div');
div.style.width = "auto";
div.style.height = "auto";
div.style.fontSize = fontSize;
div.style.whiteSpace = "nowrap";
div.style.position = "absolute";
div.innerHTML = textSample;
parentElement.appendChild(div);
var pixels = Math.ceil((div.clientWidth + 1) / textSample.length);
parentElement.removeChild(div);
return pixels;
}
/**
* Helper to truncate text to fit into a given width over a specified number of lines
* @param {string} text Text to truncate
* @param {string} oneChar Average width of one character in px
* @param {number} pxWidth Width of the container (adjusted for padding)
* @param {number} lineCount Number of lines to span over
* @param {number} pad Adjust this to ensure optimum fit in containers. Use a negative value to Increase length of truncation, positive values to decrease it.
*/
function truncateTextForDisplay(text, oneChar, pxWidth, lineCount, pad) {
var ellipsisPadding = isNaN(pad) ? 0 : pad;
var charsPerLine = Math.floor(pxWidth / oneChar);
var allowedCount = (charsPerLine * (lineCount)) - ellipsisPadding;
return text.substr(0, allowedCount) + "...";
}
//SAMPLE USAGE:
var rawContainer = document.getElementById("raw");
var clipContainer1 = document.getElementById("clip-container-1");
var clipContainer2 = document.getElementById("clip-container-2");
//Get the text to be truncated
var text=rawContainer.innerHTML;
//Find the average width of a character
//Note: Ideally, call getAverageCharacterWidth only once and reuse the value for the same font and font size as this is an expensive DOM operation
var oneChar = getAverageCharacterWidth();
//Get the container width
var pxWidth = clipContainer1.clientWidth;
//Number of lines to span over
var lineCount = 2;
//Truncate without padding
clipContainer1.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount);
//Truncate with negative padding value to adjust for particular font and font size
clipContainer2.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount,-10);
.container{
display: inline-block;
width: 200px;
overflow: hidden;
height: auto;
border: 1px dotted black;
padding: 10px;
}
<h4>Untruncated</h4>
<div id="raw" class="container">
This is super long text which needs to be clipped to the correct length with ellipsis spanning over two lines
</div>
<h4>Truncated</h4>
<div id="clip-container-1" class="container">
</div>
<h4>Truncated with Padding Tweak</h4>
<div id="clip-container-2" class="container">
</div>
추신:
- 잘림이 한 줄에 있어야하는 경우 텍스트 오버플로를 사용하는 순수한 CSS 방법 : 줄임표가 더 깔끔합니다.
- 너비가 고정되지 않은 글꼴은 다른 문자의 너비가 다르기 때문에 잘림이 너무 일찍 또는 너무 늦게 발생할 수 있습니다. pad 매개 변수를 사용하면 경우에 따라이를 완화하는 데 도움이되지만 바보는 아닙니다. :)
- 노트북을 가져온 후 원래 게시물에 대한 링크 및 참조를 추가합니다 (이력 필요).
PPS : 이것이 @DanMan과 @ st.never가 제안한 접근 방식과 매우 유사하다는 것을 깨달았습니다. 구현 예제는 코드 스 니펫을 확인하십시오.
아마도 늦었지만 SCSS를 사용하면 다음과 같은 함수를 선언 할 수 있습니다.
@mixin clamp-text($lines, $line-height) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: $lines;
line-height: $line-height;
max-height: unquote('#{$line-height*$lines}em');
@-moz-document url-prefix() {
position: relative;
height: unquote('#{$line-height*$lines}em');
&::after {
content: '';
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 30%;
height: unquote('#{$line-height}em');
background: linear-gradient(
to right,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 1) 50%
);
}
}
}
그리고 그것을 다음과 같이 사용하십시오 :
.foo {
@include clamp-text(1, 1.4);
}
텍스트를 한 줄로 자르고 텍스트가 1.4 줄임을 알 수 있습니다. 예상되는 결과물은 크롬 ...
은 끝에서 렌더링 하고 FF는 끝에서 시원한 페이드로
Firefox
크롬
매우 간단한 자바 스크립트 솔루션. div는 fe로 스타일을 지정해야합니다.
.croppedTexts {
max-height: 32px;
overflow: hidden;
}
그리고 JS :
var list = document.body.getElementsByClassName("croppedTexts");
for (var i = 0; i < list.length; i++) {
cropTextToFit(list[i]);
}
function cropTextToFit (o) {
var lastIndex;
var txt = o.innerHTML;
if (!o.title) o.title = txt;
while (o.scrollHeight > o.clientHeight) {
lastIndex = txt.lastIndexOf(" ");
if (lastIndex == -1) return;
txt = txt.substring(0, lastIndex);
o.innerHTML = txt + "…";
}
}
Courier와 같은 고정 너비 글꼴이 없으면 (현재?) 할 수 없습니다. 고정 폭 글꼴을 사용하면 모든 문자가 동일한 가로 공간을 차지하므로 문자를 세고 결과를 ems 또는 exs의 현재 글꼴 크기와 곱할 수 있습니다. 그런 다음 한 줄에 몇 개의 문자가 들어가는 지 테스트 한 다음 구분해야합니다.
또는 고정되지 않은 글꼴의 경우 가능한 모든 문자 (예 : i = 2px, m = 5px)에 대한 매핑을 만든 다음 수학을 수행 할 수 있습니다. 그래도 많은 추악한 작업.
@DanMan의 솔루션을 확장하려면 가변 너비 글꼴을 사용하는 경우 평균 글꼴 너비를 사용할 수 있습니다. 여기에는 두 가지 문제가 있습니다. 1) W가 너무 많은 텍스트가 오버플로되고 2) 너무 많은 텍스트가 잘릴 수 있습니다.
또는 최악의 접근 방식을 취하고 문자 "W"의 너비를 사용할 수 있습니다 (가장 넓습니다). 위의 문제 1은 제거되지만 문제 2는 강화됩니다.
다른 접근법은 다음과 같습니다 .div overflow: clip
에 두고 생략 된 섹션 (다른 div 또는 이미지)을 float: right; position: relative; bottom: 0px;
(unested)로 추가하십시오. 트릭은 이미지를 텍스트 끝 위에 표시하는 것입니다.
오버플로가 발생한다는 것을 알고있을 때만 이미지를 표시 할 수도 있습니다 (예 : 약 100 자).
이 코드를 사용하면 요소의 높이가 최대 높이 스타일로 제한되는 경우 추가 래퍼 div가 필요하지 않습니다.
// Shorten texts in overflowed paragraphs to emulate Operas text-overflow: -o-ellipsis-lastline
$('.ellipsis-lastline').each(function(i, e) {
var $e = $(e), original_content = $e.text();
while (e.scrollHeight > e.clientHeight)
$e.text($e.text().replace(/\W*\w+\W*$/, '…'));
$e.attr('data-original-content', original_content);
});
또한 예를 들어 스타일 만 사용하여 표시 할 수있는 데이터 속성에 원본 텍스트를 저장합니다. 마우스 오버시 :
.ellipsis-lastline {
max-height: 5em;
}
.ellipsis-lastline:before {
content: attr(data-original-content);
position: absolute;
display: none;
}
.ellipsis-lastline:hover:before {
display: block;
}
내 시나리오에서는 위에서 언급 한 기능을 사용할 수 없었으며 글꼴 크기 또는 컨테이너 크기에 관계없이 표시 할 행 수를 함수에 알려 주어야했습니다.
나는의 사용에 대한 내 솔루션을 기반으로 Canvas.measureText의 (AN입니다 whic 방법 HTML5의 설명에 따라 기능) 여기 에서 도미 완전히 크로스 브라우저되지 않도록를.
이 바이올린 에서 어떻게 작동하는지 볼 수 있습니다 .
이것은 코드입니다.
var processTexts = function processTexts($dom) {
var canvas = processTexts .canvas || (processTexts .canvas = document.createElement("canvas"));
$dom.find('.block-with-ellipsis').each(function (idx, ctrl) {
var currentLineAdded = false;
var $this = $(ctrl);
var font = $this.css('font-family').split(",")[0]; //This worked for me so far, but it is not always so easy.
var fontWeight = $(this).css('font-weight');
var fontSize = $(this).css('font-size');
var fullFont = fontWeight + " " + fontSize + " " + font;
// re-use canvas object for better performance
var context = canvas.getContext("2d");
context.font = fullFont;
var widthOfContainer = $this.width();
var text = $.trim(ctrl.innerHTML);
var words = text.split(" ");
var lines = [];
//Number of lines to span over, this could be calculated/obtained some other way.
var lineCount = $this.data('line-count');
var currentLine = words[0];
var processing = "";
var isProcessing = true;
var metrics = context.measureText(text);
var processingWidth = metrics.width;
if (processingWidth > widthOfContainer) {
for (var i = 1; i < words.length && isProcessing; i++) {
currentLineAdded = false;
processing = currentLine + " " + words[i];
metrics = context.measureText(processing);
processingWidth = metrics.width;
if (processingWidth <= widthOfContainer) {
currentLine = processing;
} else {
if (lines.length < lineCount - 1) {
lines.push(currentLine);
currentLine = words[i];
currentLineAdded = true;
} else {
processing = currentLine + "...";
metrics = context.measureText(processing);
processingWidth = metrics.width;
if (processingWidth <= widthOfContainer) {
currentLine = processing;
} else {
currentLine = currentLine.slice(0, -3) + "...";
}
lines.push(currentLine);
isProcessing = false;
currentLineAdded = true;
}
}
}
if (!currentLineAdded)
lines.push(currentLine);
ctrl.innerHTML = lines.join(" ");
}
});
};
(function () {
$(document).ready(function () {
processTexts($(document));
});
})();
그리고 그것을 사용하는 HTML은 다음과 같습니다.
<div class="block-with-ellipsis" data-line-count="2">
VERY LONG TEXT THAT I WANT TO BREAK IN LINES. VERY LONG TEXT THAT I WANT TO BREAK IN LINES.
</div>
글꼴 모음을 가져 오는 코드는 다소 간단하며 제 경우에는 효과가 있지만 더 복잡한 시나리오의 경우이 줄을 따라 무언가를 사용해야 할 수도 있습니다 .
또한 필자의 경우 함수에 사용할 줄 수를 알려주고 있지만 컨테이너 크기와 글꼴에 따라 표시 할 줄 수를 계산할 수 있습니다.
HTML을 그대로 유지하는 버전을 만들었습니다. jsfiddle 예제
jQuery
function shorten_text_to_parent_size(text_elem) {
textContainerHeight = text_elem.parent().height();
while (text_elem.outerHeight(true) > textContainerHeight) {
text_elem.html(function (index, text) {
return text.replace(/(?!(<[^>]*>))\W*\s(\S)*$/, '...');
});
}
}
$('.ellipsis_multiline').each(function () {
shorten_text_to_parent_size($(this))
});
CSS
.ellipsis_multiline_box {
position: relative;
overflow-y: hidden;
text-overflow: ellipsis;
}
문제를 해결하는 각도 구성 요소를 작성했습니다. 주어진 텍스트를 범위 요소로 분할합니다. 렌더링 후에는 넘친 모든 요소를 제거하고 마지막으로 보이는 요소 바로 뒤에 줄임표를 배치합니다.
사용 예 :
<app-text-overflow-ellipsis [text]="someText" style="max-height: 50px"></app-text-overflow-ellipsis>
Stackblitz 데모 : https://stackblitz.com/edit/angular-wfdqtd
구성 요소 :
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef, HostListener,
Input,
OnChanges,
ViewChild
} from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-text-overflow-ellipsis',
template: `
<span *ngFor="let word of words; let i = index" [innerHTML]="word + (!endsWithHyphen(i) ? ' ' : '')"></span>
<span #ellipsis [hidden]="!showEllipsis && !initializing" [class.initializing]="initializing" [innerHTML]="'...' + (initializing ? ' ' : '')"></span>
`,
styles: [`
:host {
display: block;
position: relative;
}
.initializing {
opacity: 0;
}
`
]
})
export class TextOverflowEllipsisComponent implements OnChanges {
@Input()
text: string;
showEllipsis: boolean;
initializing: boolean;
words: string[];
@ViewChild('ellipsis')
ellipsisElement: ElementRef;
constructor(private element: ElementRef, private cdRef: ChangeDetectorRef) {}
ngOnChanges(){
this.init();
}
@HostListener('window:resize')
init(){
// add space after hyphens
let text = this.text.replace(/-/g, '- ') ;
this.words = text.split(' ');
this.initializing = true;
this.showEllipsis = false;
this.cdRef.detectChanges();
setTimeout(() => {
this.initializing = false;
let containerElement = this.element.nativeElement;
let containerWidth = containerElement.clientWidth;
let wordElements = (<HTMLElement[]>Array.from(containerElement.childNodes)).filter((element) =>
element.getBoundingClientRect && element !== this.ellipsisElement.nativeElement
);
let lines = this.getLines(wordElements, containerWidth);
let indexOfLastLine = lines.length - 1;
let lineHeight = this.deductLineHeight(lines);
if (!lineHeight) {
return;
}
let indexOfLastVisibleLine = Math.floor(containerElement.clientHeight / lineHeight) - 1;
if (indexOfLastVisibleLine < indexOfLastLine) {
// remove overflowing lines
for (let i = indexOfLastLine; i > indexOfLastVisibleLine; i--) {
for (let j = 0; j < lines[i].length; j++) {
this.words.splice(-1, 1);
}
}
// make ellipsis fit into last visible line
let lastVisibleLine = lines[indexOfLastVisibleLine];
let indexOfLastWord = lastVisibleLine.length - 1;
let lastVisibleLineWidth = lastVisibleLine.map(
(element) => element.getBoundingClientRect().width
).reduce(
(width, sum) => width + sum, 0
);
let ellipsisWidth = this.ellipsisElement.nativeElement.getBoundingClientRect().width;
for (let i = indexOfLastWord; lastVisibleLineWidth + ellipsisWidth >= containerWidth; i--) {
let wordWidth = lastVisibleLine[i].getBoundingClientRect().width;
lastVisibleLineWidth -= wordWidth;
this.words.splice(-1, 1);
}
this.showEllipsis = true;
}
this.cdRef.detectChanges();
// delay is to prevent from font loading issues
}, 1000);
}
deductLineHeight(lines: HTMLElement[][]): number {
try {
let rect0 = lines[0][0].getBoundingClientRect();
let y0 = rect0['y'] || rect0['top'] || 0;
let rect1 = lines[1][0].getBoundingClientRect();
let y1 = rect1['y'] || rect1['top'] || 0;
let lineHeight = y1 - y0;
if (lineHeight > 0){
return lineHeight;
}
} catch (e) {}
return null;
}
getLines(nodes: HTMLElement[], clientWidth: number): HTMLElement[][] {
let lines = [];
let currentLine = [];
let currentLineWidth = 0;
nodes.forEach((node) => {
if (!node.getBoundingClientRect){
return;
}
let nodeWidth = node.getBoundingClientRect().width;
if (currentLineWidth + nodeWidth > clientWidth){
lines.push(currentLine);
currentLine = [];
currentLineWidth = 0;
}
currentLine.push(node);
currentLineWidth += nodeWidth;
});
lines.push(currentLine);
return lines;
}
endsWithHyphen(index: number): boolean {
let length = this.words[index].length;
return this.words[index][length - 1] === '-' && this.words[index + 1] && this.words[index + 1][0];
}
}
더 빠른 알고리즘으로 다른 라이브러리를 만들었습니다. 확인해주십시오:
https://github.com/i-ahmed-biz/fast-ellipsis
바우어를 사용하여 설치하려면 :
bower install fast-ellipsis
npm을 사용하여 설치하려면 다음을 수행하십시오.
npm install fast-ellipsis
당신이 즐기시기 바랍니다!
이것이 당신이 찾고있는 것인지 확실하지 않으면 높이 대신 최소 높이를 사용합니다.
<div id="content" style="min-height:10px;width:190px;background:lightblue;">
<?php
function truncate($text,$numb) {
// source: www.kigoobe.com, please keep this if you are using the function
$text = html_entity_decode($text, ENT_QUOTES);
if (strlen($text) > $numb) {
$text = substr($text, 0, $numb);
$etc = "...";
$text = $text.$etc;
}
$text = htmlentities($text, ENT_QUOTES);
return $text;
}
echo truncate("this is a multi-lines text block, some lines inside the div, while some outside", 63);
?>
</div>
매우 간단한 기능이 가능합니다.
지령:
$scope.truncateAlbumName = function (name) {
if (name.length > 36) {
return name.slice(0, 34) + "..";
} else {
return name;
}
};
전망:
<#p>{{truncateAlbumName(album.name)}}<#/p>
'Programing' 카테고리의 다른 글
C ++의 내부 typedef-좋은 스타일 또는 나쁜 스타일? (0) | 2020.05.27 |
---|---|
.idea 폴더 란 무엇입니까? (0) | 2020.05.27 |
함수 내부의 정적 constexpr 변수가 의미가 있습니까? (0) | 2020.05.27 |
json.Unmarshal과 json.NewDecoder.Decode를 사용하여 JSON 디코딩 (0) | 2020.05.27 |
“this”모듈의 소스 코드는 무엇입니까? (0) | 2020.05.27 |