UNPKG

@visactor/vrender-components

Version:

components library for dp visualization

205 lines (195 loc) 10.8 kB
import { vglobal } from "@visactor/vrender-core"; import { merge, normalizePadding, clamp, clampRange, debounce, throttle, isValid } from "@visactor/vutils"; import { AbstractComponent } from "../core/base"; import { loadScrollbarComponent } from "./register"; import { SCROLLBAR_START_EVENT, SCROLLBAR_EVENT, SCROLLBAR_END_EVENT } from "../constant"; import { getEndTriggersOfDrag } from "../util/event"; const delayMap = { debounce: debounce, throttle: throttle }; loadScrollbarComponent(); export class ScrollBar extends AbstractComponent { constructor(attributes, options) { super((null == options ? void 0 : options.skipDefault) ? attributes : merge({}, ScrollBar.defaultAttributes, attributes)), this.name = "scrollbar", this._handleTouchMove = e => { isValid(this._prePos) && e.preventDefault(); }, this._onRailPointerDown = e => { const {viewX: viewX, viewY: viewY} = e, {direction: direction, width: width, height: height, range: range} = this.attribute, sliderSize = this._sliderSize, [min, max] = this._getScrollRange(); let currentScrollValue; if ("vertical" === direction) { const relativeY = viewY - this._viewPosition.y, currentYPos = clamp(relativeY - sliderSize / 2, min, max); currentScrollValue = relativeY / height, this._slider.setAttribute("y", currentYPos, !0); } else { const relativeX = viewX - this._viewPosition.x, currentXPos = clamp(relativeX - sliderSize / 2, min, max); currentScrollValue = relativeX / width, this._slider.setAttribute("x", currentXPos, !0); } this.setScrollRange([ currentScrollValue - (range[1] - range[0]) / 2, currentScrollValue + (range[1] - range[0]) / 2 ], !1), this.stage && !this.stage.autoRender && this.stage.renderNextFrame(); }, this._onSliderPointerDown = e => { this._clearDragEvents(); const {stopSliderDownPropagation: stopSliderDownPropagation = !0} = this.attribute; stopSliderDownPropagation && e.stopPropagation(); const {direction: direction} = this.attribute, {x: x, y: y} = this.stage.eventPointTransform(e); this._prePos = "horizontal" === direction ? x : y, this._dispatchEvent(SCROLLBAR_START_EVENT, { pos: this._prePos, event: e }); const triggers = getEndTriggersOfDrag(), obj = "browser" === vglobal.env ? vglobal : this.stage; obj.addEventListener("pointermove", this._onSliderPointerMoveWithDelay, { capture: !0 }), triggers.forEach((trigger => { obj.addEventListener(trigger, this._onSliderPointerUp); })); }, this._computeScrollValue = e => { const {direction: direction} = this.attribute, {x: x, y: y} = this.stage.eventPointTransform(e); let currentScrollValue, currentPos, delta = 0; const {width: width, height: height} = this.getSliderRenderBounds(); return "vertical" === direction ? (currentPos = y, delta = currentPos - this._prePos, currentScrollValue = delta / height) : (currentPos = x, delta = currentPos - this._prePos, currentScrollValue = delta / width), [ currentPos, currentScrollValue ]; }, this._onSliderPointerMove = e => { const {stopSliderMovePropagation: stopSliderMovePropagation = !0} = this.attribute; stopSliderMovePropagation && e.stopPropagation(); const preScrollRange = this.getScrollRange(), [currentPos, currentScrollValue] = this._computeScrollValue(e); this.setScrollRange([ preScrollRange[0] + currentScrollValue, preScrollRange[1] + currentScrollValue ], !0), this._prePos = currentPos; }, this._onSliderPointerMoveWithDelay = 0 === this.attribute.delayTime ? this._onSliderPointerMove : delayMap[this.attribute.delayType](this._onSliderPointerMove, this.attribute.delayTime), this._onSliderPointerUp = e => { const {range: preRange, limitRange: limitRange = [ 0, 1 ]} = this.attribute, preScrollRange = this.getScrollRange(), [currentPos, currentScrollValue] = this._computeScrollValue(e), range = [ preScrollRange[0] + currentScrollValue, preScrollRange[1] + currentScrollValue ]; this._prePos = null, this._dispatchEvent(SCROLLBAR_END_EVENT, { pre: preRange, value: clampRange(range, limitRange[0], limitRange[1]) }), this._clearDragEvents(); }; } setScrollRange(range, render = !0) { const {direction: direction = "horizontal", limitRange: limitRange = [ 0, 1 ], range: preRange, realTime: realTime = !0} = this.attribute, currScrollRange = clampRange(range, limitRange[0], limitRange[1]); if (render) { const sliderPos = this._getSliderPos(currScrollRange); if (this._slider) { const sliderSize = sliderPos[1] - sliderPos[0]; this._sliderSize = sliderSize, "horizontal" === direction ? this._slider.setAttributes({ x: sliderPos[0], width: sliderSize }, !0) : this._slider.setAttributes({ y: sliderPos[0], height: sliderSize }, !0), this.stage && !this.stage.autoRender && this.stage.renderNextFrame(); } } this.attribute.range = currScrollRange, realTime && this._dispatchEvent(SCROLLBAR_EVENT, { pre: preRange, value: currScrollRange }); } getScrollRange() { return this.attribute.range; } bindEvents() { if (this.attribute.disableTriggerEvent) return; const {delayType: delayType = "throttle", delayTime: delayTime = 0} = this.attribute; this._rail && this._rail.addEventListener("pointerdown", delayMap[delayType](this._onRailPointerDown, delayTime)), this._slider && this._slider.addEventListener("pointerdown", this._onSliderPointerDown), ("browser" === vglobal.env ? vglobal : this.stage).addEventListener("touchmove", this._handleTouchMove, { passive: !1 }); } render() { this._reset(); const {direction: direction = "horizontal", width: width, height: height, range: range, limitRange: limitRange = [ 0, 1 ], railStyle: railStyle, sliderStyle: sliderStyle, padding: padding = 2} = this.attribute, group = this.createOrUpdateChild("scrollbar-container", {}, "group"), rail = group.createOrUpdateChild("scrollbar-rail", Object.assign({ x: 0, y: 0, width: width, height: height }, railStyle), "rect"); this._rail = rail; const sliderRenderBounds = this.getSliderRenderBounds(), sliderPos = this._getSliderPos(clampRange(range, limitRange[0], limitRange[1])), sliderSize = sliderPos[1] - sliderPos[0]; let sliderAttribute; this._sliderSize = sliderSize, sliderAttribute = "horizontal" === direction ? { x: sliderPos[0], y: sliderRenderBounds.y1, width: sliderSize, height: sliderRenderBounds.height } : { x: sliderRenderBounds.x1, y: sliderPos[0], width: sliderRenderBounds.width, height: sliderSize }; const slider = group.createOrUpdateChild("slider", Object.assign(Object.assign(Object.assign(Object.assign({}, sliderAttribute), { cornerRadius: this._getDefaultSliderCornerRadius() }), sliderStyle), { boundsPadding: normalizePadding(padding), pickMode: "imprecise" }), "rect"); this._slider = slider, this._container = group; const containerAABBBounds = this._container.AABBBounds; this._viewPosition = { x: containerAABBBounds.x1, y: containerAABBBounds.y1 }; } getSliderRenderBounds() { if (this._sliderRenderBounds) return this._sliderRenderBounds; const {width: width, height: height, padding: padding = 2} = this.attribute, [top, right, bottom, left] = normalizePadding(padding), renderBounds = { x1: left, y1: top, x2: width - right, y2: height - bottom, width: Math.max(0, width - (left + right)), height: Math.max(0, height - (top + bottom)) }; return this._sliderRenderBounds = renderBounds, renderBounds; } _getDefaultSliderCornerRadius() { const {direction: direction, round: round} = this.attribute; if (round) { const {width: width, height: height} = this.getSliderRenderBounds(); return "horizontal" === direction ? height : width; } return 0; } _getSliderPos(range) { const {direction: direction} = this.attribute, {width: width, height: height, x1: x1, y1: y1} = this.getSliderRenderBounds(); return "horizontal" === direction ? [ width * range[0] + x1, width * range[1] + x1 ] : [ height * range[0] + y1, height * range[1] + y1 ]; } _getScrollRange() { if (this._sliderLimitRange) return this._sliderLimitRange; const {limitRange: limitRange = [ 0, 1 ], direction: direction} = this.attribute, [min, max] = clampRange(limitRange, 0, 1), {width: width, height: height, x1: x1, y1: y1} = this.getSliderRenderBounds(), sliderSize = this._sliderSize; return "horizontal" === direction ? clampRange([ x1 + min * width, x1 + max * width ], x1, width - sliderSize) : clampRange([ y1 + min * height, y1 + max * height ], y1, height - sliderSize); } _clearDragEvents() { const triggers = getEndTriggersOfDrag(), obj = "browser" === vglobal.env ? vglobal : this.stage; obj.removeEventListener("pointermove", this._onSliderPointerMoveWithDelay, { capture: !0 }), triggers.forEach((trigger => { obj.removeEventListener(trigger, this._onSliderPointerUp); })); } _reset() { this._sliderRenderBounds = null, this._sliderLimitRange = null; } release(all) { super.release(all), ("browser" === vglobal.env ? vglobal : this.stage).addEventListener("touchmove", this._handleTouchMove, { passive: !1 }), this._clearDragEvents(); } } ScrollBar.defaultAttributes = { direction: "horizontal", round: !0, sliderSize: 20, sliderStyle: { fill: "rgba(0, 0, 0, .5)" }, railStyle: { fill: "rgba(0, 0, 0, .0)" }, padding: 2, scrollRange: [ 0, 1 ], delayType: "throttle", delayTime: 0, realTime: !0 }; //# sourceMappingURL=scrollbar.js.map