本文仅针对在小程序侧的多行文本溢出省略,超出现实展开按钮的实现。web方向的实现,不在本文赘述。
效果
- 两种方式
-
- 一种是另起一行的
- 一种是在省略号右侧
另起一行展示”展开收起“
要点:
- 多行省略,并且不超过制定行数时,不显示展开按钮
- 如何判断是否已超出省略
多行文本省略
这块比较简单,css已实现多行文本省略的属性,在小程序侧可以直接使用。并且该属性可以让文字在不超过制定行数时,不显示展开按钮。
.overflow{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
通过上面的代码,我们就可以实现多行文本的yichu省略啦。接下来我们来实现显示展开按钮
显示展开按钮
是否显示展开按钮,核心就是如何判断当前文本是否已超出溢出。由于溢出省略这块的逻辑全部都由CSS实现,不可以直接通过样式来拿到当前是否溢出的状态。因此我们想到是否可以通过js来做判断。
首先我们想到的是,当视图在页面中渲染完成,这个时候我们是可以拿到相关元素的位置及宽高信息的,那如何通过这种信息来识别是否溢出隐藏呢。
其实我们可以在通过多展示一个不溢出隐藏的容器,来承载这些文字,只是将该容器进行隐藏而且不影响当前视图布局。可以使用多展示的容器通过绝对定位超出当前文档流。
样式布局
<view class="content-wrap">
<view class="content">
文本内容
<view class="content-hide">文本内容</view>
</view>
</view>
对应的CSS。
.content {
position: relative;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.content-hide {
position: absolute;
left: 0;
top: 0;
z-index: -1;
visibility: hidden;
}
JS逻辑操作
这里考虑前端静态数据的情况下,如果是根据后端返回数据的渲染,可以在对应的setData之后的回调中进行计算。这里考虑只有一条数据时的情况
Page({
data: {
overflowStatus: false,
}
onReady(){
this.calcOverflowStatus();
},
calcOverflowStatus() {
const query = this.createSelectorQuery();
query.select('.content').boundingClientRect();
query.select('.content-hide').boundingClientRect();
query.exec((res) => {
this.setData({
overflowStatus: res[1].height - res[0].height
})
})
}
})
这样我就实现了另起一行展示”展开收起“按钮的操作了
右下角展示“展开收起”
这里是参考阅文前端团队的文章CSS 实现多行文本“展开收起”,在小程序侧的实现。
注意的点:
- 当display设置为-webkit-box时,该容器内的float元素不生效,因此这里直接使用其提供的兼容写法,就不能使用line-clamp属性了。
- 当我们设置容器的before伪元素的位置时,偏移量的单位使用px,否则使用rpx在各个机型上进行动态计算,会导致有误差。
- 动态高度的问题,在不定高的情况下,如何使height:100%生效。这里可以使用flex布局,因为flex布局的子项中,可以通过百分比来计算变化高度。
html结构
<view class="wrap">
<view class="content-box {{open ? 'open' : ''}} ">
<view wx:if="{{!open && overflowStatus}}" class="more-btn" bindtap="handleOpen">展开</view>
{{content}}
</view>
</view>
wrap最外层的容器,主要是为了解决height: 100%失效的问题。给该元素设定display: flex属性。
.wrap {
display: flex;
}
多行文本省略
这里直接写兼容写法。
.content {
/*
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
*/
line-height: 1.5;
max-height: 4.5em;
overflow: hidden;
text-align: justify;
}
这里使用text-align: justify来实现...与文字对齐。否则的话会出现,展示省略号的一行,省略号无法与文字紧挨在一起。
展示“展开”按钮
这里参考阅文团队的大佬,使用float元素来实现。直接展示完整的css代码。
.wrap {
display: flex;
}
.content-box {
overflow: hidden;
line-height: 1.5;
max-height: 4.5em;
text-align: justify;
color: #999;
position: relative;
}
.content-box.open {
max-height: none;
}
.content-box::before {
content: '';
float: right;
height: 100%;
width: 0;
margin-bottom: -24px;
/* height: calc(100% - 24px); */
}
.more-btn {
color: #000;
float: right;
clear: both;
position: relative;
}
.more-btn::before{
content: '...';
color: #999;
font-size: 14px;
margin-right: 8rpx;
}
解读:
- 最外层的wrap容器设定display解决context-box的伪元素设定height:100%失效的问题
- 利用context-box的伪元素右浮动,并设定其高度为100%。more-btn设定float: right时,这时会看到是展示在context-box伪元素的左侧,如何将其放到下面呢。可以让more-btn清除下浮动clear: both; 这样就是实现了展开按钮右下角环绕效果了。
- 但是content-box的伪元素高度设定为100%,则会导致将more-btn直接被挤出容器,因此可以设定content-box的伪元素一个margin-bottom负值,这样可以让more-btn展示出来。
- 这里margin-bottom设定为-24px,而不是小程序的rpx单位,是由于rpx还会在各个机型上进行计算,导致位置出现误差,这里直接使用px单位,保证位置准确性
- 省略号的添加,利用more-btn元素的伪元素来添加。
超过设定的行数展开按钮展示
这里依然使用JS判断的手段。跟另起一行展示的手法保持一致。
Page({
data: {
overflowStatus: false,
}
onReady(){
this.calcOverflowStatus();
},
calcOverflowStatus() {
const query = this.createSelectorQuery();
query.select('.content-box').boundingClientRect();
query.select('.content-hide').boundingClientRect();
query.exec((res) => {
this.setData({
overflowStatus: res[1].height - res[0].height
})
})
}
})