BUG: #150442 - 添加消息通知组展开动效
This commit is contained in:
parent
6ca0c2beaa
commit
e8319eaca6
|
@ -5,24 +5,105 @@ import {
|
|||
eventOptions,
|
||||
queryAssignedElements,
|
||||
} from 'lit/decorators.js'
|
||||
import {StarNotification} from '../notification/notification.js'
|
||||
import {StarNotification} from '@star-web-components/notification'
|
||||
|
||||
@customElement('star-notification-group')
|
||||
export class StarNotificationGroup extends LitElement {
|
||||
_opacity: number = 0
|
||||
_show: boolean = false
|
||||
@property({type: Number}) count = 0
|
||||
@property({type: String}) id = ''
|
||||
@queryAssignedElements({flatten: true}) slotElements!:
|
||||
| HTMLSlotElement[]
|
||||
| StarNotification[]
|
||||
|
||||
get show() {
|
||||
return this._show
|
||||
}
|
||||
n = 0
|
||||
set show(value) {
|
||||
if (this._show !== value) {
|
||||
/* 暂时未填加手指按住滑动的控制, 变更show, 即在合并和展开之间二极切换 */
|
||||
if (value) {
|
||||
this.addGroupHeight(this._singleHeight * this.children.length)
|
||||
} else {
|
||||
this.addGroupHeight(0)
|
||||
}
|
||||
this.setAttribute('show', String(value))
|
||||
this._show = value
|
||||
}
|
||||
}
|
||||
|
||||
/* 控制单条消息具体内容的透明度 */
|
||||
set contentOpacity(value: number) {
|
||||
this._opacity = value
|
||||
this.style.setProperty('--single-noti-opacity', String(value))
|
||||
if (value !== 1) {
|
||||
this.style.setProperty('--single-noti-events', 'none')
|
||||
} else {
|
||||
this.style.removeProperty('--single-noti-events')
|
||||
}
|
||||
}
|
||||
|
||||
get contentOpacity() {
|
||||
return this._opacity
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知组的展开高度
|
||||
*/
|
||||
set containerHeight(value: number) {
|
||||
// 通知组DOM的最大高度, 为通知数量个数的高度之和
|
||||
const maxHeight = this._singleHeight * this.children.length
|
||||
if (value < (this._singleHeight ?? 0)) {
|
||||
// 小于单条通知高度时, 移除展开高度的控制, 显示为合并高度
|
||||
this.style.removeProperty('--expand-height')
|
||||
return
|
||||
} else if (value > maxHeight) {
|
||||
value = maxHeight
|
||||
}
|
||||
this.style.setProperty('--expand-height', value + 'px')
|
||||
}
|
||||
|
||||
/* 增加控制通知组容器高度 */
|
||||
addGroupHeight(value: number) {
|
||||
// 所有被隐藏的通知的展开动画的将会在滑动一个高度前完成
|
||||
let ratio = value / this._singleHeight
|
||||
ratio = ratio > 1 ? 1 : ratio
|
||||
ratio = ratio < 0 ? 0 : ratio
|
||||
this.contentOpacity = ratio
|
||||
this.containerHeight = value
|
||||
}
|
||||
|
||||
_singleHeight!: number
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
window.addEventListener('notification-delete', this)
|
||||
window.addEventListener('notification-touchmove', this)
|
||||
window.addEventListener('resize', this.resize)
|
||||
|
||||
// 用于监控自身高度变化, 用于第一时间设置自身高度
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
if ((this.children[0] as HTMLElement)?.offsetHeight) {
|
||||
this.resize()
|
||||
resizeObserver.unobserve(this)
|
||||
}
|
||||
})
|
||||
resizeObserver.observe(this)
|
||||
}
|
||||
|
||||
resize = () => {
|
||||
if (this.children.length) {
|
||||
// 获取单条通知高度, 并作为合并状态时的高度
|
||||
this._singleHeight = (this.children[0] as StarNotification).offsetHeight
|
||||
this.style.setProperty('--shrink-height', this._singleHeight + 'px')
|
||||
} else {
|
||||
this.addEventListener('slotchange', this.resize, {once: true})
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.setAttribute('show', 'false')
|
||||
this.show = false
|
||||
}
|
||||
|
||||
@eventOptions({passive: false})
|
||||
|
@ -36,7 +117,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
;(this.slotElements as StarNotification[]).forEach(
|
||||
(el: StarNotification) => {
|
||||
if (!el.noclear) {
|
||||
if (this.getAttribute('show') == 'false') {
|
||||
if (!this.show) {
|
||||
if (el.id == id) {
|
||||
// 删除某个notification-group
|
||||
this.dispatchEvent(
|
||||
|
@ -94,17 +175,17 @@ export class StarNotificationGroup extends LitElement {
|
|||
|
||||
if (slotLen == 1) {
|
||||
// group中只有一条消息,应该转为'one-notification'类型,并折叠
|
||||
this.setAttribute('show', 'false')
|
||||
firstChild.setAttribute(
|
||||
'notificationType',
|
||||
'group-with-one-notification'
|
||||
)
|
||||
this.show = false
|
||||
firstChild.withArrowUp = false
|
||||
firstChild.removeEventListener('notification-tap', allNotificationshown)
|
||||
} else if (slotLen > 1) {
|
||||
let lastChild = slotElements[slotLen - 1] as StarNotification
|
||||
|
||||
if (this.getAttribute('show') == 'true') {
|
||||
if (this.show) {
|
||||
// 展开
|
||||
firstChild.setAttribute('radiusType', 'top-border-radius')
|
||||
firstChild.setAttribute('notificationType', 'more-notifiactions')
|
||||
|
@ -156,6 +237,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
}
|
||||
|
||||
allNotificationshown(event: Event) {
|
||||
console.log('allNotificationshown')
|
||||
let firstChild = this.slotElements[0] as StarNotification
|
||||
if (firstChild !== event.target || this.slotElements.length == 1) {
|
||||
return
|
||||
|
@ -167,10 +249,12 @@ export class StarNotificationGroup extends LitElement {
|
|||
event.stopImmediatePropagation()
|
||||
}
|
||||
|
||||
let isShow = this.getAttribute('show') == 'true'
|
||||
let isShow = this.show
|
||||
console.log('hellowq allNotificationshown isShow: ', isShow)
|
||||
if (isShow) {
|
||||
// 当前是展开状态,点击需折叠
|
||||
let self = this
|
||||
this.show = false
|
||||
firstChild.setAttribute('radiusType', 'border-radius')
|
||||
firstChild.withArrowUp = false
|
||||
firstChild.setAttribute('notificationType', 'more-notifiactions-first')
|
||||
|
@ -179,7 +263,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
;(element as StarNotification).classList.add('animation-out')
|
||||
element.addEventListener('animationend', function tEnd() {
|
||||
if (index == self.slotElements.length - 1) {
|
||||
self.setAttribute('show', 'false')
|
||||
self.show = false
|
||||
self.dispatchEventFurther()
|
||||
}
|
||||
;(element as StarNotification).classList.remove('animation-out')
|
||||
|
@ -188,7 +272,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
}
|
||||
})
|
||||
} else {
|
||||
this.setAttribute('show', 'true')
|
||||
this.show = true
|
||||
this.dispatchEventFurther()
|
||||
this.slotElements.forEach((element) => {
|
||||
if (element !== firstChild) {
|
||||
|
@ -228,7 +312,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
|
||||
collapseNotifications() {
|
||||
let firstChild = this.slotElements[0] as StarNotification
|
||||
let isShow = this.getAttribute('show') == 'true'
|
||||
let isShow = this.show
|
||||
;(this.slotElements as StarNotification[]).forEach((element) => {
|
||||
element.closeNotificationTools()
|
||||
})
|
||||
|
@ -243,7 +327,7 @@ export class StarNotificationGroup extends LitElement {
|
|||
;(element as StarNotification).classList.add('animation-out')
|
||||
element.addEventListener('animationend', function tEnd() {
|
||||
if (index == self.slotElements.length - 1) {
|
||||
self.setAttribute('show', 'false')
|
||||
self.show = false
|
||||
self.preventDefaultBehavior(true)
|
||||
}
|
||||
;(element as StarNotification).classList.remove('animation-out')
|
||||
|
@ -264,15 +348,20 @@ export class StarNotificationGroup extends LitElement {
|
|||
:host {
|
||||
display: block;
|
||||
margin-top: var(--auto-16px);
|
||||
background: var(--notification-bgc);
|
||||
border-radius: var(--auto-20px);
|
||||
height: var(--expand-height, var(--shrink-height));
|
||||
transition: height 0.25s;
|
||||
|
||||
--notification-bgc: var(--opacity-white-55);
|
||||
--single-noti-opacity: 0;
|
||||
--single-noti-bgc: transparent;
|
||||
}
|
||||
|
||||
:host([show='false']) ::slotted(*) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host([show='false']) ::slotted(:first-child) {
|
||||
display: block;
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:host {
|
||||
--notification-bgc: var(--opacity-black-25);
|
||||
}
|
||||
}
|
||||
|
||||
:host([show='true']) ::slotted(*) {
|
||||
|
@ -295,6 +384,10 @@ export class StarNotificationGroup extends LitElement {
|
|||
animation: disappearing 0.25s cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
}
|
||||
|
||||
::slotted(*) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@keyframes disappearing {
|
||||
0% {
|
||||
opacity: 1;
|
||||
|
|
|
@ -122,11 +122,13 @@ export class StarNotification extends StarBaseElement {
|
|||
render(): HTMLTemplateResult | typeof nothing {
|
||||
switch (this.notificationType) {
|
||||
case NotificationType.ONE:
|
||||
case NotificationType.MORE:
|
||||
case NotificationType.GROUP_ONE:
|
||||
return this.getone()
|
||||
case NotificationType.MORE:
|
||||
case NotificationType.MORE_FIRST:
|
||||
return this.getmorefirst()
|
||||
return html`
|
||||
${this.getmorefirst()} ${this.getone()}
|
||||
`
|
||||
case NotificationType.BLUETOOTH_TRANSFER:
|
||||
return this.getbluetoothtransfer()
|
||||
default:
|
||||
|
@ -296,10 +298,10 @@ export class StarNotification extends StarBaseElement {
|
|||
const deleteShow =
|
||||
this.noclear == true
|
||||
? html`
|
||||
<div class="btn-tool-wrapper btn-tool-only-settings
|
||||
<div data-icon="settings" @click=${this}></div>
|
||||
</div>
|
||||
`
|
||||
<div class="btn-tool-wrapper btn-tool-only-settings">
|
||||
<div data-icon="settings" @click=${this}></div>
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
<div class="btn-tool-wrapper btn-tool">
|
||||
<div data-icon="delete" @click=${this}></div>
|
||||
|
|
|
@ -30,6 +30,7 @@ export const sharedStyles: CSSResult = css`
|
|||
position: relative;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:host([notificationType='bluetooth-transfer']) {
|
||||
|
@ -43,7 +44,6 @@ export const sharedStyles: CSSResult = css`
|
|||
}
|
||||
|
||||
.notification {
|
||||
// transition: transform 0.6s;
|
||||
transition: transform 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
height: inherit;
|
||||
width: inherit;
|
||||
|
@ -109,7 +109,7 @@ export const sharedStyles: CSSResult = css`
|
|||
width: 90.2%;
|
||||
height: 18.4%;
|
||||
left: 9.8%;
|
||||
top: 23.7%;
|
||||
top: 24%;
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
|
@ -153,9 +153,9 @@ export const sharedStyles: CSSResult = css`
|
|||
// font-size: 2vw;
|
||||
line-height: 1;
|
||||
// right: 3.7%;
|
||||
top: -2.6%;
|
||||
font-size: var(--auto-24px);
|
||||
right: var(--auto-32px);
|
||||
line-height: var(--auto-24px);
|
||||
}
|
||||
|
||||
.notification > div.detail {
|
||||
|
@ -163,7 +163,7 @@ export const sharedStyles: CSSResult = css`
|
|||
position: absolute;
|
||||
width: 90.2%;
|
||||
left: 9.8%;
|
||||
top: 55%;
|
||||
top: 58.65%;
|
||||
}
|
||||
|
||||
.notification > div.detail .detail-content {
|
||||
|
@ -241,7 +241,7 @@ export const sharedStyles: CSSResult = css`
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: inherit;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,9 @@ export const sharedStyles: CSSResult = css`
|
|||
// left: 28px;
|
||||
|
||||
width: 90.2%;
|
||||
height: var(--auto-48px);
|
||||
left: 9.8%;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
|
@ -340,6 +342,20 @@ export const sharedStyles: CSSResult = css`
|
|||
// font-size: 1.45vh;
|
||||
// font-size: 2.3vw;
|
||||
font-size: var(--auto-28px);
|
||||
line-height: var(--auto-38px);
|
||||
}
|
||||
|
||||
/* 打开通知组动画过程中时 */
|
||||
.more,
|
||||
.one {
|
||||
transition: opacity 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
}
|
||||
.one {
|
||||
opacity: var(--single-noti-opacity, 1);
|
||||
pointer-events: var(--single-noti-events, all);
|
||||
}
|
||||
.more {
|
||||
opacity: calc(1 - var(--single-noti-opacity, 1));
|
||||
}
|
||||
|
||||
.container .detail-content {
|
||||
|
@ -362,22 +378,18 @@ export const sharedStyles: CSSResult = css`
|
|||
|
||||
left: 0.93%;
|
||||
// top: -3px;
|
||||
top: -2%;
|
||||
// top: -2%;
|
||||
// top: -0.16vh;
|
||||
// font-size: 1.35vh;
|
||||
font-size: var(--auto-26px);
|
||||
}
|
||||
|
||||
.one-container {
|
||||
// top: 36px;
|
||||
// top: 12px;
|
||||
top: 23.7%;
|
||||
top: 20.7%;
|
||||
}
|
||||
|
||||
.another-container {
|
||||
// top: 89px;
|
||||
// top: 29px;
|
||||
top: 58.5%;
|
||||
top: 58.65%;
|
||||
}
|
||||
|
||||
.one-container .timestamp {
|
||||
|
@ -400,9 +412,8 @@ export const sharedStyles: CSSResult = css`
|
|||
|
||||
// height: 1.8vh;
|
||||
height: var(--auto-34px);
|
||||
right: 4%;
|
||||
top: -0.2vh;
|
||||
line-height: 1.7vh;
|
||||
right: var(--auto-32px);
|
||||
line-height: var(--auto-34px);
|
||||
// font-size: 2vw;
|
||||
font-size: var(--auto-24px);
|
||||
}
|
||||
|
@ -519,10 +530,13 @@ export const sharedStyles: CSSResult = css`
|
|||
mix-blend-mode: normal;
|
||||
opacity: 0.65;
|
||||
}
|
||||
.notification {
|
||||
background: var(--single-noti-bgc, var(--notification-bgc));
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
.notification {
|
||||
background: var(--notification-background-lm);
|
||||
:host {
|
||||
--notification-bgc: var(--notification-background-lm);
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
|
@ -571,8 +585,8 @@ export const sharedStyles: CSSResult = css`
|
|||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.notification {
|
||||
background: var(--notification-background-dm);
|
||||
:host {
|
||||
--notification-bgc: var(--notification-background-dm);
|
||||
}
|
||||
|
||||
.notification > div.detail .arrow-up {
|
||||
|
|
Loading…
Reference in New Issue