feat:滚动标题
This commit is contained in:
parent
f7cdcce8cb
commit
b71ba53a9c
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -18,7 +18,6 @@ declare module 'vue' {
|
||||
CustomEchartPictorialBar: typeof import('./src/components/custom-echart-pictorial-bar/index.vue')['default']
|
||||
CustomEchartPie: typeof import('./src/components/custom-echart-pie/index.vue')['default']
|
||||
CustomEchartPie3d: typeof import('./src/components/custom-echart-pie-3d/index.vue')['default']
|
||||
CustomEchartPieCircle: typeof import('./src/components/custom-echart-pie-circle/index.vue')['default']
|
||||
CustomEchartPieGauge: typeof import('./src/components/custom-echart-pie-gauge/index.vue')['default']
|
||||
CustomEchartRadar: typeof import('./src/components/custom-echart-radar/index.vue')['default']
|
||||
CustomEchartScatterBlister: typeof import('./src/components/custom-echart-scatter-blister/index.vue')['default']
|
||||
@ -29,6 +28,7 @@ declare module 'vue' {
|
||||
CustomRankList: typeof import('./src/components/custom-rank-list/index.vue')['default']
|
||||
CustomRichEditor: typeof import('./src/components/custom-rich-editor/index.vue')['default']
|
||||
CustomScrollBoard: typeof import('./src/components/custom-scroll-board/index.vue')['default']
|
||||
CustomScrollTitle: typeof import('./src/components/custom-scroll-title/index.vue')['default']
|
||||
CustomTableOperate: typeof import('./src/components/custom-table-operate/index.vue')['default']
|
||||
CustomTableTree: typeof import('./src/components/custom-table-tree/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
|
@ -129,103 +129,90 @@ const handlePlay = () => {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.carousel {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
&-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
&-list {
|
||||
flex: 3;
|
||||
|
||||
:deep(.el-scrollbar__bar) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:deep(.el-scrollbar__view) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-item {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 10px;
|
||||
border: 2px solid #fff;
|
||||
text-align: center;
|
||||
border: 2px solid #ffffff;
|
||||
border-radius: 4px;
|
||||
background: var(--el-color-danger-light-9);
|
||||
text-align: center;
|
||||
color: var(--el-color-danger);
|
||||
background: var(--el-color-danger-light-9);
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-arrow {
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
|
||||
.el-icon {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 auto;
|
||||
line-height: 40px;
|
||||
font-size: 32px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&-video {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 300px;
|
||||
|
||||
&-picture {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&-video {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
&-btn {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 12;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-left: -25px;
|
||||
margin-top: -25px;
|
||||
border-radius: 25px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
margin-top: -25px;
|
||||
margin-left: -25px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 25px;
|
||||
background: rgb(0 0 0 / 20%);
|
||||
flex-direction: row;
|
||||
cursor: pointer;
|
||||
|
||||
.el-icon {
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,12 +91,12 @@ defineExpose({
|
||||
<style lang="scss" scoped>
|
||||
.import {
|
||||
&-tips {
|
||||
@include flex-row();
|
||||
@include flex-row;
|
||||
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
color: #979797;
|
||||
|
||||
p {
|
||||
flex: 3;
|
||||
}
|
||||
|
@ -178,53 +178,46 @@ onUnmounted(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.go-tables-rank {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.row-item {
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ranking-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
font-size: 13px;
|
||||
align-items: center;
|
||||
|
||||
.rank {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.info-name {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.ranking-column {
|
||||
border-bottom: 2px solid #1370fb80;
|
||||
margin-top: 5px;
|
||||
|
||||
border-bottom: 2px solid #1370fb80;
|
||||
.inside-column {
|
||||
position: relative;
|
||||
height: 6px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 1px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 2px;
|
||||
height: 6px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.shine {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
top: 2px;
|
||||
height: 2px;
|
||||
left: 0%;
|
||||
width: 50px;
|
||||
height: 2px;
|
||||
background: radial-gradient(rgb(40 248 255) 5%, transparent 80%);
|
||||
transform: translateX(-100%);
|
||||
background: radial-gradient(rgb(40, 248, 255) 5%, transparent 80%);
|
||||
animation: shine 3s ease-in-out infinite alternate;
|
||||
}
|
||||
}
|
||||
@ -235,7 +228,6 @@ onUnmounted(() => {
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 100%;
|
||||
transform: translateX(0%);
|
||||
|
@ -157,8 +157,8 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.rich-editor {
|
||||
border: 1px solid $color-border;
|
||||
z-index: 9999;
|
||||
border: 1px solid $color-border;
|
||||
&-toolbar {
|
||||
border-bottom: 1px solid $color-border;
|
||||
:deep(.w-e-bar-divider) {
|
||||
|
@ -332,34 +332,29 @@ onUnmounted(() => {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
|
||||
color: #ffffff;
|
||||
.text {
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0 10px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 15px;
|
||||
|
||||
.header-item {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.rows {
|
||||
overflow: hidden;
|
||||
|
||||
.row-item {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
191
src/components/custom-scroll-title/index.vue
Normal file
191
src/components/custom-scroll-title/index.vue
Normal file
@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<section class="header_title" :style="{ '--titleContentW': titleContentW + 'px', '--itemW': itemW + 'px', '--gap': gap + 'px' }">
|
||||
<el-button icon="el-icon-arrow-left" class="left_btn" @click="handleTitleBtn(1)"></el-button>
|
||||
<el-button icon="el-icon-arrow-right" class="right_btn" @click="handleTitleBtn(-1)"></el-button>
|
||||
<section class="left_titles_container">
|
||||
<section class="title_content" :style="{ left: `-${position}px` }">
|
||||
<section
|
||||
v-for="(item, i) in leftTitles"
|
||||
:key="`left_title_${i}`"
|
||||
:class="['title_item', activeTitle == item.value ? 'active' : '']"
|
||||
@click="handleTitleClick(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section class="right_titles_container">
|
||||
<section class="title_content" :style="{ left: `${right ? right + 'px' : '-' + position + 'px'}` }">
|
||||
<section
|
||||
v-for="(item, i) in rightTitles"
|
||||
:key="`right_title_${i}`"
|
||||
:class="['title_item', activeTitle == item.value ? 'active' : '']"
|
||||
@click="handleTitleClick(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
|
||||
onMounted(() => {
|
||||
handleWidth();
|
||||
});
|
||||
const emit = defineEmits(['changeTitle']);
|
||||
const props = defineProps({
|
||||
titles: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [
|
||||
{ label: '标题1', value: '1' },
|
||||
{ label: '标题2', value: '2' },
|
||||
{ label: '标题3', value: '3' },
|
||||
{ label: '标题4', value: '4' },
|
||||
{ label: '标题5', value: '5' },
|
||||
{ label: '标题6', value: '6' },
|
||||
{ label: '标题7', value: '7' },
|
||||
{ label: '标题8', value: '8' },
|
||||
{ label: '标题9', value: '9' },
|
||||
{ label: '标题10', value: '10' },
|
||||
{ label: '标题11', value: '11' },
|
||||
{ label: '标题12', value: '12' },
|
||||
{ label: '标题13', value: '13' },
|
||||
{ label: '标题14', value: '14' },
|
||||
{ label: '标题15', value: '15' },
|
||||
{ label: '标题16', value: '16' },
|
||||
{ label: '标题17', value: '17' },
|
||||
{ label: '标题18', value: '18' },
|
||||
{ label: '标题19', value: '19' },
|
||||
];
|
||||
},
|
||||
},
|
||||
});
|
||||
const titleContentW = ref('0');
|
||||
const itemW = ref('1');
|
||||
const gap = ref(24);
|
||||
const leftNum = ref(0);
|
||||
const position = ref(0);
|
||||
const right = ref(null);
|
||||
const activeTitle = ref('1');
|
||||
const leftTitles = ref([]);
|
||||
const rightTitles = ref([]);
|
||||
|
||||
watch(
|
||||
() => props.titles,
|
||||
(val) => {
|
||||
if (val && val.length) {
|
||||
let l = val.length;
|
||||
if (l > 6) {
|
||||
leftTitles.value = val.slice(0, l - 3);
|
||||
rightTitles.value = val.slice(3);
|
||||
} else {
|
||||
leftTitles.value = val.slice(0, 3);
|
||||
if (l > 3) {
|
||||
rightTitles.value = val.slice(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
function handleWidth() {
|
||||
let ld = document.querySelector('.left_titles_container');
|
||||
let w = ld.clientWidth;
|
||||
itemW.value = (w - 2 * gap.value) / 3;
|
||||
titleContentW.value = itemW.value * leftTitles.value.length + leftTitles.value.length * gap.value;
|
||||
if (props.titles.length > 3 && props.titles.length < 6) {
|
||||
let l = 3 - (props.titles.length - 3);
|
||||
right.value = l * itemW.value + (l - 1) * gap.value;
|
||||
}
|
||||
}
|
||||
function handleTitleBtn(t = -1) {
|
||||
if (props.titles.length > 6) {
|
||||
if (leftNum.value > -1) leftNum.value = leftNum.value + t;
|
||||
if (leftNum.value < 0) leftNum.value = 0;
|
||||
if (leftNum.value > leftTitles.value.length - 3) leftNum.value = leftTitles.value.length - 3;
|
||||
position.value = leftNum.value * itemW.value + leftNum.value * gap.value;
|
||||
}
|
||||
}
|
||||
function handleTitleClick(val) {
|
||||
activeTitle.value = val;
|
||||
emit('changeTitle', val);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.header_title {
|
||||
background-color: #f5f5f5;
|
||||
position: relative;
|
||||
padding: 0 68px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100vw;
|
||||
height: 60px;
|
||||
// background: url('./headerBG.png') no-repeat center/cover;
|
||||
background-color: skyblue;
|
||||
.left_btn,
|
||||
.right_btn {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
padding: 6px 6px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: rgb(39, 172, 255);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
user-select: none;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
.left_btn {
|
||||
left: 14px;
|
||||
}
|
||||
.right_btn {
|
||||
right: 14px;
|
||||
}
|
||||
.left_titles_container,
|
||||
.right_titles_container {
|
||||
position: relative;
|
||||
width: 30%;
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
.title_content {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
width: var(--titleContentW);
|
||||
height: 40px;
|
||||
transition: all 0.4s ease;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #f5f5f5;
|
||||
.active {
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 2px red;
|
||||
}
|
||||
.title_item {
|
||||
margin-right: var(--gap);
|
||||
display: inline-block;
|
||||
width: var(--itemW);
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
// background: url('./titleBG.png') no-repeat center/cover;
|
||||
background-color: aquamarine;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -86,33 +86,28 @@ const handleNodeClick = (data, node) => {
|
||||
<style lang="scss" scoped>
|
||||
.custom-table-tree {
|
||||
width: 100%;
|
||||
min-width: 200px;
|
||||
height: 100%;
|
||||
min-height: 400px;
|
||||
min-width: 200px;
|
||||
@include flex-column();
|
||||
|
||||
@include flex-column;
|
||||
&__shadow {
|
||||
box-shadow: 2px 0px 5px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 2px 0 5px rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 36px;
|
||||
padding: 0 20px;
|
||||
line-height: 36px;
|
||||
border-radius: 4px;
|
||||
height: 36px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
background: var(--el-color-primary);
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 16px 10px 10px;
|
||||
|
||||
&-filter {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-tree {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import CustomEchartPieGauge from './custom-echart-pie-gauge';
|
||||
import CustomEchartWordCloud from './custom-echart-word-cloud';
|
||||
import customEchartScatterBlister from './custom-echart-scatter-blister';
|
||||
import customEchartMaps from './custom-echart-maps';
|
||||
import customScrollTitle from './custom-scroll-title';
|
||||
|
||||
export {
|
||||
SvgIcon,
|
||||
@ -42,4 +43,5 @@ export {
|
||||
CustomEchartWordCloud,
|
||||
customEchartScatterBlister,
|
||||
customEchartMaps,
|
||||
customScrollTitle,
|
||||
};
|
||||
|
@ -66,16 +66,15 @@ const styleExternalIcon = computed(() => {
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
overflow: hidden;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
fill: currentcolor;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover !important;
|
||||
display: inline-block;
|
||||
background-color: currentcolor;
|
||||
mask-size: cover !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -32,6 +32,12 @@ export const constantRoutes = [
|
||||
// ],
|
||||
// },
|
||||
...demoRouters,
|
||||
{
|
||||
path: '/test',
|
||||
name: 'test',
|
||||
component: () => import('@/views/test/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
@import 'common/base';
|
||||
@import 'common/define';
|
||||
|
||||
#app {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@ -8,8 +7,9 @@
|
||||
font-family: Avenir, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background-color: #fff;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
// .el-dialog__body {
|
||||
// overflow: hidden auto;
|
||||
// height: auto;
|
||||
|
@ -52,12 +52,11 @@ const options = ref({
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.demo {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
margin: 30px auto 0;
|
||||
padding: 50px;
|
||||
background-color: #999;
|
||||
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
background-color: #999999;
|
||||
&-title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -38,11 +38,10 @@ const boardOption = ref({
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.demo {
|
||||
margin: 30px auto 0;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
margin: 30px auto 0;
|
||||
background-color: #fff;
|
||||
|
||||
background-color: #ffffff;
|
||||
&-title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
27
src/views/test/index.vue
Normal file
27
src/views/test/index.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<section class="test_container">
|
||||
<customScrollTitle />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.test_container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
</style>
|
12
yarn.lock
12
yarn.lock
@ -6611,6 +6611,18 @@ vue-demi@*, vue-demi@^0.14.10:
|
||||
resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
|
||||
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
|
||||
|
||||
vue-demi@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
|
||||
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
|
||||
|
||||
vue-echarts@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.npmmirror.com/vue-echarts/-/vue-echarts-7.0.3.tgz#bf79f7ee0144bbdc6aee5610e8443fed91f6abbe"
|
||||
integrity sha512-/jSxNwOsw5+dYAUcwSfkLwKPuzTQ0Cepz1LxCOpj2QcHrrmUa/Ql0eQqMmc1rTPQVrh2JQ29n2dhq75ZcHvRDw==
|
||||
dependencies:
|
||||
vue-demi "^0.13.11"
|
||||
|
||||
vue-eslint-parser@^9.4.3:
|
||||
version "9.4.3"
|
||||
resolved "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8"
|
||||
|
Loading…
x
Reference in New Issue
Block a user