zyejMAll-mobile/sheep/ui/su-notice-bar/su-notice-bar.vue
2024-08-07 21:40:27 +08:00

476 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 公告栏组件 -->
<template>
<view
v-if="show"
class="uni-noticebar"
:style="{ backgroundColor: backgroundColor }"
@click="onClick"
>
<slot name="icon">
<uni-icons
v-if="showIcon === true || showIcon === 'true'"
class="uni-noticebar-icon"
type="sound"
:color="color"
size="22"
/>
</slot>
<view
ref="textBox"
class="uni-noticebar__content-wrapper"
:class="{
'uni-noticebar__content-wrapper--scrollable': scrollable,
'uni-noticebar__content-wrapper--single': !scrollable && (single || moreText),
}"
>
<view
:id="elIdBox"
class="uni-noticebar__content"
:class="{
'uni-noticebar__content--scrollable': scrollable,
'uni-noticebar__content--single': !scrollable && (single || moreText),
}"
>
<text
:id="elId"
ref="animationEle"
class="uni-noticebar__content-text"
:class="{
'uni-noticebar__content-text--scrollable': scrollable,
'uni-noticebar__content-text--single': !scrollable && (single || showGetMore),
}"
:style="{
color: color,
width: wrapWidth + 'px',
animationDuration: animationDuration,
'-webkit-animationDuration': animationDuration,
animationPlayState: webviewHide ? 'paused' : animationPlayState,
'-webkit-animationPlayState': webviewHide ? 'paused' : animationPlayState,
animationDelay: animationDelay,
'-webkit-animationDelay': animationDelay,
}"
>
{{ text }}
</text>
</view>
</view>
<view
v-if="showGetMore === true || showGetMore === 'true'"
class="uni-noticebar__more uni-cursor-point"
@click="clickMore"
>
<text
v-if="moreText.length > 0"
:style="{ color: moreColor }"
class="uni-noticebar__more-text"
>
{{ moreText }}
</text>
<uni-icons v-else type="right" :color="moreColor" size="16" />
</view>
<view
class="uni-noticebar-close uni-cursor-point"
v-if="
(showClose === true || showClose === 'true') &&
(showGetMore === false || showGetMore === 'false')
"
>
<view @click="close">
<slot name="close">
<uni-icons type="closeempty" :color="color" size="16" />
</slot>
</view>
</view>
</view>
</template>
<script>
import sheep from '@/sheep';
// #ifdef APP-NVUE
const dom = weex.requireModule('dom');
const animation = weex.requireModule('animation');
// #endif
/**
* NoticeBar 自定义导航栏
* @description 通告栏组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=30
* @property {Number} speed 文字滚动的速度默认100px/秒
* @property {String} text 显示文字
* @property {String} backgroundColor 背景颜色
* @property {String} color 文字颜色
* @property {String} moreColor 查看更多文字的颜色
* @property {String} moreText 设置“查看更多”的文本
* @property {Boolean} single = [true|false] 是否单行
* @property {Boolean} scrollable = [true|false] 是否滚动为true时NoticeBar为单行
* @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
* @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
* @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标为true时NoticeBar为单行
* @event {Function} click 点击 NoticeBar 触发事件
* @event {Function} close 关闭 NoticeBar 触发事件
* @event {Function} getmore 点击”查看更多“时触发事件
*/
export default {
name: 'UniNoticeBar',
emits: ['click', 'getmore', 'close'],
props: {
text: {
type: String,
default: '',
},
moreText: {
type: String,
default: '',
},
backgroundColor: {
type: String,
default: '',
},
speed: {
// 默认1s滚动100px
type: Number,
default: 100,
},
color: {
type: String,
default: 'var(--ui-BG-Main)',
},
moreColor: {
type: String,
default: '#FF9A43',
},
single: {
// 是否单行
type: [Boolean, String],
default: false,
},
scrollable: {
// 是否滚动,添加后控制单行效果取消
type: [Boolean, String],
default: false,
},
showIcon: {
// 是否显示左侧icon
type: [Boolean, String],
default: false,
},
showGetMore: {
// 是否显示右侧查看更多
type: [Boolean, String],
default: false,
},
showClose: {
// 是否显示左侧关闭按钮
type: [Boolean, String],
default: false,
},
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`;
const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`;
return {
textWidth: 0,
boxWidth: 0,
wrapWidth: '',
webviewHide: false,
// #ifdef APP-NVUE
stopAnimation: false,
// #endif
elId: elId,
elIdBox: elIdBox,
show: true,
animationDuration: 'none',
animationPlayState: 'paused',
animationDelay: '0s',
};
},
mounted() {
// #ifdef APP-PLUS
var pages = getCurrentPages();
var page = pages[pages.length - 1];
var currentWebview = page.$getAppWebview();
currentWebview.addEventListener('hide', () => {
this.webviewHide = true;
});
currentWebview.addEventListener('show', () => {
this.webviewHide = false;
});
// #endif
this.$nextTick(() => {
this.initSize();
});
},
// #ifdef APP-NVUE
beforeDestroy() {
this.stopAnimation = true;
},
// #endif
methods: {
initSize() {
if (this.scrollable) {
// #ifndef APP-NVUE
let query = [],
boxWidth = 0,
textWidth = 0;
let textQuery = new Promise((resolve, reject) => {
uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
.select(`#${this.elId}`)
.boundingClientRect()
.exec((ret) => {
this.textWidth = ret[0].width;
resolve();
});
});
let boxQuery = new Promise((resolve, reject) => {
uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
.select(`#${this.elIdBox}`)
.boundingClientRect()
.exec((ret) => {
this.boxWidth = ret[0].width;
resolve();
});
});
query.push(textQuery);
query.push(boxQuery);
Promise.all(query).then(() => {
this.animationDuration = `${this.textWidth / this.speed}s`;
this.animationDelay = `-${this.boxWidth / this.speed}s`;
setTimeout(() => {
this.animationPlayState = 'running';
}, 1000);
});
// #endif
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['animationEle'], (res) => {
let winWidth = sheep.$platform.device.windowWidth;
this.textWidth = res.size.width;
animation.transition(
this.$refs['animationEle'],
{
styles: {
transform: `translateX(-${winWidth}px)`,
},
duration: 0,
timingFunction: 'linear',
delay: 0,
},
() => {
if (!this.stopAnimation) {
animation.transition(
this.$refs['animationEle'],
{
styles: {
transform: `translateX(-${this.textWidth}px)`,
},
timingFunction: 'linear',
duration: ((this.textWidth - winWidth) / this.speed) * 1000,
delay: 1000,
},
() => {
if (!this.stopAnimation) {
this.loopAnimation();
}
},
);
}
},
);
});
// #endif
}
// #ifdef APP-NVUE
if (!this.scrollable && (this.single || this.moreText)) {
dom.getComponentRect(this.$refs['textBox'], (res) => {
this.wrapWidth = res.size.width;
});
}
// #endif
},
loopAnimation() {
// #ifdef APP-NVUE
animation.transition(
this.$refs['animationEle'],
{
styles: {
transform: `translateX(0px)`,
},
duration: 0,
},
() => {
if (!this.stopAnimation) {
animation.transition(
this.$refs['animationEle'],
{
styles: {
transform: `translateX(-${this.textWidth}px)`,
},
duration: (this.textWidth / this.speed) * 1000,
timingFunction: 'linear',
delay: 0,
},
() => {
if (!this.stopAnimation) {
this.loopAnimation();
}
},
);
}
},
);
// #endif
},
clickMore() {
this.$emit('getmore');
},
close() {
this.show = false;
this.$emit('close');
},
onClick() {
this.$emit('click');
},
},
};
</script>
<style lang="scss" scoped>
.uni-noticebar {
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
box-sizing: border-box;
/* #endif */
flex-direction: row;
align-items: center;
padding: 10px 12px;
// margin-bottom: 10px;
}
.uni-cursor-point {
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-noticebar-close {
margin-left: 8px;
margin-right: 5px;
}
.uni-noticebar-icon {
margin-right: 5px;
}
.uni-noticebar__content-wrapper {
flex: 1;
flex-direction: column;
overflow: hidden;
}
.uni-noticebar__content-wrapper--single {
/* #ifndef APP-NVUE */
line-height: 18px;
/* #endif */
}
.uni-noticebar__content-wrapper--single,
.uni-noticebar__content-wrapper--scrollable {
flex-direction: row;
}
/* #ifndef APP-NVUE */
.uni-noticebar__content-wrapper--scrollable {
position: relative;
height: 18px;
}
/* #endif */
.uni-noticebar__content--scrollable {
/* #ifdef APP-NVUE */
flex: 0;
/* #endif */
/* #ifndef APP-NVUE */
flex: 1;
display: block;
overflow: hidden;
/* #endif */
}
.uni-noticebar__content--single {
/* #ifndef APP-NVUE */
display: flex;
flex: none;
width: 100%;
justify-content: center;
/* #endif */
}
.uni-noticebar__content-text {
font-size: 14px;
line-height: 18px;
/* #ifndef APP-NVUE */
word-break: break-all;
/* #endif */
}
.uni-noticebar__content-text--single {
/* #ifdef APP-NVUE */
lines: 1;
/* #endif */
/* #ifndef APP-NVUE */
display: block;
width: 100%;
white-space: nowrap;
/* #endif */
overflow: hidden;
text-overflow: ellipsis;
}
.uni-noticebar__content-text--scrollable {
/* #ifdef APP-NVUE */
lines: 1;
padding-left: 750rpx;
/* #endif */
/* #ifndef APP-NVUE */
position: absolute;
display: block;
height: 18px;
line-height: 18px;
white-space: nowrap;
padding-left: 100%;
animation: notice 10s 0s linear infinite both;
animation-play-state: paused;
/* #endif */
}
.uni-noticebar__more {
/* #ifndef APP-NVUE */
display: inline-flex;
/* #endif */
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
padding-left: 5px;
}
.uni-noticebar__more-text {
font-size: 14px;
}
@keyframes notice {
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>