基于angular6的滚动条组件

简要说明:依赖于angular6框架,也可以延伸到其他框架。

scroll-bar.directive.ts 

import { Directive, HostBinding, ElementRef, Host, HostListener } from '@angular/core';
import { hostElement } from '@angular/core/src/render3/instructions';
import { Overlay } from '@angular/cdk/overlay';

@Directive({
  selector: '[appScrollBar]',
})
export class ScrollBarDirective {
  target: ElementRef;
  scrollContainer: HTMLDivElement = document.createElement('div');
  scrollBar: HTMLDivElement = document.createElement('div');
  inited = false;
  visible = false;
  scale = 1;
  triggerClick = false;
  clientHeight = 0;
  scrollHieght = 0;
  scrollBarWidth = 0;
  dragLength = 0;
  preTick = 0;
  timer = 0;
  step = 100; // 定义拖拽的速度,如果设置的过小,会一定概率出现误差
  @HostBinding('style.overflow-y') OverlayY = 'hidden';
  @HostBinding('style.margin-right') marginRight = '0';
  @HostListener('mouseenter') initScrollBar(e) {
    if (!this.inited) {
      this.initEvent();
      this.initScrollHeight();
      this.append();
      this.inited = true;
    }
    this.scrollContainer.style.visibility = 'visible';
  }
  @HostListener('mouseleave') hiddenScroll() {
    this.scrollContainer.style.visibility = 'hidden';
  }
  constructor(private e: ElementRef) {
    this.scrollBarWidth = this.getScrollbarWidth();
    this.target = e;
    this.scrollContainer.setAttribute('class', 'scroll-container');
    this.scrollBar.setAttribute('class', 'scroll-bar');
  }
  initScrollHeight() {
    const ele = this.target.nativeElement, clientHeight = this.clientHeight = ele.clientHeight,
      scrollHeight = this.scrollHieght = ele.scrollHeight;
    this.scale = clientHeight / scrollHeight;
    if (this.scale >= 1) {
      this.OverlayY = 'hidden';
      this.hiddenScroll();
    } else {
      this.marginRight = `-${this.scrollBarWidth}px`;
      this.OverlayY = 'scroll';
    }
    ele.style.position = 'relative';
    this.scrollBar.style.height = clientHeight * this.scale + 'px';
    this.scrollContainer.style.height = clientHeight * 1 + 'px';
  }
  append() {
    this.scrollContainer.appendChild(this.scrollBar);
    this.target.nativeElement.appendChild(this.scrollContainer);
  }
  initEvent() {
    window.onresize = () => {
      this.inited = false;
    };
    const ele = this.target.nativeElement;
    this.scrollBar.onmouseup = this.removeTrigger;
    this.scrollBar.onmouseleave = this.removeTrigger;
    this.target.nativeElement.onscroll = (e) => {
      if(ele.scrollHeight !== this.scrollHieght) {
        this.inited = false;
        this.initScrollHeight();
      }
      this.scrollContainer.style.top = ele.scrollTop * 1 + 'px';
      this.scrollBar.style.top = ele.scrollTop * this.scale + 'px';
    };
    this.scrollBar.draggable = true;
    this.scrollBar.ondragstart = (e) => {
      this.triggerClick = true;
      this.preTick = e.clientY || e.y;
    };
    this.scrollBar.ondrag = (e) => {
      if (Date.now() - this.timer < 15) {
        return false;
      }
      const height = e.clientY || e.y;
      if (height === 0 && this.preTick > this.step) {
        console.log(this.preTick);
        return false;
      }
      this.dragLength = height - this.preTick;
      this.timer = Date.now();
      ele.scrollTop += this.dragLength / this.scale;
      this.preTick = height;
    };
    this.scrollBar.ondragover = (e) => {
      const height = e.clientY || e.y;
      this.dragLength = height - this.preTick;
      ele.scrollTop += this.dragLength / this.scale;
      e.preventDefault();
    };
  }
  removeTrigger = (e) => {
    this.triggerClick = false;
  }
  getScrollbarWidth() {
    const div: ElementDiv = document.createElement('div'),
      styles = {
        width: '100px',
        height: '100px',
        overflowY: 'scroll'
      };
    let scrollbarWidth;
    for (const i in styles) {
      if (i) {
        div.style[i] = styles[i];
      }
    }
    document.body.appendChild(div);
    scrollbarWidth = div.offsetWidth - div.clientWidth;
    try {
      div.remove();
    } catch (error) {
      div.removeNode(true);
    }
    return scrollbarWidth;
  }
}

interface ElementDiv extends HTMLElement {
  removeNode?: (e) => {};
}

 

[appScrollBar] {
    position: relative;
    overflow-x: hidden;
    overflow-y: hidden;
    .scroll-container {
        position: absolute;
        width: 8px;
        border-radius: 3px;
        background: rgba($color: #000000, $alpha: 0.2);
        top: 0px;
        right: 0px;
        z-index: 999;

        .scroll-bar {
            position: absolute;
            width: 8px;
            border-radius: 3px;
            background: rgba(77, 119, 119, 0.8);
            top: 0px;
            right: 0px;
            z-index: 1000;
            cursor: pointer;
        }
    }
}

app.moddule.ts

基于angular6的滚动条组件_第1张图片

三:简单效果图

基于angular6的滚动条组件_第2张图片

你可能感兴趣的:(基于angular6的滚动条组件)