Vue: Encapsulate the vertical scrolling gradient mask layer component

Description of Requirement

There are often pages in the system that need to be scrolled vertically. The upper and lower sides of the scrolling container are generally "solid", which will clearly cut off the scrolling content; if a gradient mask layer with the same color as the background is added to the top and bottom of the container, the scrolling content will be Produces a "fading in and out" effect, the comparison is as follows:
Normal scroll container vs. scroll container with gradient mask

Implementation points

1. The z-index of the gradient mask layer is higher than the container content. You need to add pointer-events: none to the mask layer; let the mouse "penetrate" to the lower layer; 2.
When the content scrolls to the top or bottom, it needs to be hidden The top or bottom mask layer prevents the display content from being blocked;
3. When the outer container has rounded corners, the inner content needs to be set with the same rounded corners, otherwise there will be bugs in the rounded corner effect when scrolling.

Reference Code

Attached here is the GradientCover code of the gradient mask layer component packaged by this miscellaneous fish, for reference only:

<!-- 在可垂直滚动的div上下增加渐变色遮罩层,且滚动到顶部或底部时隐藏遮罩层 -->
<template>
  <div id="GradientCover">
    <div v-show="showGradientCover[0]" class="gradientMask top" 
      :style="`height: ${coverHeight}px;margin-bottom: -${coverHeight}px;`"
    ></div>
    <div class="container" @scroll="scrollContent" ref="scrollContent"
      :style="`overflow: ${overflow};border-radius: 0 0 ${borderRadius}px ${borderRadius}px;`"
    >
      <slot></slot>
    </div>
    <div v-show="showGradientCover[1]" class="gradientMask bottom" 
      :style="`height: ${coverHeight}px;margin-top: -${coverHeight}px;border-radius: 0 0 ${borderRadius}px ${borderRadius}px;`"
    ></div>
  </div>
</template>

<script>
	export default {
    
    
		props: {
    
    
			overflow: {
    
     // 是否可滚动
				type: String,
				default: () => 'hidden'
			},
			coverHeight: {
    
     // 遮罩高度
				type: [String, Number],
				default: () => 32
			},
			borderRadius: {
    
     // 外层容器圆角
				type: [String, Number],
				default: () => 0
			}
		},
		data () {
    
    
			return {
    
    
				// 是否显示渐变遮罩层(初始处于顶部,不显示顶部遮罩,显示底部遮罩)
				showGradientCover: [ false, this.overflow !== 'hidden' ]
			}
		},
		watch: {
    
    
			overflow: {
    
    
				immediate: true,
				handler (newVal) {
    
     // 页面滚动样式变化时,更新遮罩层可见配置
					this.showGradientCover = [ false, newVal !== 'hidden' ]
				}
			}
		},
		methods: {
    
    
			scrollContent (e) {
    
    
				this.showGradientCover = [
					// 滚动到距离顶部<20px时,隐藏顶部渐变遮罩层;否则显示
					20 < e.srcElement.scrollTop, 
					// 滚动到距离底部<20px时,隐藏底部渐变遮罩层;否则显示
					e.srcElement.scrollTop + e.srcElement.offsetHeight + 20 
						< e.srcElement.scrollHeight
				]
			},
			scrollTop () {
    
     // 滚动到顶部
				this.$refs.scrollContent.scrollTop= 0
			}
		}
	}

</script>

<style lang="less" scoped>
	#GradientCover {
    
    
		height: 100%;
		width: 100%;

		.gradientMask {
    
    
			pointer-events: none;
			z-index: 100;
			position: relative;
			left: 0;
			width: calc(100% - 8px);

			&.top {
    
    
				top: 0;
				background: linear-gradient(180deg, #ffffff, transparent);
			}
			&.bottom {
    
    
				bottom: 0;
				background: linear-gradient(0deg, #ffffff, transparent);
			}
		}

		.container {
    
    
			width: 100%;
			height: 100%;
		}
	}
</style>

Guess you like

Origin blog.csdn.net/qq_36604536/article/details/130822295