Vue2大屏项目的简要总结
1、屏幕自适应 — v-scale-screen
简介
实现的主要核心手段就是使用css属性transform实现缩放效果,会进行等比例计算达到等比缩放效果
使用
// 1、安装依赖
npm install v-scale-screen -save
# or
yarn add v-scale-screen
// 2、main.js中引入
import VScaleScreen from 'v-scale-screen'
Vue.use(VScaleScreen)
// 3、使用
<v-scale-screen width="1920" height="1080">
<!--页面内容-->
</v-scale-screen>
简要说明
- 通过该方法实现屏幕自适应无需考虑使用rem等单位,直接px布局即可。
实现效果
- 正常打开情况下
- 调整浏览器大小后显示情况
2、数字翻牌器 - vue-count-to
简介
是一个组件插件,像组件一样注册就可使用
使用
// 1、安装
npm install vue-count-to
// 2、引入
import CountTo from 'vue-count-to'
// 3、注册
components: {
CountTo
},
// 4、使用
// 变化前数据startVal:Number
// 变化后数据endVal:Number
// 变化时间间隔duration:ms
<CountTo
:startVal='startVal'
:endVal='endVal'
:duration='duration'
/>
项目中使用
封装数字翻牌部分,将数据以对象的形式传递过去
// 数据(假设父组件传递过来的数据是下面这个)
testData: {
startVal: 0,
endVal: 32,
}
// 至于duration的话看个人情况吧,直接再翻牌组件中写死也行
补充说明
其实dataV也有数字翻牌器功能,但这种方法和dataV的数字翻牌器更加易于理解并且更加直观,大家可以研究研究
3、Echarts图表的使用
简介
大屏中echarts图表展示几乎是不可避免的,以图表的形式展示数据给人的感官更加直观舒服,能够清除的反映数据的变化。下面是Vue项目中echarts图表的使用
使用
// 1、下包
npm install echarts --save
// 2、全局引入
import * as echarts from "echarts"; // 引入echarts
Vue.prototype.$echarts = echarts;
// 3、组件中使用 HuLiDengJi.vue
// 模板
<template>
<div ref="huLiRef"></div>
</template>
// 逻辑部分
async mounted() {
this.huLiEcharts = this.$echarts.init(this.$refs.huLiRef);
this.drawLine();
},
data() {
return {
huLiEcharts: "",
options: {}, // echarts图表的数据,可在线上调试后复制即可,但里面的数据部分需要父组件传递,因为是会变化的
};
},
// 方法
methods: {
drawLine() {
this.huLiEcharts.setOption(this.option);
}
},
// 侦听器 -- 数据变化重新渲染
watch: {
huLiData: {
deep: true,
// immediate: true,
handler() {
this.drawLine();
},
},
},
4、echarts图表自动轮播tooltip
简介
最终效果是实现鼠标在不移入echarts图的情况下,能够让他以一定时间间隔自动顺序选中内容进行展示,当鼠标移入后会停止自动轮播,鼠标移除后又回复轮播
代码
1、先将自动轮播方法封装成一个单独的js文件
/**
* echarts tooltip轮播
* @param chart ECharts实例
* @param chartOption echarts的配置信息
* @param options object 选项
* {
* interval 轮播时间间隔,单位毫秒,默认为2000
* loopSeries boolean类型,默认为false。
* true表示循环所有series的tooltip,false则显示指定seriesIndex的tooltip
* seriesIndex 默认为0,指定某个系列(option中的series索引)循环显示tooltip,
* 当loopSeries为true时,从seriesIndex系列开始执行。
* updateData 自定义更新数据的函数,默认为null;
* 用于类似于分页的效果,比如总数据有20条,chart一次只显示5条,全部数据可以分4次显示。
* }
* @returns {{clearLoop: clearLoop}|undefined}
*/
export function loopShowTooltip(chart, chartOption, options) {
let defaultOptions = {
interval: 2000,
loopSeries: false,
seriesIndex: 0,
updateData: null,
};
if (!chart || !chartOption) {
return;
}
let dataIndex = 0; // 数据索引,初始化为-1,是为了判断是否是第一次执行
let seriesIndex = 0; // 系列索引
let timeTicket = 0;
let seriesLen = chartOption.series.length; // 系列个数
let dataLen = 0; // 某个系列数据个数
let chartType; // 系列类型
let first = true;
let lastShowSeriesIndex = 0;
let lastShowDataIndex = 0;
if (seriesLen === 0) {
return;
}
// 待处理列表
// 不循环series时seriesIndex指定显示tooltip的系列,不指定默认为0,指定多个则默认为第一个
// 循环series时seriesIndex指定循环的series,不指定则从0开始循环所有series,指定单个则相当于不循环,指定多个
// 要不要添加开始series索引和开始的data索引?
if (options) {
options.interval = options.interval || defaultOptions.interval;
options.loopSeries = options.loopSeries || defaultOptions.loopSeries;
options.seriesIndex = options.seriesIndex || defaultOptions.seriesIndex;
options.updateData = options.updateData || defaultOptions.updateData;
} else {
options = defaultOptions;
}
// 如果设置的seriesIndex无效,则默认为0
if (options.seriesIndex < 0 || options.seriesIndex >= seriesLen) {
seriesIndex = 0;
} else {
seriesIndex = options.seriesIndex;
}
/**
* 清除定时器
*/
function clearLoop() {
if (timeTicket) {
clearInterval(timeTicket);
timeTicket = 0;
}
chart.off("mousemove", stopAutoShow);
zRender.off("mousemove", zRenderMouseMove);
zRender.off("globalout", zRenderGlobalOut);
}
/**
* 取消高亮
*/
function cancelHighlight() {
/**
* 如果dataIndex为0表示上次系列完成显示,如果是循环系列,且系列索引为0则上次是seriesLen-1,否则为seriesIndex-1;
* 如果不是循环系列,则就是当前系列;
* 如果dataIndex>0则就是当前系列。
*/
let tempSeriesIndex =
dataIndex === 0
? options.loopSeries
? seriesIndex === 0
? seriesLen - 1
: seriesIndex - 1
: seriesIndex
: seriesIndex;
let tempType = chartOption.series[tempSeriesIndex].type;
if (tempType === "pie" || tempType === "radar" || tempType === "map") {
chart.dispatchAction({
type: "downplay",
seriesIndex: lastShowSeriesIndex,
dataIndex: lastShowDataIndex,
}); // wait 系列序号为0且循环系列,则要判断上次的系列类型是否是pie、radar
}
}
/**
* 自动轮播tooltip
*/
function autoShowTip() {
let invalidSeries = 0;
let invalidData = 0;
function showTip() {
// chart不在页面中时,销毁定时器
let dom = chart.getDom();
if (document !== dom && !document.documentElement.contains(dom)) {
clearLoop();
return;
}
// 判断是否更新数据
if (
dataIndex === 0 &&
!first &&
typeof options.updateData === "function"
) {
options.updateData();
chart.setOption(chartOption);
}
let series = chartOption.series;
let currSeries = series[seriesIndex];
if (
!series ||
series.length === 0 ||
!currSeries ||
!currSeries.type ||
!currSeries.data ||
!currSeries.data.length
) {
return;
}
chartType = currSeries.type; // 系列类型
dataLen = currSeries.data.length; // 某个系列的数据个数
let tipParams = {
seriesIndex: seriesIndex,
};
switch (chartType) {
case "pie":
// 处理饼图中数据为0或系列名为空的不显示tooltip
if (
!currSeries.data[dataIndex].name ||
currSeries.data[dataIndex].name === "空" ||
!currSeries.data[dataIndex].value
) {
invalidData += 1;
dataIndex = (dataIndex + 1) % dataLen;
if (options.loopSeries && dataIndex === 0) {
// 数据索引归0表示当前系列数据已经循环完
// 无效数据个数个总数据个数相等,则该系列无效
if (invalidData === dataLen) {
invalidSeries += 1;
}
// 新系列,重置无效数据个数
invalidData = 0;
// 系列循环递增1
seriesIndex = (seriesIndex + 1) % seriesLen;
// 系列数循环至起始值时重置无效系列数
if (seriesIndex === options.seriesIndex) {
if (seriesLen !== invalidSeries) {
// 下一次系列轮回,重置无效系列数
invalidSeries = 0;
showTip();
} else {
// 下一次系列轮回,重置无效系列数
invalidSeries = 0;
clearLoop();
}
} else {
showTip();
}
} else if (!options.loopSeries && dataIndex === 0) {
if (dataLen !== invalidData) {
invalidData = 0;
showTip();
} else {
invalidData = 0;
clearLoop();
}
} else {
showTip();
}
return;
}
// eslint-disable-next-line no-fallthrough
case "map":
case "chord":
tipParams.name = currSeries.data[dataIndex].name;
break;
case "radar": // 雷达图
tipParams.seriesIndex = seriesIndex;
// tipParams.dataIndex = dataIndex;
break;
case "lines": // 线图地图上的lines忽略
dataIndex = 0;
seriesIndex = (seriesIndex + 1) % seriesLen;
invalidSeries++; // 记录无效系列数,如果无效系列数和系列总数相等则取消循环显示
if (seriesLen !== invalidSeries) {
showTip();
} else {
clearLoop();
}
return;
default:
tipParams.dataIndex = dataIndex;
break;
}
if (chartType === "pie" || chartType === "radar" || chartType === "map") {
if (!first) {
cancelHighlight();
}
// 高亮当前图形
chart.dispatchAction({
type: "highlight",
seriesIndex: seriesIndex,
dataIndex: dataIndex,
});
}
// 显示 tooltip
tipParams.type = "showTip";
chart.dispatchAction(tipParams);
lastShowSeriesIndex = seriesIndex;
lastShowDataIndex = dataIndex;
dataIndex = (dataIndex + 1) % dataLen;
if (options.loopSeries && dataIndex === 0) {
// 数据索引归0表示当前系列数据已经循环完
invalidData = 0;
seriesIndex = (seriesIndex + 1) % seriesLen;
if (seriesIndex === options.seriesIndex) {
invalidSeries = 0;
}
}
first = false;
}
showTip();
timeTicket = setInterval(showTip, options.interval);
}
// 关闭轮播
function stopAutoShow() {
if (timeTicket) {
clearInterval(timeTicket);
timeTicket = 0;
if (chartType === "pie" || chartType === "radar" || chartType === "map") {
cancelHighlight();
}
}
}
let zRender = chart.getZr();
function zRenderMouseMove(param) {
if (param.event) {
// 阻止canvas上的鼠标移动事件冒泡
// param.event.cancelBubble = true;
}
stopAutoShow();
}
// 离开echarts图时恢复自动轮播
function zRenderGlobalOut() {
// console.log("移出了")
// console.log(timeTicket)
if (!timeTicket) {
autoShowTip();
}
}
// 鼠标在echarts图上时停止轮播
chart.on("mousemove", stopAutoShow);
zRender.on("mousemove", zRenderMouseMove);
zRender.on("globalout", zRenderGlobalOut);
autoShowTip();
return {
clearLoop: clearLoop,
};
}
2、在需要使用改方法的文件中引入
import { loopShowTooltip } from "../../../tooltip-auto-show-vue.js";
export default {
data() {
return {
tootipTimer:""
};
},
}
3、引用刚才封装的js方法
myChart.setOption(option);
this.tootipTimer && this.tootipTimer.clearLoop(); // this.tootipTimer 在data里定义
this.tootipTimer = 0;
// 调用轮播的方法
this.tootipTimer = loopShowTooltip(myChart, option, {
interval: 2000, // 轮播间隔时间
loopSeries: true, // 是否开启轮播循环
// loopSeries: boolean类型,默认为false。true表示循环所有series的tooltip;false则显示指定seriesIndex的tooltip。
// seriesIndex: 默认为0,指定某个系列(option中的series索引)循环显示tooltip,当loopSeries为true时,从seriesIndex系列开始执行。
});
效果
初始效果
会自动的顺序选中显示
5、echarts图标禁用legend默认的点击行为实现
简介
我遇到的场景是基于上面的一个场景,默认情况下点击图标的legend时会隐藏对应区域,但如果存在自动轮播的时候,就会产生一个空缺,也就是你让点击的legend内容隐藏了,但轮播的时候还会对隐藏区域进行轮播,造成轮播到隐藏部分时会出现显示的一个空缺,如果我们去禁用掉隐藏区域这个功能后,那么也就不会出现这一问题了
代码
myChart.on('legendselectchanged', function (params) {
myChart.setOption({
legend:{selected:{[params.name]: true}}
})
console.log('点击了', params.name);
// do something
});
6、表格自动滚动
简介
大屏中很可能遇到图标自动滚动效果,这个可以使用dataV的一个组件进行实现
代码
// 模板使用
<dv-scroll-board :config="config" style="width:500px;height:220px" />
// 数据部分
export default {
header: ['列1', '列2', '列3'], // 表头
data: [
['行1列1', '行1列2', '行1列3'],
['行2列1', '行2列2', '行2列3'],
['行3列1', '行3列2', '行3列3'],
['行4列1', '行4列2', '行4列3'],
['行5列1', '行5列2', '行5列3'],
['行6列1', '行6列2', '行6列3'],
['行7列1', '行7列2', '行7列3'],
['行8列1', '行8列2', '行8列3'],
['行9列1', '行9列2', '行9列3'],
['行10列1', '行10列2', '行10列3']
]
}
注意事项
- 数据改变时用修改整个config对象的形式进行修改,因为它组件内部没用设置deep进行深度侦听,因此只修改configdata是监测不到的,刷新不了
- 轮播表还有很多配置可参考,具体可以看一下dataV官网
7、公告类的部分实现自动滚动
简介
需要一个类似公告消息滚动的实现,移动端一般有对应的vant或者uView可以使用,pc的话element-ui暂时没有,但也是有方法可以实现的
代码
新建一个组件使用就行
<template>
<div
id="box"
ref="box"
>
<div
class="marquee-box"
ref="marquee"
@mouseover="menter"
@mouseleave="mleave"
>
<p
ref="cmdlist"
id="pWidth"
>
{{ sendVal }}
</p>
</div>
</div>
</template>
<script>
export default {
name: 'ScrollMessageTwo',
props: {
sendVal: {
type: String,
default: '暂无'
}
},
data() {
return {
value: 0,
timer: '', //计时器
pwidth: 0, //公告文本的宽度
windowWidth: 0 // 设备屏幕的宽度
}
},
mounted() {
this.windowWidth = document.querySelector('#box').clientWidth
let element = this.$refs.cmdlist
this.pwidth = document.defaultView
.getComputedStyle(element, '')
.width.split('px')
this.timer = setInterval(this.clickCommend, 20)
},
watch: {
value(newValue) {
let allWidth = parseInt(this.windowWidth) + parseInt(this.pwidth[0])
if (newValue <= -allWidth) {
this.$refs.cmdlist.style.marginLeft = this.windowWidth + 'px'
this.value = 0
}
}
},
methods: {
clickCommend() {
let _this = this
this.$nextTick(() => {
this.value -= 1
this.$refs.cmdlist.style.marginLeft =
_this.windowWidth + this.value + 'px'
})
},
menter() {
clearInterval(this.timer)
},
mleave() {
this.timer = setInterval(this.clickCommend, 20)
}
},
beforeDestroy() {
clearInterval(this.timer)
}
}
</script>
<style scoped lang="scss">
#box {
display: flex;
align-items: center;
overflow: hidden;
}
.marquee-box {
display: inline-block;
overflow: auto;
}
#pWidth {
display: inline-block;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
}
</style>
说明
原参考文章是获取整个屏幕的宽度,也就是屏幕宽度的一个消息滚动,但我遇到的场景只是一小块内容区域滚动,因此对它windowWidth的值进行了修改,大家也可以按自己的情况进行修改
8、区域内容自动滚动实现
简介
类似于表格自动滚动,但这不是一个表格却也要进行滚动
当内容超过高度时,开启自动滚动
默认向下滚动,触底后在向上
点击内容区域后还会停止滚动,此时你可以通过鼠标滚轮进行滚动
代码实现
<template>
<div
:id="scrollId"
style="border:1px solid red;
height: 300px;
width: 200px;
overflow-y: scroll;
position: absolute;
text-align: center;
top: 10%;
left: 40%;"
>
<div>
滚动内容1<br>
滚动内容2<br>
滚动内容3<br>
滚动内容4<br>
滚动内容5<br>
滚动内容6<br>
滚动内容7<br>
滚动内容8<br>
滚动内容9<br>
滚动内容10<br>
滚动内容11<br>
滚动内容12<br>
滚动内容13<br>
滚动内容14<br>
滚动内容15<br>
滚动内容16<br>
滚动内容17<br>
滚动内容18<br>
</div>
</div>
</template>
<script>
export default {
data() {
return {
scrollTimer: null, // 滚动定时器
pauseTimer: null, // 暂停定时器
scrollId: 'scrollId', // 滚动容器id
scrollDirection: 'down' // 滚动方向 up向上 down向下
}
},
destroyed() {
// 清理定时器
clearTimeout(this.pauseTimer)
this.pauseTimer = null
clearInterval(this.scrollTimer)
this.scrollTimer = null
// 清理点击监听
window.document.removeEventListener('click', this.pauseScroll)
},
mounted() {
this.dataCompleteFun()
},
methods: {
// 数据加载完成方法
dataCompleteFun() {
// 开启滚动
this.autoScroll()
},
autoScroll() {
const scrollHeight = document.getElementById(this.scrollId).scrollHeight
const clientHeight = document.getElementById(this.scrollId).clientHeight
const scroll = scrollHeight - clientHeight
// 滚动长度为0
if (scroll === 0) {
return
}
// 触发滚动方法
this.scrollFun()
// 去除点击监听
window.document.removeEventListener('click', this.pauseScroll)
// 重设点击监听
window.document.addEventListener('click', this.pauseScroll, false)
},
pauseScroll() {
// 定时器不为空
if (this.scrollTimer) {
// 清除定时器
clearInterval(this.scrollTimer)
this.scrollTimer = null
// 一秒钟后重新开始定时器
this.pauseTimer = setTimeout(() => {
this.scrollFun()
}, 2000)
}
},
scrollFun() {
// 如果定时器存在
if (this.scrollTimer) {
// 则先清除
clearInterval(this.scrollTimer)
this.scrollTimer = null
}
this.scrollTimer = setInterval(() => {
const scrollHeight = document.getElementById(this.scrollId).scrollHeight
const clientHeight = document.getElementById(this.scrollId).clientHeight
const scroll = scrollHeight - clientHeight
// 获取当前滚动条距离顶部高度
const scrollTop = document.getElementById(this.scrollId).scrollTop
// 向下滚动
if (this.scrollDirection === 'down') {
const temp = scrollTop + 1
document.getElementById(this.scrollId).scrollTop = temp // 滚动
// 距离顶部高度 大于等于 滚动长度
if (scroll <= temp) {
// 滚动到底部 停止定时器
clearInterval(this.scrollTimer)
this.scrollTimer = null
// 改变方向
this.scrollDirection = 'up'
// 一秒后重开定时器
setTimeout(() => {
this.scrollFun()
}, 1000)
}
// 向上滚动
} else if (this.scrollDirection === 'up') {
const temp = scrollTop - 0.5
document.getElementById(this.scrollId).scrollTop = temp // 滚动
// 距离顶部高度 小于等于 0
if (temp <= 0) {
// 滚动到底部 停止定时器
clearInterval(this.scrollTimer)
this.scrollTimer = null
// 改变方向
this.scrollDirection = 'down'
// 一秒后重开定时器
setTimeout(() => {
this.scrollFun()
}, 1000)
}
}
}, 150)
}
}
}
</script>
更新
后期对排版进行了调整