1. 前端实现图片预览
一、图片在后端中存储 一般来说,图片在后端的存储方式分为两种:
其一:可以将图片以独立文件的形式存储在服务器的指定文件夹中,再将路径存入数据库字段中;
其二:将图片转换成二进制流,直接存储到数据库的 Image 类型字段中.
- 对于第一种存储方式,我们前端直接将存储路径赋值给 src 属性即可轻松显示。
- 对于第二种存储方式,我们前端需要将其二进制流交由 blob 对象处理,然后通过 blob 的 API 生成临时 URL 赋值给 src 属性来显示。
遇到的问题数据乱码
出现问题的原因的axios 默认返回的是 json 文本形式,二进制图片数据被强制转换成了 json 文本形式。
找到了原因,解决方案就好办了。我们在 axios 里面,responseType 默认返回数据类型是 json,将其改为返回数据类型 blob。
1.1 网上参考代码:
- 请求数据
export function miniprogramQrcode (params) {
return axios.post(
env.MI_URL + '/XXXX/XXX/XXXX',
params,
// 将responseType的默认json改为blob
{
responseType: 'blob',
emulateJSON: true
}).then(res => {
if (res.data) {
return Promise.resolve(res.data)
} else {
throw res
}
}).catch(err => {
return Promise.reject(err)
})
}
- 处理blob对象
- 在特定元素中显示图片
//这是在页面中显示图片
createMiniQrcode (blob) {
let img = document.createElement('img')
img.onload = function (e) {
// 元素的onload 事件触发后将销毁URL对象, 释放内存。
window.URL.revokeObjectURL(img.src)
}
// 浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL。
// 这个 URL 以blob://开头,表明对应一个 Blob 对象。
img.src = window.URL.createObjectURL(blob)
document.querySelector('.imgQrCode').appendChild(img)
}
1.2 我项目中用的代码如下,在浏览器新窗口打开图片:
function createMiniQrcode(blob) {
// // 浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL。
// // 这个 URL 以blob://开头,表明对应一个 Blob 对象。
let imgssrc = window.URL.createObjectURL(blob)
// window.open(item, `img${index}`) // 尝试失败
window.open('').document.write(`<!DOCTYPE html><html><body ><img src='${imgssrc}' /></body></html>`)
}
// 请求图片数据
const getBolob = async () => {
return await axios
.get(
`api/FileMessage/Download?fid=${row.FileMessageId}&dirUrl=${this.catalogList[0].DirectoryUrl}&dlTag=${false}`,
// 将responseType的默认json改为blob
{
responseType: 'blob',
emulateJSON: true,
}
)
.then((res) => {
if (res.data) {
return Promise.resolve(res.data)
} else {
throw res
}
})
.catch((err) => {
return Promise.reject(err)
})
}
getBolob().then((res) => {
console.log('res', res)
// 新窗口打开图片
createMiniQrcode(res)
})
2. vue-office 预览docx、.xlsx、pdf
vue-office是一个支持多种文件(docx、.xlsx、pdf)预览的vue组件库,支持vue2和vue3。 链接地址
直接安装这三个库
#docx文档预览组件
npm install @vue-office/docx vue-demi
#excel文档预览组件
npm install @vue-office/excel vue-demi
#pdf文档预览组件
npm install @vue-office/pdf vue-demi
如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
npm install @vue/composition-api
完整可实现代码如下:把接口换成自己的接口就可以
<template>
<div class="file">
<div v-if="src" class="docx">
<vue-office-docx :src="src" v-if="src" />
</div>
<div v-if="pdf" class="pdf">
<vue-office-pdf :src="pdf" v-if="pdf" @rendered="renderedHandler" @error="errorHandler" />
<div class="pagination">
</div>
</div>
<div v-if="excel" class="excel">
<vue-office-excel :src="excel" :options="options" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" />
</div>
</div>
</template>
<script>
import axios from 'axios'
import mammoth from 'mammoth'
import VueOfficeDocx from '@vue-office/docx'
import VueOfficePdf from '@vue-office/pdf'
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
import '@vue-office/docx/lib/index.css'
export default {
name: 'file',
props: {},
data() {
return {
src: '',
pdf: '',
excel: '',
options: {
xls: false, //预览xlsx文件设为false;预览xls文件设为true
minColLength: 0, // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
minRowLength: 0, // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
widthOffset: 10, //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
beforeTransformData: (workbookData) => {
return workbookData
}, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
transformData: (workbookData) => {
return workbookData
}, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
},
htmlContent: '',
currentPage: 1,
totalPages: 0,
pages: [],
}
},
components: { VueOfficeDocx, VueOfficePdf, VueOfficeExcel },
computed: {},
methods: {
renderedHandler() {
console.log('渲染完成')
},
errorHandler() {
console.log('渲染失败')
},
getFileData() {
let query = this.$route.query
const getBolob = async () => {
//这里是你请求的地址
return await axios
.get(
`api/FileMessage/Download?fid=${query.fid}&dirUrl=${query.dirUrl}&dlTag=${query.dlTag}`,
// 将responseType的默认json改为blob
{
responseType: 'blob',
emulateJSON: true,
}
)
.then((res) => {
if (res) {
return Promise.resolve(res)
} else {
throw res
}
})
.catch((err) => {
return Promise.reject(err)
})
}
getBolob().then((res) => {
let fileType = res.headers['content-disposition'].split('.')[1]
console.log('fileType', fileType)
console.log('res', res)
let path = window.URL.createObjectURL(res.data)
console.log('path', path)
if (fileType === 'doc' || fileType === 'docx') {
console.log('world文档')
this.src = path
} else if (fileType === 'pdf') {
console.log('pdf文档')
this.pdf = path
} else if (fileType === 'xls' || fileType === 'xlsx') {
this.excel = path
}
})
},
},
watch: {},
mounted() {
console.log('ruote', this.$route)
this.getFileData()
},
}
</script>
<style lang="scss" scoped>
.file {
height: 100vh;
.docx {
height: 800px;
overflow: auto;
width: 100%;
}
.pdf {
height: 800px;
width: 100%;
overflow: auto;
}
.excel {
height: 800px;
width: 100%;
overflow: auto;
}
}
</style>
3. 文件下载
关键代码如下:
methods:{
// 请求数据
async getBolob(row, query) {
return await axios
.get(
`api/FileMessage/Download?fid=${row.FileMessageId}&dirUrl=${this.catalogList[0].DirectoryUrl}&dlTag=${query.dlTag}`,
// 将responseType的默认json改为blob
{
responseType: 'blob',
emulateJSON: true,
}
)
.then((res) => {
if (res) {
return Promise.resolve(res)
} else {
throw res
}
})
.catch((err) => {
return Promise.reject(err)
})
},
// 下载的点击事件
download(row) {
console.log('row', row)
let query = {
fid: row.FileMessageId, //文件ID
dirUrl: this.catalogList[0].DirectoryUrl, //资料库路径
dlTag: true, //下载标记
}
//这里是请求数据
this.getBolob(row, query).then((res) => {
console.log('res', res)
//获取文件的后缀
let fileType = res.headers['content-disposition'].split('.')[1]
console.log('fileType', fileType)
const blob = res.data
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
//文件的名字
link.download = row.FileMessageName + '.' + fileType
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(link.href)
})
},
}
4. 文件上传
使用element-ui
的组件el-upload
实现文件上传
介绍如下: 具体参数说明,如何实现上传、下载、删除等功能
-
action:文件上传地址,我的项目里已经封装好了请求。使用的时候需要依据项目填写。
-
show-file-list: 是否显示已上传文件列表。
-
headers:设置上传的请求头部。我的项目需要传token。
-
on-preview:点击文件列表中已上传的文件时的钩子。 可以在这个这个回调方法里写下载功能部分代码,实现点击文件下载功能。
-
on-remove:文件列表移除文件时的钩子。 在文件列表回显时,使用数组fileData记录id列,执行删除回调时,匹配id,因为删除回调方法返回的file中不记录id,只记录url,可通过url相同返回id,再调用删除接口。
-
on-success: function(response, file, fileList) 文件上传成功时的钩子。 如果不设置auto-upload:false ,则选取文件后立即进行上传,成功回调后使用返回的参数调用接口,完成文件上传。
<el-upload
class="upload-demo"
action //必要属性,上传文件的地址,可以不给,但必须要有,不给就i调接口上传
:http-request="uploadFile"//这个是就上传文件的方法,把上传的接口写在这个方法里
ref="upload"
:limit="fileLimit"//上传文件个数的限制
:on-remove="handleRemove"//上传之后,移除的事件
:file-list="fileList"//上传了那些文件的列表
:on-exceed="handleExceed"//超出上传文件个数的错误回调
:before-upload="beforeUpload"//文件通过接口上传之前,一般用来判断规则,
//比如文件大小,文件类型
:show-file-list="false"//是否用默认文件列表显示
:headers="headers"//上传文件的请求头
>
<!-- action="/api/file/fileUpload" -->
<el-button class="btn"><i class="el-icon-paperclip"></i>上传附件</el-button>
</el-upload>
网上代码参考如下:
<template>
<basic-container>
<el-upload class="upload-demo"
ref="upload"
:headers="headers"
action="/admin/sys-file/upload"
:on-success="handleAvatarSuccess"
:show-file-list="false">
<el-button slot="trigger" size="small" type="primary">上传文件</el-button>
</el-upload>
<el-table class="down" :data="dataList" border stripe style="width: 100%;margin-top: 20px;">
<el-table-column prop="attachName" label="文件名称"></el-table-column>
<el-table-column prop="attachSize" label="文件大小">
<template slot-scope="scope">
<span v-if="scope.row.attachSize / 1024 / 1024 < 1">{{(scope.row.attachSize / 1024).toFixed(2) + 'KB'}}</span>
<span v-else>{{(scope.row.attachSize / 1024 / 1024).toFixed(2) + 'MB'}}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="上传时间"></el-table-column>
<el-table-column width="150px" label="操作">
<template slot-scope="scope">
<el-button size="small" type="text">
<a @click="downloadFile(scope.row.attachName,scope.row.attachUrl)">下载</a>
</el-button>
<el-button size="small" type="text" @click="deleteHandle(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</basic-container>
/template>
<script>
import { getObj, addObj, putObj, fetchList, getnoticeId, delObj } from '@/api/policy/noticeattachment'
import store from '@/store'
import {mapState} from 'vuex'
export default {
data() {
return {
dataForm: {
id: 0,
noticeId: '',
attachName: '',
attachUrl: '',
attachSize: '',
},
dataList: [],
headers: {
'Authorization': 'Bearer ' + store.getters.access_token,
},
}
},
methods: {
init(id) {
this.dataForm.noticeId = id
this.$nextTick(() => {
if (this.dataForm.noticeId) {
this.getDataList()
}
});
},
//获取附件列表
getDataList(){
getnoticeId(this.dataForm.noticeId).then(response => {
this.dataList = response.data.data;
});
},
//下载按钮回调
downloadFile(name,url){
var a = document.createElement('a');
var event = new MouseEvent('click');
a.download = name;
a.href = url;
a.dispatchEvent(event);
},
//成功回调
handleAvatarSuccess(res, file, fileList) {
this.dataForm.attachName = file.name
this.dataForm.attachUrl = res.data.url
this.dataForm.attachSize = file.size
this.dataFormSubmit()
},
// 删除
deleteHandle(id) {
this.$confirm('是否确认删除该附件', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function () {
return delObj(id)
}).then(data => {
this.$message.success('删除成功')
this.getDataList()
})
},
// 表单提交
dataFormSubmit() {
addObj(this.dataForm).then(data => {
this.$message.success('添加成功')
this.getDataList()
})
}
}
}
</script>
<style lang="scss" scoped="scoped">
.down >>> a {
color: #409EFF;
}
</style>
我按需求功能实现的代码如下:
<template>
<div class="home">
<div class="header">
<div>
<el-upload class="upload-demo" ref="upload" :action="actionsPath" :on-preview="handlePreview" :on-remove="handleRemove" :auto-upload="false" :on-change="onChange" :show-file-list="false" :headers="headers" :file-list="fileList" :data="query" :on-success="onSuccess">
<el-button slot="trigger" type="primary" icon="el-icon-plus" @click="handleAddFile" size="small" round>添加文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload" round icon="el-icon-upload2">确认上传</el-button>
</el-upload>
</div>
<div>
<el-radio-group v-model="radio">
<el-radio :label="3">同名时加后缀</el-radio>
<el-radio :label="6">同时时覆盖</el-radio>
</el-radio-group>
</div>
<div class="tips"><span>提示:单个文件大小不超过1G</span></div>
</div>
<div class="main">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="FileMessageName" label="文件名称" width="420" style="font-size: 12px;" />
<el-table-column prop="FileMessageSize" label="文件大小" width="220" />
<el-table-column prop="UploadState" label="上传状态">
<template #default="scope">
<span v-if="scope.row.UploadState == 2" style="color:#ff5722;">
{{ scope.row.Message }}
</span>
<span v-else-if="scope.row.UploadState != 2"> {{ scope.row.Message }} </span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
name: 'home',
props: {
catalogList: {
type: Array,
default: [],
},
},
data() {
return {
headers: {},
radio: '3',
fileList: [],
tableData: [],
actionsPath: '/api/FileMessage/Upload', //上传的接口
query: {
//上传的参数
DirectoryIdTag: '', //目录ID,
SimilarAddSuffix: false, //同名称添加后缀
SimilarCover: false, //同名称覆盖
DirectoryUrl: '', //资料库路径
},
}
},
components: {},
computed: {},
methods: {
onSuccess(res) {
console.log('上传成功!', res)
if (res.IsSuccess) {
this.$layer.msgSuccess('上传成功!')
this.$parent.$parent.openUploadDialog(false)
this.$parent.$parent.queryFiles()
}
},
onChange(file, files) {
console.log(file)
console.log('files', files)
const fileSize = file.size
let fileSizeStr = ''
//确认文件的大小
function formatFileSize(fileSize) {
const units = ['GB', 'MB', 'KB']
const thresholds = [1024 * 1024 * 1024, 1024 * 1024, 1024]
for (let i = 0; i < units.length; i++) {
if (fileSize >= thresholds[i]) {
return (fileSize / thresholds[i]).toFixed(2) + ' ' + units[i]
}
}
return fileSize + ' B' // 如果小于1KB,返回原始大小
}
// 使用示例
fileSizeStr = formatFileSize(fileSize)
console.log('file.response', file.response)
const index = this.tableData.findIndex((q) => q.uid === file.uid)
if (file.response) {
const success = file.response.IsSuccess
this.tableData[index].Message = success ? file.response.Data : file.response.ErrorMessage
this.tableData[index].UploadState = success ? 1 : 2
} else {
this.tableData.push({
uid: file.uid,
LibName: 'hxzkLib',
FileMessageName: file.name,
FileMessageSize: fileSizeStr,
UploadState: 0,
Message: '待上传文件。。。',
})
}
console.log('catalogList', this.catalogList)
},
handleAddFile() {},
handleUpload() {},
submitUpload() {
this.query.DirectoryIdTag = this.catalogList.at(-1).DirectoryId
this.query.DirectoryUrl = this.catalogList[0].DirectoryUrl
console.log(' this.actionsPath', this.actionsPath)
this.$refs.upload.submit()
},
handleRemove(file, fileList) {
console.log(file, fileList)
},
handlePreview(file) {
console.log(file)
},
},
watch: {},
mounted() {
//获取token
let token = this.$cookies.get(this.$member.TOKEN)
this.headers = {
token: token,
}
},
}
</script>
<style lang="scss" scoped>
.home {
height: 500px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
.tips {
font-size: 12px;
color: red;
}
}
.main {
margin-top: 20px;
border-top: 1px solid #ccc;
}
}
</style>
效果如下:
注意:
使用element ui中el-upload组件实现文件上传功能,主要分为两种:
-
- 通过action, url为服务器的地址
-
- 通过http-request(覆盖默认的上传行为,可以自定义上传的实现), 注意此时 on-success 和 on-error事件无法使用
方法1: action (上传xls文件),自己补充上传文件的方法
<el-upload
class="upload-demo"
accept=".xls,.xlsx"
action="/dashboardSystem/manage/uploadFile" // 服务器地址
:data="fileupload" // 上传时附带的额外参数, 通常为{}, 比如 {date: '2023-05-05'}, 则,上传参数为{date: xx, file: Binary}
:style="{ textAlign: 'left' }"
ref="upload"
:show-file-list="true"
:before-upload="beforeUpload" // 判断文件类型和文件大小
:on-exceed="handleExceed" // 上传文件个数限制
:on-success="fileSuccess" // function(res, file, fileList) 上传成功,res为服务器返回的数据,可以判断是否解析成功
:on-error="showError" // function(err, file, fileList) 上传失败
:limit="1"
>
<el-button
slot="trigger"
:style="{ display: 'inlineBlock' }"
size="small"
type="primary"
>选择文件
</el-button>
</el-upload>
方法2: 通过http-request自定义上传文件,没有on-success, on-error
template中:
<div class="flex-div uploaditem">
//这里是上传了那些文件的提示,我没有要默认的文件提示
<el-tooltip class="item" effect="dark" :content="tag.name" placement="top-start" v-for="(tag,index) in fileList" :key="index">
<el-tag style="margin-right:10px;display:flex;" :disable-transitions="false" @close="handleClose(index)" closable @click="downloadFile(tag)"><i class="el-icon-paperclip"></i><span class="tagtext">{{tag.name}}</span></el-tag>
</el-tooltip>
<el-upload
class="upload-demo"
action //必要属性,上传文件的地址,可以不给,但必须要有,不给就i调接口上传
:http-request="uploadFile"//这个是就上传文件的方法,把上传的接口写在这个方法里
ref="upload"
:limit="fileLimit"//上传文件个数的限制
:on-remove="handleRemove"//上传之后,移除的事件
:file-list="fileList"//上传了那些文件的列表
:on-exceed="handleExceed"//超出上传文件个数的错误回调
:before-upload="beforeUpload"//文件通过接口上传之前,一般用来判断规则,
//比如文件大小,文件类型
:show-file-list="false"//是否用默认文件列表显示
:headers="headers"//上传文件的请求头
>
<!-- action="/api/file/fileUpload" -->
<el-button class="btn"><i class="el-icon-paperclip"></i>上传附件</el-button>
</el-upload>
</div>
data中:
//上传后的文件列表
fileList: [],
// 允许的文件类型
fileType: [ "pdf", "doc", "docx", "xls", "xlsx","txt","png","jpg", "bmp", "jpeg"],
// 运行上传文件大小,单位 M
fileSize: 50,
// 附件数量限制
fileLimit: 5,
//请求头
headers: { "Content-Type": "multipart/form-data" },
methods:中
//上传文件之前
beforeUpload(file){
if (file.type != "" || file.type != null || file.type != undefined){
//截取文件的后缀,判断文件类型
const FileExt = file.name.replace(/.+\./, "").toLowerCase();
//计算文件的大小
const isLt5M = file.size / 1024 / 1024 < 50; //这里做文件大小限制
//如果大于50M
if (!isLt5M) {
this.$showMessage('上传文件大小不能超过 50MB!');
return false;
}
//如果文件类型不在允许上传的范围内
if(this.fileType.includes(FileExt)){
return true;
}
else {
this.$message.error("上传文件格式不正确!");
return false;
}
}
},
//上传了的文件给移除的事件,由于我没有用到默认的展示,所以没有用到
handleRemove(){
},
//这是我自定义的移除事件
handleClose(i){
this.fileList.splice(i,1);//删除上传的文件
if(this.fileList.length == 0){//如果删完了
this.fileflag = true;//显示url必填的标识
this.$set(this.rules.url,0,{ required: true, validator: this.validatorUrl, trigger: 'blur' })//然后动态的添加本地方法的校验规则
}
},
//超出文件个数的回调
handleExceed(){
this.$message({
type:'warning',
message:'超出最大上传文件数量的限制!'
});return
},
//上传文件的事件
uploadFile(item){
this.$showMessage('文件上传中........')
//上传文件的需要formdata类型;所以要转
let FormDatas = new FormData()
FormDatas.append('file',item.file);
this.$axios({
method: 'post',
url: '/file/fileUpload',
headers:this.headers,
timeout: 30000,
data: FormDatas
}).then(res=>{
if(res.data.id != '' || res.data.id != null){
this.fileList.push(item.file);//成功过后手动将文件添加到展示列表里
let i = this.fileList.indexOf(item.file)
this.fileList[i].id = res.data.id;//id也添加进去,最后整个大表单提交的时候需要的
if(this.fileList.length > 0){//如果上传了附件就把校验规则给干掉
this.fileflag = false;
this.$set(this.rules.url,0,'')
}
//this.handleSuccess();
}
})
},
//上传成功后的回调
handleSuccess(){
},
5. 轮播图展示多张图片
效果如下:
1.安装swiper(我安装的是4.5.1)
npm install swiper@4.5.1
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'
新建SwiperBanner.vue
- 完整代码如下:粘贴复制,替换自己的数据就可以
<template>
<div>
<div class="pc-banner">
<div class="swiper-container">
<div class="swiper-wrapper" style="display: flex;align-items: center;">
<div class="swiper-slide" v-for="item in imgList" :key="item.index">
<img :src="item.src" alt="" height="200px">
</div>
</div>
</div>
<div class="swiper-pagination"></div>
<div class="button">
<div class="swiper-button-prev">
</div>
<div class="swiper-button-next">
</div>
</div>
</div>
</div>
</template>
<script>
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'
export default {
props: {
// 这里是展示图片的路径数组
imgList: {
type: Array,
default: [],
},
},
data() {
return {}
},
mounted() {
this.Lunbo()
},
methods: {
Lunbo() {
var swiper = new Swiper('.swiper-container', {
//这里的4是展示图片的张数
slidesPerView: 4,
breakpoints: {
750: {
slidesPerView: 1,
},
990: {
slidesPerView: 2,
},
},
spaceBetween: 0,
loop: true,
speed: 1000,
autoplay: true,
autoplayDisableOnInteraction: false,
disableOnInteraction: true,
observer: true,
observeParents: true,
pagination: '.swiper-pagination',
paginationClickable: true,
mousewheelControl: true,
debugger: true,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
// 鼠标移入停止播放,鼠标离开继续轮播
swiper.el.onmouseover = function () {
swiper.autoplay.stop()
}
swiper.el.onmouseleave = function () {
swiper.autoplay.start()
}
},
},
}
</script>
<style lang="scss" scoped>
.pc-banner {
position: relative;
.swiper-container {
width: 100%;
}
.button {
width: 100%;
display: flex;
justify-content: space-between;
position: absolute;
top: 50%;
.swiper-button-next {
color: black;
}
}
}
@media only screen and (min-width: 1200px) {
.main {
background: springgreen;
}
}
/*最大的宽度是1200px,小于1200px都适用于这里*/
@media only screen and (max-width: 960px) {
.main {
width: 100%;
}
}
/*
大于min-width的宽度,小于max-width宽度
* */
@media only screen and (min-width: 960px) and (max-width: 1200px) {
.main {
width: 100%;
}
}
.swiper-slide {
-webkit-transition: transform 1s;
-moz-transition: transform 1s;
-ms-transition: transform 1s;
-o-transition: transform 1s;
// -webkit-transform: scale(0.7);
// transform: scale(0.7);
}
.swiper-slide-active {
-webkit-transform: scale(1);
transform: scale(1);
}
.none-effect {
-webkit-transition: none;
-moz-transition: none;
-ms-transition: none;
-o-transition: none;
}
.swiper-slide {
img {
width: 100%;
display: block;
}
}
.button {
width: 100%;
margin: auto;
position: relative;
top: 25%;
}
@media screen and (max-width: 750px) {
.button {
width: 100%;
}
}
.swiper-button-prev {
width: 40px;
height: 40px;
border-radius: 50%;
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l4.2%2C4.2L8.4%2C22l17.8%2C17.8L22%2C44L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")
#c9c9ca center 50%/50% 50% no-repeat;
}
.swiper-button-next {
width: 40px;
height: 40px;
border-radius: 50%;
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L5%2C44l-4.2-4.2L18.6%2C22L0.8%2C4.2L5%2C0z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")
#c9c9ca center 50%/50% 50% no-repeat;
}
@media screen and (max-width: 750px) {
.button div {
width: 28px;
height: 28px;
}
}
</style>
父组件使用:
6.css 鼠标悬浮时变成小手指
.cursor {
cursor: pointer; //悬浮时变手指
}
PS:工作中用过的一些知识点,自己记录的笔记和整理来网络上的资源 ,方便以后复习使用。