@@ -1,148 +1,178 @@
< template >
< div class = "notice-bar" : style = "{ background, height: `${height}px` }" v-show = "!isMode" >
< div class = "notice-bar-warp" : style = "{ color, fontSize: `${size}px` }" >
< lay-icon v-if = "leftIcon" class="notice-bar-warp-left-icon" :type="leftIcon" > < / lay -icon >
< div class = "notice-bar-warp-text-box" ref = "noticeBarWarpRef" >
< div class = "notice-bar-warp-text" ref = "noticeBarTextRef" v-if = "!scrollable" > {{ text }} < / div >
< div class = "notice-bar-warp-slot" v-else > < slot / > < / div >
< / div >
< lay-icon :type = "rightIcon" v-if = "rightIcon" class="notice-bar-warp-right-icon" @click="onRightIconClick" > < / lay -icon >
< / div >
< / div >
< div
class = "notice-bar"
: style = "{ background, height: `${height}px` }"
v-show = "!isMode"
>
< div class = "notice-bar-warp" : style = "{ color, fontSize: `${size}px` }" >
< lay-icon
v-if = "leftIcon"
class = "notice-bar-warp-left-icon"
:type = "leftIcon"
> < / lay-icon >
< div class = "notice-bar-warp-text-box" ref = "noticeBarWarpRef" >
< div
class = "notice-bar-warp-text"
ref = "noticeBarTextRef"
v-if = "!scrollable"
>
{ { text } }
< / div >
< div class = "notice-bar-warp-slot" v-else > < slot / > < / div >
< / div >
< lay-icon
:type = "rightIcon"
v-if = "rightIcon"
class = "notice-bar-warp-right-icon"
@click ="onRightIconClick"
> < / lay-icon >
< / div >
< / div >
< / template >
< script lang = "ts" >
import { toRefs , reactive , defineComponent , ref , onMounted , nextTick } from 'vue' ;
import {
toRefs ,
reactive ,
defineComponent ,
ref ,
onMounted ,
nextTick ,
} from "vue" ;
export default defineComponent ( {
name : ' LayNoticeBar' ,
props : {
// 选值为 closeable link
mode : {
type : String ,
default : ( ) => '' ,
} ,
// 通知文本内容
text : {
type : String ,
default : ( ) => '' ,
} ,
// 通知文本颜色
color : {
type : String ,
default : ( ) => ' var(--color-warning)' ,
} ,
// 通知背景色
background : {
type : String ,
default : ( ) => ' var(--color-warning-light-9)' ,
} ,
// 字体大小, 单位px
size : {
type : [ Number , String ] ,
default : ( ) => 14 ,
} ,
// 通知栏高度, 单位px
height : {
type : Number ,
default : ( ) => 40 ,
} ,
// 动画延迟时间 (s)
delay : {
type : Number ,
default : ( ) => 1 ,
} ,
// 滚动速率 (px/s)
speed : {
type : Number ,
default : ( ) => 100 ,
} ,
// 是否开启垂直滚动
scrollable : {
type : Boolean ,
default : ( ) => false ,
} ,
// 自定义左侧图标
leftIcon : {
type : String ,
default : ( ) => '' ,
} ,
// 自定义右侧图标
rightIcon : {
type : String ,
default : ( ) => '' ,
} ,
} ,
setup ( props , { emit } ) {
const noticeBarWarpRef = ref ( ) ;
const noticeBarTextRef = ref ( ) ;
const state = reactive ( {
order : 1 ,
oneTime : 0 ,
twoTime : 0 ,
warpOWidth : 0 ,
textOWidth : 0 ,
isMode : false ,
} ) ;
// 初始化 animation 各项参数
const initAnimation = ( ) => {
nextTick ( ( ) => {
state . warpOWidth = noticeBarWarpRef . value . offsetWidth ;
state . textOWidth = noticeBarTextRef . value . offsetWidth ;
document . styleSheets [ 0 ] . insertRule ( ` @keyframes oneAnimation {0% {left: 0px;} 100% {left: - ${ state . textOWidth } px;}} ` ) ;
document . styleSheets [ 0 ] . insertRule ( ` @keyframes two Animation {0% {left: ${ state . warpOWidth } px;} 100% {left: - ${ state . textOWidth } px;}} ` ) ;
computeAnimationTime ( ) ;
setTimeout ( ( ) => {
changeAnimation ( ) ;
} , props . delay * 1000 ) ;
} ) ;
} ;
// 计算 animation 滚动时长
const computeAnimationTime = ( ) => {
state . oneTime = state . textOWidth / props . speed ;
state . twoTime = ( state . textOWidth + state . warpOWidth ) / props . speed ;
} ;
// 改变 animation 动画调用
const changeAnimation = ( ) => {
if ( state . order === 1 ) {
noticeBarTextRef . value . style . cssText = ` animation: oneAnimation ${ state . oneTime } s linear; opactity: 1;} ` ;
state . order = 2 ;
} else {
noticeBarTextRef . value . style . cssText = ` animation: twoAnimation ${ state . twoTime } s linear infinite; opacity: 1; ` ;
}
} ;
// 监听 animation 动画的结束
const listenerAnimationend = ( ) => {
noticeBarTextRef . value . addEventListener (
'animationend' ,
( ) => {
changeAnimation ( ) ;
} ,
false
) ;
} ;
// 右侧 icon 图标点击
const onRightIconClick = ( ) => {
if ( ! props . mode ) return false ;
if ( props . mode === 'closeable' ) {
state . isMode = true ;
emit ( 'close' ) ;
} else if ( props . mode === 'link' ) {
emit ( 'link' ) ;
}
} ;
// 页面加载时
onMounted ( ( ) => {
if ( props . scrollable ) return false ;
initAnimation ( ) ;
listenerAnimationend ( ) ;
} ) ;
return {
noticeBarWarpRef ,
noticeBarTextRef ,
onRightIconClick ,
... toRefs ( state ) ,
} ;
} ,
name : " LayNoticeBar" ,
props : {
// 选值为 closeable link
mode : {
type : String ,
default : ( ) => "" ,
} ,
// 通知文本内容
text : {
type : String ,
default : ( ) => "" ,
} ,
// 通知文本颜色
color : {
type : String ,
default : ( ) => " var(--color-warning)" ,
} ,
// 通知背景色
background : {
type : String ,
default : ( ) => " var(--color-warning-light-9)" ,
} ,
// 字体大小, 单位px
size : {
type : [ Number , String ] ,
default : ( ) => 14 ,
} ,
// 通知栏高度, 单位px
height : {
type : Number ,
default : ( ) => 40 ,
} ,
// 动画延迟时间 (s)
delay : {
type : Number ,
default : ( ) => 1 ,
} ,
// 滚动速率 (px/s)
speed : {
type : Number ,
default : ( ) => 100 ,
} ,
// 是否开启垂直滚动
scrollable : {
type : Boolean ,
default : ( ) => false ,
} ,
// 自定义左侧图标
leftIcon : {
type : String ,
default : ( ) => "" ,
} ,
// 自定义右侧图标
rightIcon : {
type : String ,
default : ( ) => "" ,
} ,
} ,
setup ( props , { emit } ) {
const noticeBarWarpRef = ref ( ) ;
const noticeBarTextRef = ref ( ) ;
const state = reactive ( {
order : 1 ,
oneTime : 0 ,
twoTime : 0 ,
warpOWidth : 0 ,
textOWidth : 0 ,
isMode : false ,
} ) ;
// 初始化 animation 各项参数
const initAnimation = ( ) => {
nextTick ( ( ) => {
state . warpOWidth = noticeBarWarpRef . value . offsetWidth ;
state . textOWidth = noticeBarTextRef . value . offsetWidth ;
document . styleSheets [ 0 ] . insertRule (
` @keyframes one Animation {0% {left: 0 px;} 100% {left: - ${ state . textOWidth } px;}} `
) ;
document . styleSheets [ 0 ] . insertRule (
` @keyframes twoAnimation {0% {left: ${ state . warpOWidth } px;} 100% {left: - ${ state . textOWidth } px;}} `
) ;
computeAnimationTime ( ) ;
setTimeout ( ( ) => {
changeAnimation ( ) ;
} , props . delay * 1000 ) ;
} ) ;
} ;
// 计算 animation 滚动时长
const computeAnimationTime = ( ) => {
state . oneTime = state . textOWidth / props . speed ;
state . twoTime = ( state . textOWidth + state . warpOWidth ) / props . speed ;
} ;
// 改变 animation 动画调用
const changeAnimation = ( ) => {
if ( state . order === 1 ) {
noticeBarTextRef . value . style . cssText = ` animation: oneAnimation ${ state . oneTime } s linear; opactity: 1;} ` ;
state . order = 2 ;
} else {
noticeBarTextRef . value . style . cssText = ` animation: twoAnimation ${ state . twoTime } s linear infinite; opacity: 1; ` ;
}
} ;
// 监听 animation 动画的结束
const listenerAnimationend = ( ) => {
noticeBarTextRef . value . addEventListener (
"animationend" ,
( ) => {
changeAnimation ( ) ;
} ,
false
) ;
} ;
// 右侧 icon 图标点击
const onRightIconClick = ( ) => {
if ( ! props . mode ) return false ;
if ( props . mode === "closeable" ) {
state . isMode = true ;
emit ( "close" ) ;
} else if ( props . mode === "link" ) {
emit ( "link" ) ;
}
} ;
// 页面加载时
onMounted ( ( ) => {
if ( props . scrollable ) return false ;
initAnimation ( ) ;
listenerAnimationend ( ) ;
} ) ;
return {
noticeBarWarpRef ,
noticeBarTextRef ,
onRightIconClick ,
... toRefs ( state ) ,
} ;
} ,
} ) ;
< / script >
@@ -175,7 +205,11 @@ export default defineComponent({
width : 100 % ;
white - space : nowrap ;
}
. notice - bar . notice - bar - warp . notice - bar - warp - text - box . notice - bar - warp - slot : : v - deep ( . el - carousel _ _item ) {
. notice - bar
. notice - bar - warp
. notice - bar - warp - text - box
. notice - bar - warp - slot
: : v - deep ( . el - carousel _ _item ) {
display : flex ;
align - items : center ;
}