mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-07 17:07:19 +08:00
feat: add SeamlessScroll component
This commit is contained in:
parent
db237d2f51
commit
e09ed0fb47
@ -1,15 +1,545 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div ref="wrap">
|
||||
<div :style="leftSwitch" v-if="navigation" :class="leftSwitchClass" @click="leftSwitchClick">
|
||||
<slot name="left-switch"></slot>
|
||||
</div>
|
||||
<div :style="rightSwitch" v-if="navigation" :class="rightSwitchClass" @click="rightSwitchClick">
|
||||
<slot name="right-switch"></slot>
|
||||
</div>
|
||||
<div
|
||||
ref="realBox"
|
||||
:style="pos"
|
||||
@mouseenter="enter"
|
||||
@mouseleave="leave"
|
||||
@touchstart="touchStart"
|
||||
@touchmove="touchMove"
|
||||
@touchend="touchEnd"
|
||||
>
|
||||
<div ref="slotList" :style="float">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div v-html="copyHtml" :style="float"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts'>
|
||||
export default {
|
||||
name: "SeamlessScroll",
|
||||
setup() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
import {
|
||||
defineComponent,
|
||||
computed,
|
||||
ref,
|
||||
unref,
|
||||
watchEffect,
|
||||
nextTick,
|
||||
} from "vue";
|
||||
import { tryOnMounted, tryOnUnmounted, templateRef } from "@vueuse/core";
|
||||
import * as utilsMethods from "./utils";
|
||||
const { animationFrame, copyObj } = utilsMethods;
|
||||
animationFrame();
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
// move动画的animationFrame定时器
|
||||
let reqFrame = null;
|
||||
let startPos = null;
|
||||
// single 单步滚动的定时器
|
||||
let singleWaitTime = null;
|
||||
//记录touchStart时候的posY
|
||||
let startPosY = null;
|
||||
//记录touchStart时候的posX
|
||||
let startPosX = null;
|
||||
// mouseenter mouseleave 控制scrollMove()的开关
|
||||
let isHover = false;
|
||||
let ease = "ease-in";
|
||||
export default defineComponent({
|
||||
name: "SeamlessScroll",
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
classOption: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
emits: ["ScrollEnd"],
|
||||
setup(props, { emit }) {
|
||||
let xPos = ref(0);
|
||||
let yPos = ref(0);
|
||||
let delay = ref(0);
|
||||
let copyHtml = ref("");
|
||||
let height = ref(0);
|
||||
// 外容器宽度
|
||||
let width = ref(0);
|
||||
// 内容实际宽度
|
||||
let realBoxWidth = ref(0);
|
||||
let realBoxHeight = ref(0);
|
||||
|
||||
const wrap = templateRef<HTMLElement | null>("wrap", null);
|
||||
const slotList = templateRef<HTMLElement | null>("slotList", null);
|
||||
const realBox = templateRef<HTMLElement | null>("realBox", null);
|
||||
|
||||
let { data, classOption } = props;
|
||||
|
||||
let leftSwitchState = computed(() => {
|
||||
return unref(xPos) < 0;
|
||||
});
|
||||
|
||||
let rightSwitchState = computed(() => {
|
||||
return Math.abs(unref(xPos)) < unref(realBoxWidth) - unref(width);
|
||||
});
|
||||
|
||||
let defaultOption = computed(() => {
|
||||
return {
|
||||
//步长
|
||||
step: 1,
|
||||
//启动无缝滚动最小数据数
|
||||
limitMoveNum: 5,
|
||||
//是否启用鼠标hover控制
|
||||
hoverStop: true,
|
||||
// bottom 往下 top 往上(默认) left 向左 right 向右
|
||||
direction: "top",
|
||||
//开启移动端touch
|
||||
openTouch: true,
|
||||
//单条数据高度有值hoverStop关闭
|
||||
singleHeight: 0,
|
||||
//单条数据宽度有值hoverStop关闭
|
||||
singleWidth: 0,
|
||||
//单步停止等待时间
|
||||
waitTime: 1000,
|
||||
switchOffset: 30,
|
||||
autoPlay: true,
|
||||
navigation: false,
|
||||
switchSingleStep: 134,
|
||||
switchDelay: 400,
|
||||
switchDisabledClass: "disabled",
|
||||
// singleWidth/singleHeight 是否开启rem度量
|
||||
isSingleRemUnit: false,
|
||||
};
|
||||
});
|
||||
|
||||
let options = computed(() => {
|
||||
// @ts-ignore
|
||||
return copyObj({}, unref(defaultOption), classOption);
|
||||
});
|
||||
|
||||
let leftSwitchClass = computed(() => {
|
||||
return unref(leftSwitchState) ? "" : unref(options).switchDisabledClass;
|
||||
});
|
||||
|
||||
let rightSwitchClass = computed(() => {
|
||||
return unref(rightSwitchState) ? "" : unref(options).switchDisabledClass;
|
||||
});
|
||||
|
||||
let leftSwitch = computed(() => {
|
||||
return {
|
||||
position: "absolute",
|
||||
margin: `${unref(height) / 2}px 0 0 -${unref(options).switchOffset}px`,
|
||||
transform: "translate(-100%,-50%)",
|
||||
};
|
||||
});
|
||||
|
||||
let rightSwitch = computed(() => {
|
||||
return {
|
||||
position: "absolute",
|
||||
margin: `${unref(height) / 2}px 0 0 ${
|
||||
unref(width) + unref(options).switchOffset
|
||||
}px`,
|
||||
transform: "translateY(-50%)",
|
||||
};
|
||||
});
|
||||
|
||||
let isHorizontal = computed(() => {
|
||||
return (
|
||||
unref(options).direction !== "bottom" &&
|
||||
unref(options).direction !== "top"
|
||||
);
|
||||
});
|
||||
|
||||
let float = computed(() => {
|
||||
return unref(isHorizontal)
|
||||
? { float: "left", overflow: "hidden" }
|
||||
: { overflow: "hidden" };
|
||||
});
|
||||
|
||||
let pos = computed(() => {
|
||||
return {
|
||||
transform: `translate(${unref(xPos)}px,${unref(yPos)}px)`,
|
||||
transition: `all ${ease} ${unref(delay)}ms`,
|
||||
overflow: "hidden",
|
||||
};
|
||||
});
|
||||
|
||||
let navigation = computed(() => {
|
||||
return unref(options).navigation;
|
||||
});
|
||||
|
||||
let autoPlay = computed(() => {
|
||||
if (unref(navigation)) return false;
|
||||
return unref(options).autoPlay;
|
||||
});
|
||||
|
||||
let scrollSwitch = computed(() => {
|
||||
return data.length >= unref(options).limitMoveNum;
|
||||
});
|
||||
|
||||
let hoverStopSwitch = computed(() => {
|
||||
return unref(options).hoverStop && unref(autoPlay) && unref(scrollSwitch);
|
||||
});
|
||||
|
||||
let canTouchScroll = computed(() => {
|
||||
return unref(options).openTouch;
|
||||
});
|
||||
|
||||
let baseFontSize = computed(() => {
|
||||
return unref(options).isSingleRemUnit
|
||||
? parseInt(
|
||||
window.getComputedStyle(document.documentElement, null).fontSize
|
||||
)
|
||||
: 1;
|
||||
});
|
||||
|
||||
let realSingleStopWidth = computed(() => {
|
||||
return unref(options).singleWidth * unref(baseFontSize);
|
||||
});
|
||||
|
||||
let realSingleStopHeight = computed(() => {
|
||||
return unref(options).singleHeight * unref(baseFontSize);
|
||||
});
|
||||
|
||||
let step = computed(() => {
|
||||
let singleStep;
|
||||
let step = unref(options).step;
|
||||
if (unref(isHorizontal)) {
|
||||
singleStep = unref(realSingleStopWidth);
|
||||
} else {
|
||||
singleStep = unref(realSingleStopHeight);
|
||||
}
|
||||
if (singleStep > 0 && singleStep % step > 0) {
|
||||
throw "如果设置了单步滚动,step需是单步大小的约数,否则无法保证单步滚动结束的位置是否准确";
|
||||
}
|
||||
return step;
|
||||
});
|
||||
|
||||
function reset() {
|
||||
scrollCancle();
|
||||
scrollInitMove();
|
||||
}
|
||||
|
||||
function leftSwitchClick() {
|
||||
if (!unref(leftSwitchState)) return;
|
||||
// 小于单步距离
|
||||
if (Math.abs(unref(xPos)) < unref(options).switchSingleStep) {
|
||||
xPos.value = 0;
|
||||
return;
|
||||
}
|
||||
xPos.value += unref(options).switchSingleStep;
|
||||
}
|
||||
|
||||
function rightSwitchClick() {
|
||||
if (!unref(rightSwitchState)) return;
|
||||
// 小于单步距离
|
||||
if (
|
||||
unref(realBoxWidth) - unref(width) + unref(xPos) <
|
||||
unref(options).switchSingleStep
|
||||
) {
|
||||
xPos.value = unref(width) - unref(realBoxWidth);
|
||||
return;
|
||||
}
|
||||
xPos.value -= unref(options).switchSingleStep;
|
||||
}
|
||||
|
||||
function scrollCancle() {
|
||||
cancelAnimationFrame(reqFrame || "");
|
||||
}
|
||||
|
||||
function touchStart(e) {
|
||||
if (!unref(canTouchScroll)) return;
|
||||
let timer;
|
||||
//touches数组对象获得屏幕上所有的touch,取第一个touch
|
||||
const touch = e.targetTouches[0];
|
||||
const { waitTime, singleHeight, singleWidth } = unref(options);
|
||||
//取第一个touch的坐标值
|
||||
startPos = {
|
||||
x: touch.pageX,
|
||||
y: touch.pageY,
|
||||
};
|
||||
//记录touchStart时候的posY
|
||||
startPosY = unref(yPos);
|
||||
//记录touchStart时候的posX
|
||||
startPosX = unref(xPos);
|
||||
if (!!singleHeight && !!singleWidth) {
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
scrollCancle();
|
||||
}, waitTime + 20);
|
||||
} else {
|
||||
scrollCancle();
|
||||
}
|
||||
}
|
||||
|
||||
function touchMove(e) {
|
||||
//当屏幕有多个touch或者页面被缩放过,就不执行move操作
|
||||
if (
|
||||
!unref(canTouchScroll) ||
|
||||
e.targetTouches.length > 1 ||
|
||||
(e.scale && e.scale !== 1)
|
||||
)
|
||||
return;
|
||||
const touch = e.targetTouches[0];
|
||||
const { direction } = unref(options);
|
||||
let endPos = {
|
||||
x: touch.pageX - startPos.x,
|
||||
y: touch.pageY - startPos.y,
|
||||
};
|
||||
//阻止触摸事件的默认行为,即阻止滚屏
|
||||
e.preventDefault();
|
||||
//dir,1表示纵向滑动,0为横向滑动
|
||||
const dir = Math.abs(endPos.x) < Math.abs(endPos.y) ? 1 : 0;
|
||||
if (
|
||||
(dir === 1 && direction === "bottom") ||
|
||||
(dir === 1 && direction === "top")
|
||||
) {
|
||||
// 表示纵向滑动 && 运动方向为上下
|
||||
yPos.value = startPosY + endPos.y;
|
||||
} else if (
|
||||
(dir === 0 && direction === "left") ||
|
||||
(dir === 0 && direction === "right")
|
||||
) {
|
||||
// 为横向滑动 && 运动方向为左右
|
||||
xPos.value = startPosX + endPos.x;
|
||||
}
|
||||
}
|
||||
|
||||
function touchEnd() {
|
||||
if (!unref(canTouchScroll)) return;
|
||||
let timer;
|
||||
const direction = unref(options).direction;
|
||||
delay.value = 50;
|
||||
if (direction === "top") {
|
||||
if (unref(yPos) > 0) yPos.value = 0;
|
||||
} else if (direction === "bottom") {
|
||||
let h = (unref(realBoxHeight) / 2) * -1;
|
||||
if (unref(yPos) < h) yPos.value = h;
|
||||
} else if (direction === "left") {
|
||||
if (unref(xPos) > 0) xPos.value = 0;
|
||||
} else if (direction === "right") {
|
||||
let w = unref(realBoxWidth) * -1;
|
||||
if (unref(xPos) < w) xPos.value = w;
|
||||
}
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
delay.value = 0;
|
||||
scrollMove();
|
||||
}, unref(delay));
|
||||
}
|
||||
|
||||
function enter() {
|
||||
if (unref(hoverStopSwitch)) scrollStopMove();
|
||||
}
|
||||
|
||||
function leave() {
|
||||
if (unref(hoverStopSwitch)) scrollStartMove();
|
||||
}
|
||||
|
||||
function scrollMove() {
|
||||
// 鼠标移入时拦截scrollMove()
|
||||
if (isHover) return;
|
||||
//进入move立即先清除动画 防止频繁touchMove导致多动画同时进行
|
||||
scrollCancle();
|
||||
reqFrame = requestAnimationFrame(function () {
|
||||
//实际高度
|
||||
const h = unref(realBoxHeight) / 2;
|
||||
//宽度
|
||||
const w = unref(realBoxWidth) / 2;
|
||||
let { direction, waitTime } = unref(options);
|
||||
if (direction === "top") {
|
||||
// 上
|
||||
if (Math.abs(unref(yPos)) >= h) {
|
||||
emit("ScrollEnd");
|
||||
yPos.value = 0;
|
||||
}
|
||||
yPos.value -= step.value;
|
||||
} else if (direction === "bottom") {
|
||||
// 下
|
||||
if (unref(yPos) >= 0) {
|
||||
emit("ScrollEnd");
|
||||
yPos.value = h * -1;
|
||||
}
|
||||
yPos.value += step.value;
|
||||
} else if (direction === "left") {
|
||||
// 左
|
||||
if (Math.abs(unref(xPos)) >= w) {
|
||||
emit("ScrollEnd");
|
||||
xPos.value = 0;
|
||||
}
|
||||
xPos.value -= step.value;
|
||||
} else if (direction === "right") {
|
||||
// 右
|
||||
if (unref(xPos) >= 0) {
|
||||
emit("ScrollEnd");
|
||||
xPos.value = w * -1;
|
||||
}
|
||||
xPos.value += step.value;
|
||||
}
|
||||
if (singleWaitTime) clearTimeout(singleWaitTime);
|
||||
if (!!unref(realSingleStopHeight)) {
|
||||
//是否启动了单行暂停配置
|
||||
if (
|
||||
Math.abs(unref(yPos)) % unref(realSingleStopHeight) <
|
||||
unref(step)
|
||||
) {
|
||||
// 符合条件暂停waitTime
|
||||
singleWaitTime = setTimeout(() => {
|
||||
scrollMove();
|
||||
}, waitTime);
|
||||
} else {
|
||||
scrollMove();
|
||||
}
|
||||
} else if (!!unref(realSingleStopWidth)) {
|
||||
if (
|
||||
Math.abs(unref(xPos)) % unref(realSingleStopWidth) <
|
||||
unref(step)
|
||||
) {
|
||||
// 符合条件暂停waitTime
|
||||
singleWaitTime = setTimeout(() => {
|
||||
scrollMove();
|
||||
}, waitTime);
|
||||
} else {
|
||||
scrollMove();
|
||||
}
|
||||
} else {
|
||||
scrollMove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scrollInitMove() {
|
||||
nextTick(() => {
|
||||
const { switchDelay } = unref(options);
|
||||
//清空copy
|
||||
copyHtml.value = "";
|
||||
if (unref(isHorizontal)) {
|
||||
height.value = unref(wrap).offsetHeight;
|
||||
width.value = unref(wrap).offsetWidth;
|
||||
let slotListWidth = unref(slotList).offsetWidth;
|
||||
// 水平滚动设置warp width
|
||||
if (unref(autoPlay)) {
|
||||
// 修正offsetWidth四舍五入
|
||||
slotListWidth = slotListWidth * 2 + 1;
|
||||
}
|
||||
unref(realBox).style.width = slotListWidth + "px";
|
||||
realBoxWidth.value = slotListWidth;
|
||||
}
|
||||
|
||||
if (unref(autoPlay)) {
|
||||
ease = "ease-in";
|
||||
delay.value = 0;
|
||||
} else {
|
||||
ease = "linear";
|
||||
delay.value = switchDelay;
|
||||
return;
|
||||
}
|
||||
|
||||
// 是否可以滚动判断
|
||||
if (unref(scrollSwitch)) {
|
||||
let timer;
|
||||
if (timer) clearTimeout(timer);
|
||||
copyHtml.value = unref(slotList).innerHTML;
|
||||
setTimeout(() => {
|
||||
realBoxHeight.value = unref(realBox).offsetHeight;
|
||||
scrollMove();
|
||||
}, 0);
|
||||
} else {
|
||||
scrollCancle();
|
||||
yPos.value = xPos.value = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scrollStartMove() {
|
||||
//开启scrollMove
|
||||
isHover = false;
|
||||
scrollMove();
|
||||
}
|
||||
|
||||
function scrollStopMove() {
|
||||
//关闭scrollMove
|
||||
isHover = true;
|
||||
// 防止频频hover进出单步滚动,导致定时器乱掉
|
||||
if (singleWaitTime) clearTimeout(singleWaitTime);
|
||||
scrollCancle();
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
const watchData = data;
|
||||
if (!watchData) return;
|
||||
nextTick(() => {
|
||||
reset();
|
||||
});
|
||||
|
||||
const watchAutoPlay = unref(autoPlay);
|
||||
if (watchAutoPlay) {
|
||||
reset();
|
||||
} else {
|
||||
scrollStopMove();
|
||||
}
|
||||
});
|
||||
|
||||
tryOnMounted(() => {
|
||||
scrollInitMove();
|
||||
});
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
scrollCancle();
|
||||
clearTimeout(singleWaitTime);
|
||||
});
|
||||
|
||||
return {
|
||||
xPos,
|
||||
yPos,
|
||||
delay,
|
||||
copyHtml,
|
||||
height,
|
||||
width,
|
||||
realBoxWidth,
|
||||
leftSwitchState,
|
||||
rightSwitchState,
|
||||
defaultOption,
|
||||
options,
|
||||
leftSwitchClass,
|
||||
rightSwitchClass,
|
||||
leftSwitch,
|
||||
rightSwitch,
|
||||
isHorizontal,
|
||||
float,
|
||||
pos,
|
||||
navigation,
|
||||
autoPlay,
|
||||
scrollSwitch,
|
||||
hoverStopSwitch,
|
||||
canTouchScroll,
|
||||
baseFontSize,
|
||||
realSingleStopWidth,
|
||||
realSingleStopHeight,
|
||||
step,
|
||||
reset,
|
||||
leftSwitchClick,
|
||||
rightSwitchClick,
|
||||
scrollCancle,
|
||||
touchStart,
|
||||
touchMove,
|
||||
touchEnd,
|
||||
enter,
|
||||
leave,
|
||||
scrollMove,
|
||||
scrollInitMove,
|
||||
scrollStartMove,
|
||||
scrollStopMove,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @desc AnimationFrame简单兼容hack
|
||||
*/
|
||||
const animationFrame = () => {
|
||||
export const animationFrame = () => {
|
||||
window.cancelAnimationFrame = (function () {
|
||||
return window.cancelAnimationFrame ||
|
||||
window.webkitCancelAnimationFrame ||
|
||||
@ -31,7 +31,7 @@ const animationFrame = () => {
|
||||
* @param {arr1,arr2}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
const arrayEqual = (arr1: Array<any>, arr2: Array<any>) => {
|
||||
export const arrayEqual = (arr1: Array<any>, arr2: Array<any>) => {
|
||||
if (arr1 === arr2) return true
|
||||
if (arr1.length !== arr2.length) return false
|
||||
for (let i = 0; i < arr1.length; ++i) {
|
||||
@ -43,7 +43,7 @@ const arrayEqual = (arr1: Array<any>, arr2: Array<any>) => {
|
||||
/**
|
||||
* @desc 深浅合并拷贝
|
||||
*/
|
||||
function copyObj() {
|
||||
export function copyObj() {
|
||||
if (!Array.isArray) {
|
||||
// @ts-expect-error
|
||||
Array.isArray = function (arg) {
|
||||
@ -104,11 +104,5 @@ function copyObj() {
|
||||
return target
|
||||
}
|
||||
|
||||
export default {
|
||||
animationFrame,
|
||||
arrayEqual,
|
||||
copyObj
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -18,5 +18,6 @@
|
||||
"cropping": "图片裁剪",
|
||||
"countTo": "数字动画",
|
||||
"selector": "选择器组件",
|
||||
"flowChart": "流程图"
|
||||
"flowChart": "流程图",
|
||||
"seamless": "无缝滚动"
|
||||
}
|
@ -18,5 +18,6 @@
|
||||
"cropping": "Picture Cropping",
|
||||
"countTo": "Digital Animation",
|
||||
"selector": "Selector Components",
|
||||
"flowChart": "flow Chart"
|
||||
"flowChart": "flow Chart",
|
||||
"seamless": "Seamless Scroll"
|
||||
}
|
@ -104,6 +104,15 @@ const routes: Array<RouteRecordRaw> = [
|
||||
savedPosition: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/components/seamlessScroll',
|
||||
component: () => import(/* webpackChunkName: "components" */ '../views/components/seamless-scroll/index.vue'),
|
||||
meta: {
|
||||
title: 'seamless',
|
||||
showLink: false,
|
||||
savedPosition: true
|
||||
}
|
||||
}
|
||||
// {
|
||||
// path: '/components/flowChart',
|
||||
// component: () => import(/* webpackChunkName: "components" */ '../views/components/flow-chart/index.vue'),
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div style="margin: 10px">
|
||||
<div class="cropper-container">
|
||||
<Cropper ref="refCropper" :width="'45vw'" :src="img" />
|
||||
<Cropper ref="refCropper" :width="'40vw'" :src="img" />
|
||||
<img :src="cropperImg" class="croppered" v-if="cropperImg" />
|
||||
</div>
|
||||
<el-button type="primary" @click="onCropper">裁剪</el-button>
|
||||
|
126
src/views/components/seamless-scroll/index.vue
Normal file
126
src/views/components/seamless-scroll/index.vue
Normal file
@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<el-space wrap>
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>无缝滚动示例</span>
|
||||
<el-button class="button" type="text" @click="changeDirection('top')">向上滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('bottom')">向下滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('left')">向左滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('right')">向右滚动</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<SeamlessScroll ref="scroll" :data="listData" :class-option="classOption" class="warp">
|
||||
<ul class="item">
|
||||
<li v-for="(item, index) in listData" :key="index">
|
||||
<span class="title" v-text="item.title"></span>
|
||||
<span class="date" v-text="item.date"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</SeamlessScroll>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</template>
|
||||
|
||||
<script lang='ts'>
|
||||
import { ref, unref } from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
|
||||
import SeamlessScroll from "/@/components/SeamlessScroll";
|
||||
export default {
|
||||
components: {
|
||||
SeamlessScroll,
|
||||
},
|
||||
setup() {
|
||||
const scroll = templateRef<HTMLElement | null>("scroll", null);
|
||||
|
||||
let listData = ref([
|
||||
{
|
||||
title: "无缝滚动第一行无缝滚动第一行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第二行无缝滚动第二行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第三行无缝滚动第三行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第四行无缝滚动第四行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第五行无缝滚动第五行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第六行无缝滚动第六行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第七行无缝滚动第七行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第八行无缝滚动第八行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
{
|
||||
title: "无缝滚动第九行无缝滚动第九行",
|
||||
date: "2021-5-1",
|
||||
},
|
||||
]);
|
||||
|
||||
let classOption = ref({
|
||||
direction: "top",
|
||||
});
|
||||
|
||||
function changeDirection(val) {
|
||||
scroll.value.scrollInitMove();
|
||||
classOption.value.direction = val;
|
||||
}
|
||||
|
||||
return {
|
||||
listData,
|
||||
classOption,
|
||||
changeDirection,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box-card {
|
||||
margin: 10px;
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
.warp {
|
||||
height: 270px;
|
||||
width: 360px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
li,
|
||||
a {
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user