背景
目前在做项目的UI改版,需要加一个公告栏,用于向用户展示公告信息;当公告信息过长时,公告栏对内容进行滚动展示;用户可以点击隐藏,并且同一窗口不再重复展示。 先来看看效果:
拓展
期间也造了两个其他的迷你轮子:不使用滚动插件的日期选择器、带切换动画的数字展示组件 感兴趣的可以去看看:
公告栏组件实现
滚动展示
布局:
<div className='ui-notice-container'>
<div className="icon-notice"></div>
<div ref='con' className='ui-notice'>
<span ref='word'>{ noticeMessage }</span>
</div>
<div className='iconfont icon-close' onClick={this.handleClose.bind(this)}></div>
</div>
外面包裹的容器设置
overflow:hidden
利用setInterval() 动态设置里面的用于承载公告内容的滑块的margin-left属性,实现滚动效果
if(!this.refs.con) return;
let conWidth = this.refs.con.offsetWidth,
wordWidth = this.refs.word.offsetWidth,
speed = 0.15,
translateXnum = 0;
if(navigator.userAgent.indexOf('Android 4')>-1){
wordWidth = this.refs.word.getBoundingClientRect().width;
}
if(conWidth < wordWidth){
clearInterval(sliderInterval);
sliderInterval = setInterval(function(){
if(parseInt(Math.abs(translateXnum)) > wordWidth){
translateXnum = conWidth;
this.refs.word.style.marginLeft = translateXnum + 'px';
}
translateXnum -= speed;
this.refs.word.style.marginLeft = translateXnum + 'px';
}.bind(this),2);
}
同一窗口不再重复展示
将控制公告栏显示/隐藏的状态存到session Storage ,用于存储显示隐藏状态
sessionStorage 属性允许你访问一个,对应当前源的 session Storage 对象。它与 localStorage 相似,不同之处在于 localStorage 里面存储的数据没有过期时间设置,而存储在 sessionStorage 里面的数据在页面会话结束时会被清除。
封装一下sessionStorage操作
let Storage = {
get(key) {
if(sessionStorage.getItem(key)) {
return JSON.parse(sessionStorage.getItem(key));
} else {
return '';
}
},
set(key, val) {
sessionStorage.setItem(key, JSON.stringify(val));
},
del(key) {
if(sessionStorage.getItem(key)) sessionStorage.removeItem(key);
},
clear() {
sessionStorage.clear();
}
};
export default Storage;
使用
import NoticeComponent from './modules/Notice';
<NoticeComponent noticeMessage={noticeMessage} />
完整代码
Notice.js
import React, {Component} from 'react';
import ls from '../../utilities/storage';
import "../../../less/notice.less";
let sliderInterval=null;
class NoticeComponent extends Component {
constructor(props) {
super(props);
const flagNotice = ls.get('notice') || 'show';
this.state = {
show: this.props.noticeMessage && flagNotice == 'show'
};
}
handleClose() {
this.setState({
show:false
});
clearInterval(sliderInterval);
ls.set('notice','hid');
}
componentWillUnmount() {
if(sliderInterval){
clearInterval(sliderInterval);
}
}
componentDidMount() {
if(!this.refs.con) return;
let conWidth = this.refs.con.offsetWidth,
wordWidth = this.refs.word.offsetWidth,
speed = 0.15,
translateXnum = 0;
if(navigator.userAgent.indexOf('Android 4')>-1){
wordWidth = this.refs.word.getBoundingClientRect().width;
}
if(conWidth < wordWidth){
clearInterval(sliderInterval);
sliderInterval = setInterval(function(){
if(parseInt(Math.abs(translateXnum)) > wordWidth){
translateXnum = conWidth;
this.refs.word.style.marginLeft = translateXnum + 'px';
}
translateXnum -= speed;
this.refs.word.style.marginLeft = translateXnum + 'px';
}.bind(this),2);
}
}
render() {
const { noticeMessage } = this.props;
if(this.state.show){
return <div className='ui-notice-container'>
<div className="icon-notice"></div>
<div ref='con' className='ui-notice'>
<span ref='word'>{ noticeMessage }</span>
</div>
<div className='iconfont icon-close' onClick={this.handleClose.bind(this)}></div>
</div>
}else{
return null;
}
}
}
NoticeComponent.PropTypes = {
};
export default NoticeComponent;
notice.less
// 字体大小
@defaultSize: 16;
.ui-notice-container{
top: 0;
background: #FFF8EE;
color: #AF7E46;
max-width: 800px;
font-size: unit((13/@defaultSize),rem);
height: unit((38/@defaultSize),rem);
line-height: unit((38/@defaultSize),rem);
margin: 0 unit((15/@defaultSize),rem);
display: -webkit-box;
display: -webkit-flex;
display: flex;
&.hidden{
display: none;
}
.icon-notice{
background: url(../assets/images/notice.png) no-repeat right top;
background-size:cover;
width:unit((33/@defaultSize),rem);
}
.ui-notice{
overflow: hidden;
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-webkit-flex: 1; /* Chrome */
flex: 1;
text-align: left;
span{
white-space: nowrap;
}
}
.icon-close{
background: url(../assets/images/close.png) no-repeat right top;
background-size:cover;
width:unit((14/@defaultSize),rem);
height:unit((14/@defaultSize),rem);
margin:unit((11/@defaultSize),rem) unit((7/@defaultSize),rem) unit((9/@defaultSize),rem) unit((3/@defaultSize),rem);
}
}
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情