ฉันสร้างภาพสำหรับคำถามนี้เพื่อให้เข้าใจง่ายขึ้น
เป็นไปได้ไหมที่จะสร้างจุดไข่ปลาบน a <div>
ด้วยความกว้างคงที่และหลายบรรทัด?
ฉันลองใช้ปลั๊กอิน jQuery ที่นี่และที่นั่น แต่ไม่พบสิ่งที่ฉันกำลังมองหา ข้อเสนอแนะใด ๆ ไอเดีย?
ฉันสร้างภาพสำหรับคำถามนี้เพื่อให้เข้าใจง่ายขึ้น
เป็นไปได้ไหมที่จะสร้างจุดไข่ปลาบน a <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)*$/, '...');
});
}
มันพยายามที่จะลบคำสุดท้ายของข้อความซ้ำ ๆ จนกว่าจะถึงขนาดที่ต้องการ เพราะน้ำล้น: ซ่อนเร้น; กระบวนการยังคงมองไม่เห็นและแม้เมื่อ JS ปิดผลลัพธ์ยังคง 'ถูกต้องด้วยสายตา' (โดยไม่ต้องมี "... " แน่นอน)
หากคุณรวมสิ่งนี้เข้ากับการตัดที่สมเหตุสมผลบนฝั่งเซิร์ฟเวอร์ (ที่เหลือเพียงค่าใช้จ่ายเล็ก ๆ ) จากนั้นจะทำงานเร็วขึ้น :)
อีกครั้งนี่ไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์ แต่เป็นเพียงความคิด
UPDATE:เพิ่มjsFiddle สาธิต
li
และภายในของแต่ละคนมี a .block
และ a .block h2
และฉันจำเป็นต้องใช้สิ่งนี้กับh2
ภายใน.block
แต่ฉันไม่สามารถทำให้มันใช้งานได้ มันต่างกันไหมถ้ามีมากกว่าหนึ่ง.block h2
?
height*3
โดยไม่กี่พิกเซล การแก้ไขที่ง่ายคือการเพิ่มพิกเซลเพียงไม่กี่พิกเซลdivh
while
บรรทัด:if(!$p.text().match(/\W*\s(\S)*$/)) break;
while ((upper-lower)>1) {let middle=((lower+upper)/2)|0 /*|0 is quick floor*/; if (test(words.slice(0,middle)+'...')) {lower=middle;} else {upper=middle;}}
. ตามที่ @KrisWebDev ค้นพบคุณจะต้องตรวจสอบคำยักษ์หนึ่งคำ
ลองใช้ปลั๊กอินjQuery.dotdotdot
$(".ellipsis").dotdotdot();
โปรดทราบว่า "การยึดสาย" เรียกอีกอย่างว่า "จุดไข่ปลาบนบล็อกของหลายบรรทัด" หรือ "จุดไข่ปลาแนวตั้ง"
github.com/BeSite/jQuery.dotdotdot
github.com/josephschmitt/Clamp.js
นี่คืออีกไม่กี่ฉันยังไม่ได้ตรวจสอบ:
มีบางโซลูชั่น CSS การใช้งานที่ง่ายมี แต่ที่มีการสนับสนุนเบราว์เซอร์ที่น่าสงสาร-webkit-line-clamp
ดูการสาธิตสดบนjsfiddle.net/AdrienBe/jthu55v7/
หลายคนพยายามอย่างมากเพื่อให้สิ่งนี้เกิดขึ้นโดยใช้ CSS เท่านั้น ดูบทความและคำถามเกี่ยวกับมัน:
ง่าย ๆ เข้าไว้. ยกเว้นว่าคุณมีเวลาเหลือเฟือที่จะอุทิศให้กับคุณสมบัตินี้ให้หาทางออกที่ง่ายที่สุดและทดสอบแล้ว: CSS อย่างง่ายหรือไลบรารีจาวาสคริปต์ที่ผ่านการทดสอบอย่างดี
ไปสำหรับสิ่งที่แฟนซี / ซับซ้อน / ปรับแต่งสูงและคุณจะจ่ายราคานี้ลงถนน
การจางหายไปอย่าง Airbnb อาจเป็นทางออกที่ดี มันอาจเป็น CSS พื้นฐานร่วมกับ jQuery พื้นฐาน จริงๆแล้วดูเหมือนว่าจะคล้ายกันมากโซลูชันนี้ใน CSSTricks มาก
โอ้และถ้าคุณมองหาแรงบันดาลใจในการออกแบบ:
ไม่มีคุณสมบัติดังกล่าวใน HTML และสิ่งนี้น่าผิดหวังมาก
ฉันได้พัฒนาห้องสมุดเพื่อจัดการกับสิ่งนี้
ตรวจสอบเว็บไซต์ของฉันเพื่อดูภาพหน้าจอบทแนะนำและลิงก์ dowload
วิธีการแก้ปัญหา JS บริสุทธิ์ขึ้นอยู่กับวิธีการแก้ปัญหาของbažmegakapaและการล้างข้อมูลบางอย่างสำหรับผู้ที่พยายามให้ความสูง / ความสูงสูงสุดที่น้อยกว่าองค์ประกอบของความสูง:
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 ใด ๆ และใช้งานได้กับคอนเทนเนอร์ความกว้างผันแปรรวมถึงเซลล์ตาราง มันใช้สอง divs พิเศษ แต่มันง่ายมากที่จะใช้
http://salzerdesign.com/blog/?p=453
แก้ไข: ขออภัยฉันไม่ทราบว่าลิงก์ไม่เพียงพอ การแก้ปัญหาคือการวาง div รอบข้อความและจัดวาง div เพื่อควบคุมโอเวอร์โฟลว์ ใน div ให้ใส่ div อื่นด้วยการไล่ระดับ "จาง" ซึ่งสามารถทำได้โดยใช้ CSS หรือรูปภาพ (สำหรับ IE เก่า) การไล่ระดับสีเริ่มจากโปร่งใสเป็นสีพื้นหลังของเซลล์ตารางและมีความกว้างมากกว่าจุดไข่ปลาเล็กน้อย หากข้อความยาวและล้นออกไปข้อความนั้นจะอยู่ในส่วน "จาง" และดูว่า "จาง" หากข้อความสั้นจางหายไปจะมองไม่เห็นจึงไม่มีปัญหา สามารถปรับสองคอนเทนเนอร์เพื่อให้แสดงหนึ่งหรือหลายบรรทัดโดยการตั้งค่าความสูงของคอนเทนเนอร์เป็นความสูงหลายบรรทัดของข้อความ 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>
คุณสามารถใช้-webkit-line-clamp
คุณสมบัติด้วยdiv
ทรัพย์สินที่มี
-webkit-line-clamp: <integer>
ซึ่งหมายถึงการตั้งค่าจำนวนบรรทัดสูงสุดก่อนที่จะตัดทอนเนื้อหาแล้วแสดงจุดไข่ปลา(…)
ที่ท้ายบรรทัดสุดท้าย
div {
width: 205px;
height: 40px;
background-color: gainsboro;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
/* <integer> values */
-webkit-line-clamp: 2;
}
<div>This is a multi-lines text block, some lines inside the div, while some outside</div>
นี่เป็นวิธีการแก้ปัญหาวานิลลา 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>
คุณสามารถเล่นกับมันใน codepen ด้านล่าง ลองเปลี่ยนขนาดตัวอักษรในแผง CSS และทำการแก้ไขเล็กน้อยในแผง HTML (เช่นเพิ่มพื้นที่พิเศษที่ใดที่หนึ่ง) เพื่ออัปเดตผลลัพธ์ โดยไม่คำนึงถึงขนาดตัวอักษรย่อหน้ากลางควรจะถูกปัดเศษเป็นจำนวนบรรทัดในพารามิเตอร์ที่สองที่ส่งผ่านไปยัง limitLines () เสมอ
Codepen: http://codepen.io/thdoan/pen/BoXbEK
แก้ไข: มาข้ามShaveซึ่งเป็นปลั๊กอิน JS ที่ทำการตัดทอนข้อความหลายบรรทัดตามความสูงสูงสุดที่กำหนดได้ดีจริงๆ มันใช้การค้นหาแบบไบนารี่เพื่อค้นหาจุดพักที่เหมาะสม คุ้มค่าที่จะตรวจสอบ
คำตอบเดิม:
ฉันต้องคิดหาวิธีแก้ปัญหาของ vanilla 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>
PS:
PPS: เพิ่งรู้ว่านี่คล้ายกับวิธีที่ @DanMan และ @ st.never แนะนำ ชำระเงินตัวอย่างโค้ดสำหรับตัวอย่างการนำไปใช้งาน
โซลูชัน JavaScript ที่ง่ายมาก Divs จะต้องมีสไตล์ 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 + "…";
}
}
ไม่ใช่คำตอบที่ถูกต้องสำหรับคำถาม แต่ฉันเจอหน้านี้เมื่อพยายามทำสิ่งที่คล้ายกันมาก แต่ต้องการเพิ่มลิงก์ไปยัง "ดูเพิ่มเติม" แทนที่จะเป็นแค่จุดไข่ปลาตรงไปตรงมา นี่คือฟังก์ชั่น jQuery ที่จะเพิ่มลิงก์ "เพิ่มเติม" ไปยังข้อความที่ล้นคอนเทนเนอร์ โดยส่วนตัวฉันใช้สิ่งนี้กับ Bootstrap แต่แน่นอนว่ามันจะไม่ทำงาน
วิธีใช้ใส่ข้อความของคุณในคอนเทนเนอร์ดังนี้:
<div class="more-less">
<div class="more-block">
<p>The long text goes in here</p>
</div>
</div>
เมื่อเพิ่มฟังก์ชัน jQuery ต่อไปนี้ divs ใด ๆ ที่มีขนาดใหญ่กว่าค่าการปรับความสูงจะถูกตัดทอนและเพิ่มลิงค์ "เพิ่มเติม"
$(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
ปลั๊กอิน jQuery dotdotdot ที่กล่าวถึงใช้งานได้ดีกับ angular:
(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>
เมื่อฉันค้นหาวิธีแก้ปัญหาของจุดไข่ปลาหลายเส้นฉันรู้สึกประหลาดใจที่ไม่มีสิ่งใดที่ดีหากปราศจาก jQuery นอกจากนี้ยังมีวิธีแก้ปัญหาบางอย่างที่ใช้ 'ขณะที่' ลูป แต่ฉันคิดว่ามันไม่ได้มีประสิทธิภาพและอันตรายเนื่องจากความเป็นไปได้ที่จะเข้าสู่วงวนไม่สิ้นสุด ดังนั้นฉันจึงเขียนรหัสนี้:
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);
อาจจะค่อนข้างช้า แต่ใช้ 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
โครเมียม
พบโซลูชันCSS-onlyสั้น ๆ นี้ในคำตอบของ Adrien Be :
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
ณมีนาคม 2020 การสนับสนุนเบราว์เซอร์เป็น95.3%ไม่ได้รับการสนับสนุนใน IE และ Opera Mini ใช้งานได้กับ Chrome, Safari, Firefox และ Edge
คุณอาจไม่สามารถทำได้ (ในปัจจุบัน?) หากไม่มีแบบอักษรที่มีความกว้างคงที่เช่น Courier ด้วยตัวอักษรที่มีความกว้างคงที่ตัวอักษรทุกตัวใช้พื้นที่แนวนอนเดียวกันดังนั้นคุณอาจนับตัวอักษรและทวีคูณผลลัพธ์ด้วยขนาดตัวอักษรปัจจุบันเป็น ems หรือ exs จากนั้นคุณจะต้องทดสอบจำนวนตัวอักษรที่พอดีกับหนึ่งบรรทัดแล้วแยกมันออก
อีกทางเลือกหนึ่งสำหรับแบบอักษรที่ไม่ใช่แบบตายตัวคุณอาจสร้างการแมปสำหรับตัวอักษรที่เป็นไปได้ทั้งหมด (เช่น i = 2px, m = 5px) จากนั้นทำการคำนวณ แม้ว่าการทำงานน่าเกลียดมากมาย
หากต้องการขยายโซลูชันของ @ DanMan: ในกรณีที่ใช้แบบอักษรที่มีความกว้างผันแปรได้คุณสามารถใช้ความกว้างของแบบอักษรโดยเฉลี่ยได้ ปัญหานี้มีสองปัญหา: 1) ข้อความที่มี W มากเกินควรและ 2) ข้อความที่มีมากเกินไปที่ฉันจะถูกตัดทอนก่อนหน้านี้
หรือคุณอาจใช้กรณีที่เลวร้ายที่สุดและใช้ความกว้างของตัวอักษร "W" (ซึ่งฉันเชื่อว่ากว้างที่สุด) สิ่งนี้จะลบปัญหา 1 ด้านบน แต่ทวีความรุนแรงมากขึ้นปัญหา 2
วิธีที่แตกต่างอาจเป็น: ปล่อยให้overflow: clip
div และเพิ่มส่วนจุดไข่ปลา (อาจเป็น div หรือรูปภาพอื่น)float: right; position: relative; bottom: 0px;
(ยังไม่ทดลอง) เคล็ดลับคือการทำให้ภาพปรากฏเหนือส่วนท้ายของข้อความ
คุณสามารถแสดงเฉพาะภาพเมื่อคุณรู้ว่ากำลังจะล้น (เช่นหลังจากตัวอักษรประมาณ 100 ตัว)
overflow: clip
อะไร และคุณคาดหวังอะไรกับ CSS ที่float
ต้องทำ?
ด้วยรหัสนี้ไม่จำเป็นสำหรับ div wrapper พิเศษหากองค์ประกอบที่มีความสูงถูก จำกัด ด้วยรูปแบบความสูงสูงสุด
// 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วิธี (whic เป็นHTML5คุณลักษณะ) ตามที่อธิบายไว้ที่นี่โดยDomiจึงไม่สมบูรณ์ข้ามเบราว์เซอร์
คุณสามารถดูวิธีการทำงานของซอนี้
นี่คือรหัส:
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 demo: 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:
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>
func ง่ายมากจะทำ
Directive:
$scope.truncateAlbumName = function (name) {
if (name.length > 36) {
return name.slice(0, 34) + "..";
} else {
return name;
}
};
ดู:
<#p>{{truncateAlbumName(album.name)}}<#/p>
iiiiiiiiii
vs MMMMMMMMMM
(ด้วยตัวอักษรปัจจุบันที่มองไม่เห็นแม้ว่า: D)