个人于开发中收集整合的常用组件及样式,主要为element ui
border-radius 属性可以设置元素的圆角大小。它接受一个或多个值来指定每个角的圆角半径,值可以是像素、百分比或 em 单位。
.img {
//盒子圆角
border-radius: 5PX;
}
配合使用 object-fit: cover,对这些img、video进行保留原始比例的剪切、缩放或者直接进行拉伸等
.video {
border-radius: 10px;
object-fit: cover;
}
使用box-show实现阴影效果,常用于图片、盒子阴影效果
,img{
/* 方向x 方向y 偏移量 模糊半径 阴影颜色 */
box-shadow: -5px 8px 1px 1px rgb(209, 209, 209);
}
box-shadow 属性还支持以下参数:
使用 display:flex 实现子div相对父div水平分布
//父div使用flex弹性盒模型
.planb {
display: flex;
text-align: center;
}
//子div
.planb .imag {
width: 600px;
margin: 15px auto;
}
flex-wrap: wrap;为自动换行,nowrap则为不自动换行
.hzhbdiv {
flex-wrap: wrap;
display: flex;
text-align: center;
margin: 0 5%;
padding-left: 2%;
}
通过 left: 50%; transform: translateX(-50%); 实现水平居中
.div{
position: relative;
}
.sonDiv{
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
z-index: 1;
}
通过赋予父元素text-align: center;及子元素display: inline-block;实现多个子元素居中排布
<div style="text-align: center;">
<div style="display: inline-block;">div>
<div style="display: inline-block;">div>
div>
通过赋予父元素display:flex;及align-items: center;以实现多个子元素垂直居中排布
<div class="container">
<div class="box">Div 1div>
<div class="box">Div 2div>
<div class="box">Div 3div>
div>
<style>
.container {
display: flex;
align-items: center;
}
style>
使用overflow-x: scroll;控制div水平溢出
<template>
<div>
<div class="container">
<div class="card">1div>
<div class="card">2div>
<div class="card">3div>
<div class="card">4div>
<div class="card">5div>
<div class="card">6div>
div>
div>
template>
<style scoped>
.container {
display: flex;
flex-wrap: nowrap;
/* 控制水平溢出显示 */
overflow-x: scroll;
/* 控制滚动的平滑效果 */
-webkit-overflow-scrolling: touch;
}
.card {
width: 400px;
min-width: 400px;
height: 200px;
background-color: bisque;
margin: 10px;
white-space: nowrap;
display: inline-block;
}
style>
overflow 是 CSS 的简写属性,其设置了元素溢出时所需的行为——即当元素的内容太大而无法适应它的块级格式化上下文时。
包含的值:
visible
内容不能被裁减并且可能渲染到边距盒(padding)的外部。
hidden
如果需要,内容将被裁减以适应边距(padding)盒。不提供滚动条,也不支持允许用户滚动(例如通过拖拽或者使用滚轮)。内容可以以编程的方式滚动(例如,通过设置 scrollLeft 等属性的值或 scrollTo() 方法), 因此该元素仍然是一个滚动的容器。
clip
类似于 hidden,内容将以元素的边距(padding)盒进行裁剪。clip 和 hidden 之间的区别是 clip 关键字禁止所有滚动,包括以编程方式的滚动。该盒子不是一个滚动的容器,并且不会启动新的格式化上下文。如果你希望开启一个新的格式化上下文,你可以使用 display: flow-root 来这样做。
scroll
如果需要,内容将被裁减以适应边距(padding)盒。无论是否实际裁剪了任何内容,浏览器总是显示滚动条,以防止滚动条在内容改变时出现或者消失。打印机可能会打印溢出的内容。
auto
取决于用户代理。如果内容适应边距(padding)盒,它看起来与 visible 相同,但是仍然建立了一个新的块级格式化上下文。如果内容溢出,则浏览器提供滚动条。
overlay 已弃用
行为与 auto 相同,但是滚动条绘制在内容之上,而不是占据空间。
常用的内容溢出自动添加滚动条:overflow:auto
.div:hover{
cursor:pointer
}
Transform 是 CSS3 中的一个属性,可以用来对元素进行 2D 或 3D 转换。Transform 可以通过设置一系列函数来实现不同的变换效果,Transform 属性不会改变元素的文档流位置,仅仅是在视觉上对元素进行了变换,常用的函数有:
移动+阴影
.article:hover {
box-shadow: -2px 2px 2px rgba(0, 0, 0, 0.2);
transform: translate(2px, -2px);
}
rotate():旋转,可用来实现元素的旋转效果。使用 rotate() 函数可以将元素旋转指定的角度,角度可以用 deg、grad 或 rad 来表示。例如,可以使用 rotate(45deg) 来将元素顺时针旋转 45 度。
scale():缩放,可用来调整元素的大小。使用 scale() 函数可以将元素的大小按指定的比例进行缩放。例如,可以使用 scale(2, 2) 来将元素在水平和垂直方向上都放大为原来的两倍。
变大+阴影
.img3:hover {
transform: scale(1.1);
box-shadow: -5px 5px 5px rgba(0, 0, 0, 0.3);
}
skew():倾斜,可用来实现元素的倾斜效果。使用 skew() 函数可以将元素沿着水平或垂直方向进行倾斜。例如,可以使用 skew(30deg, 0) 来将元素在水平方向上倾斜 30 度。
matrix():矩阵变换,可用来实现复杂的变换效果。使用 matrix() 函数可以通过一个 6x1 的矩阵来对元素进行变换。matrix() 函数可以实现 translate()、rotate()、scale() 和 skew() 函数的所有功能,也可以实现更加复杂的变换效果。
实现文本两端对齐(text justify)可以使用 text-align 属性,它有一个属性值为 justify,表示文本两端对齐。
<style>
.text-justify {
text-align: justify;
text-justify: inter-ideograph; /* 中文文本两端对齐 */
word-spacing: 2px; /* 单词间距 */
letter-spacing: 1px; /* 字母间距 */
}
style>
<div class="text-justify">
<p>这是一段文本,可以通过 text-align: justify 实现两端对齐的效果。同时,结合使用 word-spacing 和 letter-spacing 属性可以调整单词和字母之间的间距,以达到更好的排版效果。p>
div>
上述代码中,text-justify 属性设置为 inter-ideograph 表示中文文本两端对齐。通过调整 word-spacing 和 letter-spacing 属性的值,可以进一步调整单词和字母之间的间距,以达到更好的排版效果。
text-underline-offset 属性设置文本装饰下划线(使用 text-decoration 应用)与其原始位置的偏移距离。
/* 单个关键字 */
text-underline-offset: auto;
/* length */
text-underline-offset: 0.1em;
text-underline-offset: 3px;
/* percentage */
text-underline-offset: 20%;
媒体查询(Media Queries)是 CSS3 中的一个特性,用于根据不同的媒体类型、设备特性等条件来应用不同的 CSS 样式。通过媒体查询,可以使得网页在不同的设备上以不同的方式展现,从而实现响应式设计。
媒体查询通过在 CSS 中使用 @media 关键字来定义一个查询,其基本语法如下:
@media mediatype and (条件) {
/* CSS 样式 */
}
其中,mediatype 可以是 all(所有设备)、print(打印设备)、screen(屏幕设备)、speech(语音阅读器等)等。而条件则是指一些媒体特性,如屏幕宽度、高度、方向、分辨率等。
下面是一个示例,它会在屏幕宽度小于等于 600 像素时,应用特定的样式:
@media screen and (max-width: 600px) {
body {
background-color: yellow;
}
}
上述代码中,@media screen and 表示只应用于屏幕设备,(max-width: 600px) 表示屏幕宽度小于等于 600 像素时,应用样式。这样,当浏览器窗口的宽度小于等于 600 像素时,背景颜色会变成黄色。
流体布局(Fluid Layout)是响应式 Web 设计中常用的一种布局方式,它的特点是页面布局随着浏览器窗口大小的改变而自动调整,以适应不同屏幕和设备的显示。
下面是一个示例,它的宽度和高度将会随父div的大小二变化
.ullist img {
width: 80%;
height: 100%;
}
在流体布局中,页面元素的宽度不是固定的,而是使用百分比、em、rem 等相对单位来设置,使得页面元素可以根据浏览器窗口大小进行自适应。具体来说,流体布局常用的技术包括以下几种:
使用百分比:将页面元素的宽度设置为百分比,以相对于其父元素的宽度计算。例如,将一个容器的宽度设置为 80%,则该容器的宽度将会随着其父元素的宽度改变而自适应。
使用 em 和 rem:将页面元素的宽度设置为 em 或 rem,以相对于其父元素或根元素的字体大小计算。例如,将一个容器的宽度设置为 20em,则该容器的宽度将会随着其父元素的字体大小改变而自适应。
使用 max-width 和 min-width:使用 max-width 和 min-width 属性来限制页面元素的最大和最小宽度,以避免在屏幕过大或过小时出现不必要的空白或重叠现象。
通过使用流体布局,可以使得页面在不同设备和屏幕大小下都能呈现出最佳的布局效果,提升用户的浏览体验。不过,流体布局也有其局限性,例如在设计某些特定功能或交互时可能需要使用绝对布局或固定宽度的元素,这时需要在设计时进行权衡和取舍。
window.innerWidth 是一个 JavaScript 属性,返回当前窗口(浏览器)的宽度,即可视区域宽度,以像素为单位。它不包括滚动条的宽度,如果需要包含滚动条的宽度,可以使用 document.documentElement.clientWidth 属性。
以函数通过window.innerWidth当前窗口(浏览器)的宽度并作出相应的措施
该函数须在created等钩子函数调用才能生效
get() {
this.$nextTick(() => {
const screenWidth = window.innerWidth
if (screenWidth < 768) {
this.abImg = 'https://i.tosoiot.com/20230509/t/8f00a73bf95a98df.jpg'
}
})
}
/* 隐藏滚动条 */
/*
::-webkit-scrollbar {
display: none;
}
*/
/* 滚动条样式 */
::-webkit-scrollbar {
width: 10px; /* 滚动条宽度 */
height: 10px; /* 滚动条高度 */
}
/* 滚动条轨道 */
::-webkit-scrollbar-track {
background: #f1f1f1; /* 滚动条轨道背景色 */
}
/* 滚动条thumb */
::-webkit-scrollbar-thumb {
background: #888; /* 滚动条thumb背景色 */
}
/* 滚动条hover状态的thumb */
::-webkit-scrollbar-thumb:hover {
background: #555; /* 滚动条hover状态的thumb背景色 */
}
.div{
position: relative;
}
.sondiv{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100px;
z-index: 1;
}
text-decoration 属性是用来设置 a 标签的划线属性的。
其属性值有:
a{
text-decoration: none;
}
我们在一些情况下可能会需要在onUpdated中调用事件,但该事件会触发onUpdated从而导致递归问题
解决办法:
找到一个该事件在不同的调用中不同的参数,以此作为判断来调用事件
//不同的调用中不同的参数
const isUpdateId = ref(0)
function getFolders() {
Axios.post(
'/getFolder/Img',
{
collection_folder_id: localStorage.folderId
}
)
.then(response => {
console.log(response.data)
foldersImg.value = response.data.data.images
isUpdateId.value = localStorage.folderId
})
.catch(error => {
console.error(error);
});
}
onUpdated(() => {
//以此作为判断来调用事件
if(isUpdateId.value != localStorage.folderId){
getFolders()
}
})
通过在vue.config.js中的module.exports = defineConfig({})中添加以下代码进行修改
chainWebpack: config =>{
config.plugin('html').tap(args => {
args[0].title = 'you title';
return args;
})
},
依赖如下
"dependencies": {
"axios": "^1.3.4",
"core-js": "^3.8.3",
"element-ui": "^2.4.5",
"vue": "^2.6.14",
"vue-axios": "^2.1.5",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
}
使用 @keyup.enter.native=“调用的函数” 回车调用函数
<el-input v-model="prompt" placeholder="您有什么想问的吗?"
@keyup.enter.native="gpt()">
通过设置 autosize 属性可以使得文本域的高度能够根据文本内容自动进行调整,并且 autosize 还可以设定为一个对象,指定最小行数和最大行数。
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="textarea2">
el-input>
通过 el-input 的 show-password 属性实现密码的显示
<el-input style="height: 40px;margin-bottom: 4%;" v-model="password"
type="password" placeholder="请输入密码" show-password />
.el-menu {
border-right:0!important;
}
通过prop获取返回数据,通过slot-scope传递给img标签
<el-table :data="tableData" :header-cell-style="{ 'text-align': 'center' }">
<el-table-column label="文章">
<el-table-column prop="articleId" label="ID" width="100px" />
<el-table-column label="图片" width="150px">
<template slot-scope="scope">
<img :src="scope.row.articleImg" style="width: 100%;" />
template>
el-table-column>
<el-table-column prop="articleTitle" label="标题" />
<el-table-column prop="articleIntroduction" label="简介" />
<el-table-column prop="articleContent" label="描述" />
el-table-column>
el-table>
1.header-cell-style:表头单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有表头单元格设置一样的 Style。
2.cell-style:单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。
3.row-style:行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。
<el-table class="cs1" :data="profitData"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column label="利润计算结果">
<el-table-column prop="commission" label="佣金" />
<el-table-column prop="advertisement" label="广告费" />
<el-table-column prop="total" label="产品总成本" />
<el-table-column prop="profit" label="利润" />
<el-table-column prop="profitRatio" label="利润率" />
el-table-column>
el-table>
::v-deep .el-table tbody tr:hover>td {
background-color: transparent!important;
}
arrow=“never” indicator-position=“none” interval=“0” type=“card”
代码如下
<template>
<el-carousel id="terrace" arrow="never" indicator-position="none" interval="0" type="card" height="600px">
<el-carousel-item v-for="item in imgList" :key="item.id">
<el-image :src="item.idView" class="image" style="width: 100%; height: 600px;" />
el-carousel-item>
el-carousel>
template>
<script>
export default {
data() {
return {
imgList: [
// 后端图片地址
{ id: 0, idView: './img/1.jpg' },
{ id: 1, idView: './img/2.jpg' },
{ id: 2, idView: './img/3.jpg' },
{ id: 3, idView: './img/4.jpg' },
{ id: 4, idView: './img/5.jpg' },
{ id: 5, idView: './img/6.jpg' }
]
};
}
}
script>
<style>
#terrace {
margin: 20px 10px;
margin-bottom: 50px;
}
style>
card模式的动画不是将当前轮播项放大而是将其它的缩小到0.83,所以如果想修改轮播动画需要将当前轮播想也进行缩小并添加想要的动画
<el-carousel @change="handleCarouselChange" :autoplay=false indicator-position="none" type="card" arrow="never"
height="600px">
<el-carousel-item v-for="(item, index) in carouselItems" :key="index">
<h1>{{ item }}h1>
el-carousel-item>
el-carousel>
handleCarouselChange(index) {
const items = document.querySelectorAll('.el-carousel__item');
items.forEach(item => {
item.style.boxShadow = 'none';
});
setTimeout(() => {
const currentItem = this.$el.querySelector(".el-carousel__item:nth-child(" + (index + 1) + ")");
if (currentItem) {
currentItem.style.boxShadow = "12px 8px 10px #a4b3c086"
currentItem.style.transform = "scale(0.88) translate(79%, -40px)";
currentItem.style.transition = "transform 0.3s";
}
}, 10);
},
mounted() {
this.handleCarouselChange(0);
}
indicator-position属性定义了指示器的位置。默认情况下,它会显示在走马灯内部,设置为outside则会显示在外部;设置为none则不会显示指示器。
当el-carousel的高度固定的时候,indicator-position设置为outside可能会出现内容高度大于走马灯的高度以至于出现下拉框的情况,解决方法是设置indicator-position属性为默认即可
默认
代码如下
<el-backtop>el-backtop>
el-menu 是 Element UI 框架中的一个组件,用于创建菜单导航。它提供了多种功能和样式选项,可以轻松创建水平或垂直的菜单,并支持嵌套子菜单。el-menu 组件通常与 el-menu-item 和 el-submenu 组件一起使用。
mode 是 el-menu 组件的一个属性,用于设置菜单的显示模式。它决定了菜单是以水平布局还是垂直布局显示。
mode 属性有两个可选值:
“horizontal”:水平布局模式。菜单项水平排列,通常用于顶部导航栏或水平工具栏的菜单。在水平模式下,菜单项从左到右水平排列,适合于较宽的容器。
“vertical”:垂直布局模式。菜单项垂直排列,通常用于侧边栏或垂直导航栏的菜单。在垂直模式下,菜单项从上到下垂直排列,适合于较窄的容器。
collapse 是 el-menu 组件的一个属性,用于设置菜单是否可折叠(展开和收起)。
当 collapse 属性设置为 true 时,菜单将具有折叠功能,用户可以通过点击折叠按钮或菜单项来展开和收起菜单的子菜单。当菜单处于折叠状态时,子菜单将被隐藏,只显示菜单的图标和文本。
使用折叠菜单可以节省页面空间,在有限的空间内展示较多的菜单选项。折叠菜单通常用于侧边栏布局或移动设备上的导航栏。
menu-trigger 是 el-menu 组件的一个属性,用于设置触发菜单展开和收起的方式。
默认情况下,菜单的展开和收起是通过鼠标悬停的方式触发的,即当鼠标悬停在菜单上时,菜单将展开,鼠标离开时菜单将收起。
通过设置 menu-trigger 属性,可以改变菜单的触发方式。menu-trigger 属性支持以下取值:
“hover”: 默认值,表示通过鼠标悬停触发菜单的展开和收起。
“click”: 表示通过鼠标点击触发菜单的展开和收起。当用户点击菜单时,菜单将展开,再次点击菜单时,菜单将收起。
Apache ECharts 是基于 JavaScript 的开源可视化图表库,它可以将数据渲染成图表
npm install echarts --save
main.js中引入(此处展示的为5.X的引入,4.X的引入应改为import echarts from ‘echarts’)
import * as echarts from 'echarts'
div /
<div style="display: flex;flex-wrap: wrap;">
<div id="eChartsId1" style="width: 900px; height: 600px;">div>
<div id="eChartsId2" style="width: 900px; height: 600px;">div>
div>
JavaScript / methods
import * as echarts from 'echarts';
//省略其它代码......
tb() {
//指定图表渲染位置
let myChart = echarts.init(document.getElementById("eChartsId1"));
myChart.setOption({
title: {
text: "ysd",
fontSize: 24,
left: '10%'
},
//x轴
xAxis: {
name: 'a',
data: ['A', 'B', 'C', 'D', 'E', 'F']
},
//y轴
yAxis: {
name: 'b',
},
series: [
{
name: 'yyy',
data: [16, 22, 28, 23, 32, 28],
type: 'line',
stack: 'line1',
smooth: true
},
{
name: 'sss',
data: [15, 15, 23, 25, 18, 28],
type: 'line',
stack: 'line2',
}
],
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(32, 33, 36,.7)',
borderColor: 'rgba(32, 33, 36,0.20)',
borderWidth: 1,
textStyle: {
color: '#fff',
fontSize: '12'
}
}
});
let myChart1 = echarts.init(document.getElementById("eChartsId2"));
myChart1.setOption({
xAxis: {
data: ['A', 'B', 'C', 'D', 'E']
},
yAxis: {},
series: [
{
name: 'ddd',
data: [10, 22, 28, 23, 19],
type: 'line',
smooth: true,
areaStyle: {
color: 'lightblue',
opacity: 0.5
}
}
],
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(32, 33, 36,.7)',
borderColor: 'rgba(32, 33, 36,0.20)',
borderWidth: 1,
textStyle: {
color: '#fff',
fontSize: '12'
}
}
});
}
展示图
该组件为简单基础的一个登录模块,使用v-if实现登录和注册之间的切换,并使用transition以实现切换动画
代码如下
<template>
<div>
<div style="width: 100%; height: 100%; background-size: 100%; position: fixed;">
<div id="loginFrom">
<transition name="fade" mode="out-in">
<div :key="isShow">
<div v-if="isShow">
<el-form id="loginForm">
<h1 style="font-size: 42px;margin: 4% auto;">登录h1>
<el-form-item>
<p class="text">账号p>
<el-input style="height: 42px;" v-model.number="userId" placeholder="请输入账号" type="text" />
el-form-item>
<el-form-item>
<p class="text">密码p>
<el-input style="height: 40px;margin-bottom: 4%;" v-model="password" type="password" placeholder="请输入密码" show-password />
el-form-item>
<el-button @click="Login()">登录el-button>
<el-button @click="toChange()">注册el-button>
el-form>
div>
<div v-else>
<el-form id="registerForm">
<h1 style="font-size: 42px;margin: 4% auto;">注册h1>
<el-form-item>
<p class="text">用户名p>
<el-input style="height: 42px;" v-model="userName" placeholder="请输入用户名" type="text" />
el-form-item>
<el-form-item>
<p class="text">密码p>
<el-input style="height: 40px;margin-bottom: 4%;" v-model="password" type="password" placeholder="请输入密码"
show-password />
el-form-item>
<el-form-item>
<p class="text">确认密码p>
<el-input style="height: 40px;margin-bottom: 4%;" v-model="password2" type="password"
placeholder="请再次输入密码" show-password />
el-form-item>
<el-button @click="toChange()">登录el-button>
<el-button @click="Register()">注册el-button>
el-form>
div>
div>
transition>
div>
div>
div>
template>
<script>
export default {
data() {
return {
userId: '',
userName: '',
password: '',
password2: '',
isShow: true,
}
},
methods: {
toChange() {
this.isShow = !this.isShow;
},
Login() {
if (this.userId === "") {
this.$alert("账号不能为空", {
confirmButtonText: '确定',
});
} else if (this.password === "") {
this.$alert("密码不能为空", {
confirmButtonText: '确定',
});
} else {
this.$axios.post(
"/user/login",
this.$qs.stringify({
userId: this.userId,
userPassword: this.password
})
)
.then((res) => {
//登录成功
} else {
//登录失败
}
});
}
},
Register() {
if (this.userName === "") {
this.$alert("用户名不能为空", {
confirmButtonText: '确定',
});
} else if (this.password.length < 6) {
this.$alert("密码不能小于6位", {
confirmButtonText: '确定',
});
} else if (this.password === this.password2) {
this.$axios.post(
"/user/register",
this.$qs.stringify({
userName: this.userName,
userPassword: this.password
})
)
.then((res) => {
this.$alert(res.data, {
confirmButtonText: '确定',
});
});
} else {
this.$alert("两次密码不同", {
confirmButtonText: '确定',
});
}
}
},
components: {
}
}
script>
<style>
#loginFrom {
margin: 3% auto;
padding: 3%;
min-width: 300px;
max-width: 25%;
text-align: center;
background-color: rgba(255, 255, 255, 0.856);
border-radius: 5%;
color: rgb(0, 0, 0);
font-weight: 800;
}
.text {
font-size: 20px;
margin: 0;
text-align: left;
}
/* 进出动画时间 */
.fade-enter-active,
.fade-leave-active {
transition: all .8s;
}
/* 进出动画效果 */
.fade-enter,
.fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
style>
此轮播图模块较为复杂,它实现了电脑屏幕和手机屏幕两套不同的图片轮播,且手机屏幕下可以通过滑动切换图片
<template>
<div class="carousel-wrapper" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
<el-carousel ref="carousel" :interval="3000" :style="{ height: screenheight + 'px' }" :arrow="isMobile"
:indicator-position="isMobile ? 'none' : 'outside'">
<el-carousel-item v-for="item in imgs" :key="item.id" style="height: 100%;">
<el-image :src="item.src" class="carousel-img" />
el-carousel-item>
el-carousel>
div>
template>
<script>
export default {
data() {
return {
imgs: [
{
id: 1,
src: '1.jpg',
},
{
id: 2,
src: '2.jpg',
},
{
id: 3,
src: '3.jpg',
},
],
screenheight: 600,
isMobile: false,
startX: 0,
startY: 0,
endX: 0,
endY: 0,
};
},
created() {
this.calculateHeight();
window.addEventListener('resize', this.calculateHeight);
},
beforeDestroy() {
window.removeEventListener('resize', this.calculateHeight);
},
methods: {
handleTouchStart(e) {
this.startX = e.touches[0].clientX;
this.startY = e.touches[0].clientY;
},
handleTouchMove(e) {
this.endX = e.touches[0].clientX;
this.endY = e.touches[0].clientY;
},
handleTouchEnd() {
const distanceX = this.endX - this.startX;
const distanceY = this.endY - this.startY;
if (Math.abs(distanceX) > Math.abs(distanceY)) {
if (distanceX > 0) {
this.$refs.carousel.prev();
} else {
this.$refs.carousel.next();
}
}
},
calculateHeight() {
const windowWidth = window.innerWidth;
this.isMobile = windowWidth < 768;
if (this.isMobile) {
this.imgs = [
{
id: 1,
src: '1.jpg',
},
{
id: 2,
src: '2.jpg',
},
{
id: 3,
src: '3.jpg',
},
{
id: 4,
src: '4.jpg',
},
];
} else {
this.imgs = [
{
id: 1,
src: '1.jpg',
},
{
id: 2,
src: '2.jpg',
},
{
id: 3,
src: '3.jpg',
},
];
}
},
},
};
script>
<style>
.el-carousel__container {
height: 100% !important;
margin-bottom: 0;
overflow: hidden;
}
style>
<style scoped>
.carousel-wrapper {
width: 100%;
}
.carousel-img {
width: 100%;
height: 100%;
object-fit: contain;
}
style>
检测div的位置以实现当其进入或离开视窗的时候触发动画
<template>
<div class="scroll-container" @scroll="handleScroll">
<div class="content">Content 0div>
<div class="content">Content 1div>
<div class="content animated-content" ref="animatedContent">
Content 2 - with enter and exit animation
div>
<div class="content">Content 3div>
<div class="content">Content 4div>
div>
template>
<script>
export default {
methods: {
// 进场动画
animateEnter(el) {
el.style.transition = 'opacity 0.5s, transform 0.5s';
el.style.opacity = 1;
el.style.transform = 'translateY(0)';
},
// 退场动画
animateLeave(el) {
el.style.transition = 'opacity 0.5s, transform 0.5s';
el.style.opacity = 0;
el.style.transform = 'translateY(-30px)';
},
// 处理滚动事件
handleScroll() {
const animatedContent = this.$refs.animatedContent;
const rect = animatedContent.getBoundingClientRect();
const windowHeight = window.innerHeight;
// 判断元素是否在视窗内部
if (
rect.top < windowHeight && // 元素顶部在视窗内
rect.bottom > 0 // 元素底部在视窗外
// && rect.bottom - windowHeight < 0 // 元素底部在视窗内
) {
this.animateEnter(animatedContent);
} else {
this.animateLeave(animatedContent);
}
},
},
};
script>
<style scoped>
.scroll-container {
height: 100vh;
overflow-y: scroll;
}
.content {
height: 500px;
padding: 20px;
border: 1px solid #ccc;
margin-bottom: 20px;
}
.animated-content {
opacity: 0;
transform: translateY(30px);
}
style>
<template>
<div>
<div id="PartnersFont">
div>
<div class="carousel" ref="all">
<div v-for="(item, index) in tableData" :key="index" class="carousel-item"
:style="'transform: translateX(' + item.translateNum + 'px)'" ref="demoItem" @mouseover="mouseOver"
@mouseleave="mouseLeave">
<div>{{ item.name }}div>
div>
div>
div>
template>
<script>
export default {
data() {
return {
tableData: [
{
name: '1'
}, {
name: '2'
}, {
name: '3'
}, {
name: '4'
}, {
name: '5'
}
],
translateNum: 0,
timer: null
}
},
mounted() {
this.search()
},
beforeDestroy() {
window.clearTimeout(this.timer)
},
methods: {
search() {
for (var i = 0; i < this.tableData.length; i++) {
this.$set(this.tableData[i], 'translateNum', 0)
}
this.$nextTick(() => {
for (var j = 0; j < this.tableData.length; j++) {
this.$set(this.tableData[j], 'indexLeft', this.$refs.demoItem[j].offsetLeft)
}
this.roll()
})
},
roll() {
this.timer = setInterval(() => {
for (var i = 0; i < this.tableData.length; i++) {
if (document.body.clientWidth - this.tableData[i].translateNum - this.tableData[i].indexLeft < 0) {
this.$set(this.tableData[i], 'translateNum', this.$refs.all.offsetLeft - this.tableData[i].indexLeft - 220)
}
this.$set(this.tableData[i], 'translateNum', this.tableData[i].translateNum + 2)
}
}, 20)
},
mouseOver() {
window.clearTimeout(this.timer)
},
mouseLeave() {
this.roll()
}
}
}
script>
<style scoped>
.carousel {
width: 100%;
height: 300px;
margin: 20px auto;
overflow: hidden;
display: flex;
justify-content: left;
}
.carousel-item {
border-radius: 10px;
padding: 10px;
width: 200px;
min-width: 200px;
height: 100px;
text-align: center;
margin: 10px 20px;
background-color: rgba(156, 200, 238, 0.815);
}
#PartnersFont {
text-align: center;
}
style>