optimize:web Optimize NestedSlider scrolling
This commit is contained in:
parent
0cf75592ae
commit
b087730090
105
doric-web/dist/index.js
vendored
105
doric-web/dist/index.js
vendored
@ -8590,6 +8590,66 @@ var doric_web = (function (exports, axios, sandbox) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getX(ev) {
|
||||||
|
return ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX;
|
||||||
|
}
|
||||||
|
function getY(ev) {
|
||||||
|
return ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY;
|
||||||
|
}
|
||||||
|
function NestedSliderView(props) {
|
||||||
|
const ret = document.createElement("div");
|
||||||
|
ret.style.overflow = "hidden";
|
||||||
|
ret.style.display = "inline";
|
||||||
|
ret.style.whiteSpace = "nowrap";
|
||||||
|
let touch = {
|
||||||
|
touchStartX: 0,
|
||||||
|
touchStartY: 0,
|
||||||
|
currentIndex: 0,
|
||||||
|
isDragging: false,
|
||||||
|
horizontal: true
|
||||||
|
};
|
||||||
|
ret.ontouchstart = ret.onmousedown = (ev) => {
|
||||||
|
if (!props.scrollable())
|
||||||
|
return;
|
||||||
|
touch = Object.assign(Object.assign({}, touch), { currentIndex: Math.round(ret.scrollLeft / ret.offsetWidth), touchStartX: getX(ev), touchStartY: getY(ev), isDragging: true });
|
||||||
|
};
|
||||||
|
ret.ontouchmove = ret.onmousemove = (ev) => {
|
||||||
|
if (!props.scrollable() || !touch.isDragging)
|
||||||
|
return;
|
||||||
|
if (!touch.horizontal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Math.abs(getX(ev) - touch.touchStartX) < Math.abs(getY(ev) - touch.touchStartY)) {
|
||||||
|
touch.horizontal = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const offsetX = (touch.touchStartX - getX(ev)) * 1.2;
|
||||||
|
ret.scrollTo({
|
||||||
|
left: touch.currentIndex * ret.offsetWidth + offsetX,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
ret.onmouseup = ret.ontouchcancel = ret.ontouchend = () => {
|
||||||
|
if (!props.scrollable())
|
||||||
|
return;
|
||||||
|
touch = Object.assign(Object.assign({}, touch), { isDragging: false, horizontal: true });
|
||||||
|
let originIndex = touch.currentIndex;
|
||||||
|
if (Math.abs(ret.scrollLeft - originIndex * ret.offsetWidth) > ret.offsetWidth / 5) {
|
||||||
|
const positionOffset = Math.abs(ret.scrollLeft) > originIndex * ret.offsetWidth ? 1 : -1;
|
||||||
|
touch.currentIndex += positionOffset;
|
||||||
|
}
|
||||||
|
ret.scrollTo({
|
||||||
|
left: touch.currentIndex * ret.offsetWidth,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
if (originIndex !== touch.currentIndex) {
|
||||||
|
if (props.onPageSelected) {
|
||||||
|
props.onPageSelected(touch.currentIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
class DoricNestedSliderNode extends DoricGroupViewNode {
|
class DoricNestedSliderNode extends DoricGroupViewNode {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
@ -8613,50 +8673,13 @@ var doric_web = (function (exports, axios, sandbox) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
build() {
|
build() {
|
||||||
const ret = document.createElement("div");
|
return NestedSliderView({
|
||||||
ret.style.overflow = "hidden";
|
scrollable: () => this.scrollable, onPageSelected: index => {
|
||||||
ret.style.display = "inline";
|
|
||||||
ret.style.whiteSpace = "nowrap";
|
|
||||||
let touchStartX = 0;
|
|
||||||
let currentIndex = 0;
|
|
||||||
let isDragging = false;
|
|
||||||
const handleTouchStart = (x) => {
|
|
||||||
if (!this.scrollable)
|
|
||||||
return;
|
|
||||||
currentIndex = Math.round(ret.scrollLeft / ret.offsetWidth);
|
|
||||||
touchStartX = x;
|
|
||||||
isDragging = true;
|
|
||||||
};
|
|
||||||
ret.onmousedown = (ev) => handleTouchStart(ev.pageX);
|
|
||||||
ret.ontouchstart = (ev) => handleTouchStart(ev.touches[0].pageX);
|
|
||||||
const handleTouchMove = (x) => {
|
|
||||||
if (!this.scrollable || !isDragging)
|
|
||||||
return;
|
|
||||||
const offsetX = (touchStartX - x) * 3;
|
|
||||||
ret.scrollTo({
|
|
||||||
left: currentIndex * ret.offsetWidth + offsetX,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
ret.onmousemove = (ev) => handleTouchMove(ev.pageX);
|
|
||||||
ret.ontouchmove = (ev) => handleTouchMove(ev.touches[0].pageX);
|
|
||||||
const handleTouchCancel = () => {
|
|
||||||
if (!this.scrollable)
|
|
||||||
return;
|
|
||||||
isDragging = false;
|
|
||||||
let originInndex = currentIndex;
|
|
||||||
currentIndex = Math.round(ret.scrollLeft / ret.offsetWidth);
|
|
||||||
ret.scrollTo({
|
|
||||||
left: currentIndex * ret.offsetWidth,
|
|
||||||
behavior: "smooth",
|
|
||||||
});
|
|
||||||
if (originInndex !== currentIndex) {
|
|
||||||
if (this.onPageSelectedFuncId.length > 0) {
|
if (this.onPageSelectedFuncId.length > 0) {
|
||||||
this.callJSResponse(this.onPageSelectedFuncId, currentIndex);
|
this.callJSResponse(this.onPageSelectedFuncId, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
ret.onmouseup = ret.ontouchcancel = ret.ontouchend = handleTouchCancel;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
layout() {
|
layout() {
|
||||||
super.layout();
|
super.layout();
|
||||||
|
2
doric-web/dist/index.js.map
vendored
2
doric-web/dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +1,6 @@
|
|||||||
|
import { horizontalList } from 'doric';
|
||||||
import { DoricGroupViewNode } from "./DoricViewNode";
|
import { DoricGroupViewNode } from "./DoricViewNode";
|
||||||
|
import { NestedSliderView } from '../widgets/NestedSliderView';
|
||||||
|
|
||||||
export class DoricNestedSliderNode extends DoricGroupViewNode {
|
export class DoricNestedSliderNode extends DoricGroupViewNode {
|
||||||
onPageSelectedFuncId = "";
|
onPageSelectedFuncId = "";
|
||||||
@ -19,47 +21,13 @@ export class DoricNestedSliderNode extends DoricGroupViewNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
const ret = document.createElement("div");
|
return NestedSliderView({
|
||||||
ret.style.overflow = "hidden";
|
scrollable: () => this.scrollable, onPageSelected: index => {
|
||||||
ret.style.display = "inline";
|
|
||||||
ret.style.whiteSpace = "nowrap";
|
|
||||||
let touchStartX = 0;
|
|
||||||
let currentIndex = 0;
|
|
||||||
let isDragging = false;
|
|
||||||
const handleTouchStart = (x: number) => {
|
|
||||||
if (!this.scrollable) return;
|
|
||||||
currentIndex = Math.round(ret.scrollLeft / ret.offsetWidth);
|
|
||||||
touchStartX = x;
|
|
||||||
isDragging = true;
|
|
||||||
};
|
|
||||||
ret.onmousedown = (ev) => handleTouchStart(ev.pageX);
|
|
||||||
ret.ontouchstart = (ev) => handleTouchStart(ev.touches[0].pageX);
|
|
||||||
const handleTouchMove = (x: number) => {
|
|
||||||
if (!this.scrollable || !isDragging) return;
|
|
||||||
const offsetX = (touchStartX - x) * 3;
|
|
||||||
ret.scrollTo({
|
|
||||||
left: currentIndex * ret.offsetWidth + offsetX,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
ret.onmousemove = (ev) => handleTouchMove(ev.pageX);
|
|
||||||
ret.ontouchmove = (ev) => handleTouchMove(ev.touches[0].pageX);
|
|
||||||
const handleTouchCancel = () => {
|
|
||||||
if (!this.scrollable) return;
|
|
||||||
isDragging = false;
|
|
||||||
let originInndex = currentIndex;
|
|
||||||
currentIndex = Math.round(ret.scrollLeft / ret.offsetWidth);
|
|
||||||
ret.scrollTo({
|
|
||||||
left: currentIndex * ret.offsetWidth,
|
|
||||||
behavior: "smooth",
|
|
||||||
});
|
|
||||||
if (originInndex !== currentIndex) {
|
|
||||||
if (this.onPageSelectedFuncId.length > 0) {
|
if (this.onPageSelectedFuncId.length > 0) {
|
||||||
this.callJSResponse(this.onPageSelectedFuncId, currentIndex);
|
this.callJSResponse(this.onPageSelectedFuncId, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
ret.onmouseup = ret.ontouchcancel = ret.ontouchend = handleTouchCancel;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(): void {
|
layout(): void {
|
||||||
|
75
doric-web/src/widgets/NestedSliderView.ts
Normal file
75
doric-web/src/widgets/NestedSliderView.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
function getX(ev: MouseEvent | TouchEvent) {
|
||||||
|
return ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX
|
||||||
|
}
|
||||||
|
|
||||||
|
function getY(ev: MouseEvent | TouchEvent) {
|
||||||
|
return ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
scrollable: () => boolean,
|
||||||
|
onPageSelected?: (index: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function NestedSliderView(props: Props) {
|
||||||
|
const ret = document.createElement("div");
|
||||||
|
ret.style.overflow = "hidden";
|
||||||
|
ret.style.display = "inline";
|
||||||
|
ret.style.whiteSpace = "nowrap";
|
||||||
|
let touch = {
|
||||||
|
touchStartX: 0,
|
||||||
|
touchStartY: 0,
|
||||||
|
currentIndex: 0,
|
||||||
|
isDragging: false,
|
||||||
|
horizontal: true
|
||||||
|
}
|
||||||
|
ret.ontouchstart = ret.onmousedown = (ev: MouseEvent | TouchEvent) => {
|
||||||
|
if (!props.scrollable()) return;
|
||||||
|
touch = {
|
||||||
|
...touch,
|
||||||
|
currentIndex: Math.round(ret.scrollLeft / ret.offsetWidth),
|
||||||
|
touchStartX: getX(ev),
|
||||||
|
touchStartY: getY(ev),
|
||||||
|
isDragging: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ret.ontouchmove = ret.onmousemove = (ev: MouseEvent | TouchEvent) => {
|
||||||
|
if (!props.scrollable() || !touch.isDragging) return;
|
||||||
|
if (!touch.horizontal) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Math.abs(getX(ev) - touch.touchStartX) < Math.abs(getY(ev) - touch.touchStartY)) {
|
||||||
|
touch.horizontal = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const offsetX = (touch.touchStartX - getX(ev)) * 1.2;
|
||||||
|
ret.scrollTo({
|
||||||
|
left: touch.currentIndex * ret.offsetWidth + offsetX,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
ret.onmouseup = ret.ontouchcancel = ret.ontouchend = () => {
|
||||||
|
if (!props.scrollable()) return;
|
||||||
|
touch = {
|
||||||
|
...touch,
|
||||||
|
isDragging: false,
|
||||||
|
horizontal: true,
|
||||||
|
}
|
||||||
|
let originIndex = touch.currentIndex;
|
||||||
|
if (Math.abs(ret.scrollLeft - originIndex * ret.offsetWidth) > ret.offsetWidth / 5) {
|
||||||
|
const positionOffset = Math.abs(ret.scrollLeft) > originIndex * ret.offsetWidth ? 1 : -1;
|
||||||
|
touch.currentIndex += positionOffset;
|
||||||
|
}
|
||||||
|
ret.scrollTo({
|
||||||
|
left: touch.currentIndex * ret.offsetWidth,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
if (originIndex !== touch.currentIndex) {
|
||||||
|
if (props.onPageSelected) {
|
||||||
|
props.onPageSelected(touch.currentIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return ret
|
||||||
|
}
|
Reference in New Issue
Block a user