BUG: #150442 - 添加消息通知组展开动效

This commit is contained in:
luojiahao 2022-12-27 14:14:15 +08:00
parent 6ca0c2beaa
commit e8319eaca6
3 changed files with 150 additions and 41 deletions

View File

@ -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;

View File

@ -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>

View File

@ -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 {