写在前面,博主是个在北京打拼的码农,从事前端工作5年了,做过十多个大大小小不同类型的项目,最近心血来潮在这儿写点东西,欢迎大家多多指教。
目录
本次不是手把手教学,仅仅给大家伙写个开发过程大概情况,能让新人知道大屏大概是怎么个开发写法
本文关键字:vue3后台管理项目插入大屏页面、vue3大屏项目、大屏适配
大屏开发是针对大显示屏幕做数据可视化显示以及操作的一种技术,常用于控制中心、金融交易等领域。( 大屏做成这样,领导想不重用你都难! - 知乎)
vue开发大屏中常用的插件或组件库有
阿里DataV数据可视化
积木报表
iGaoWei/BigDataView
jackchen0120/vueDataV
DataV-Team/Datav 7.5K
同时有第三方开源库:Echarts(Apache ECharts),AntV,Highcharts,D3.js,three.js等
- mounted() {
- this.$nextTick(() => {
- // 监控屏幕尺寸变化
- var bodyStyle = document.createElement("style");
- // 这里根据具体的设计稿尺寸来定
- bodyStyle.innerHTML = `body{width:1920px; height:1080px!important;}`;
- document.documentElement.firstElementChild.appendChild(bodyStyle);
- this.screenWidth = document.body.clientWidth;
- this.screenHeight = document.body.clientHeight;
- window.onresize = () => {
- return (() => {
- this.screenWidth = document.documentElement.clientWidth;
- this.screenHeight = document.documentElement.clientHeight;
- })();
- };
- document.addEventListener("keydown", (e) => {
- if (e.code == "F11") {
- this.screenWidth = document.documentElement.clientWidth;
- this.screenHeight = document.documentElement.clientHeight;
- }
- });
- });
- },
- watch: {
- screenWidth: {
- handler: function () {
- // console.log("val", val);
- let docWidth = document.documentElement.clientWidth;
- let docHeight = document.documentElement.clientHeight;
- var designWidth = 1920, // 这里根据具体的设计稿尺寸来定
- designHeight = 1080, // 这里根据具体的设计稿尺寸来定
- widthRatio = docWidth / designWidth,
- heightRatio = docHeight / designHeight;
- document.body.style = `transform:scale(${widthRatio},${heightRatio});transform-origin:left top;overflow: hidden;`;
- // 应对浏览器全屏切换前后窗口因短暂滚动条问题出现未占满情况
- setTimeout(function () {
- var lateWidth = document.documentElement.clientWidth,
- lateHeight = document.documentElement.clientHeight;
- if (lateWidth === docWidth) return;
-
- widthRatio = lateWidth / designWidth;
- heightRatio = lateHeight / designHeight;
- document.body.style =
- "transform:scale(" +
- widthRatio +
- "," +
- heightRatio +
- ");transform-origin:left top;overflow: hidden;";
- }, 0);
- },
- immediate: true,
- deep: true,
- },
- screenHeight: {
- handler: function () {
- // console.log("val", val);
- let docWidth = document.documentElement.clientWidth;
- let docHeight = document.documentElement.clientHeight;
- var designWidth = 1920, // 这里根据具体的设计稿尺寸来定
- designHeight = 1080, // 这里根据具体的设计稿尺寸来定
- widthRatio = docWidth / designWidth,
- heightRatio = docHeight / designHeight;
- document.body.style = `transform:scale(${widthRatio},${heightRatio});transform-origin:left top;overflow: hidden;`;
- // 应对浏览器全屏切换前后窗口因短暂滚动条问题出现未占满情况
- setTimeout(function () {
- var lateWidth = document.documentElement.clientWidth,
- lateHeight = document.documentElement.clientHeight;
- if (lateWidth === docWidth) return;
-
- widthRatio = lateWidth / designWidth;
- heightRatio = lateHeight / designHeight;
- document.body.style =
- "transform:scale(" +
- widthRatio +
- "," +
- heightRatio +
- ");transform-origin:left top;overflow: hidden;";
- }, 0);
- },
- immediate: true,
- deep: true,
- },
- },
(上方适配代码来源于-最简单的vue大屏实现方式 - 简书)
Echarts相对简单些,容易上手,很多项目二次开发。
echarts等组件库需要写大量的样式覆盖才行,所以有的企业会要求新人会改源码
但实际上很多时候我们通过官方提供的配置项隐藏元素再自己写一些内容定位到指定位置也能实现
其实echart每次图标注入数据有的时候要花不少时间,因为后端返回的数据是不能直接用的,要自己转换过滤成适合插件的格式
而echart图表类型多种多样,我们不可能记住所有方法属性,所以每次基本上都是随用随查
我们发现词云初次加载出现问题,
查看代码
- :style="{ width: this.word_width + 'px' }"
- ref="wz_word_cont"
- class="wz_word_cont"
- :class="special?'large-screen':''"
- id="wz_word_cont"
-
- v-show="wordArr.length > 0"
- >
-
-
-
- .wz_word_cont{
- width: 100% !important;
- height: 220px !important;
- }
问题所在:宽度没指定,初始化识别不到正确的宽,解决方法如下,直接固定宽
- .wz_word_cont{
- width: 340px !important;
- height: 220px !important;
- }
比如页面全屏后出现留白、echarts视图页面窗口调整后才正常(页面初始化时样式错乱)
x轴数据过长轮播展示
在这中间我们可能碰到一些问题,比如echarts词云初始化加载窗口挤到一起,调整浏览器后才自适应,或是柱状图横坐标文字太长需要做倾斜处理这种问题
让eacharts的横坐标文字倾斜:
- xAxis: [
-
- {
-
- data: [],
-
- axisLabel: {
-
- margin: 10,
-
- color: 'rgba(202, 215, 245, 1)',
-
- textStyle: {
-
- fontSize: 7,
-
-
-
- }, rotate: 50, // 设置标签倾斜角度,单位为度
-
- },}]
-
-
-
-
-
数据太多还会引起图叠在一起,解决方法:相关文章
就是加滚动条
关于SCUI
SCUI (SCUI)是一个中后台前端解决方案,基于VUE3和elementPlus实现。
使用最新的前端技术栈,提供各类实用的组件方便在业务开发时的调用,并且持续性的提供丰富的业务模板帮助你快速搭建企业级中后台前端任务。
SCUI的宗旨是 让一切复杂的东西傻瓜化。
今天接到了一个在SCUI后台管理系统中开发一个大屏页面的需求,公司买了一个图书馆管理大屏的项目源码供参考,只有原型没有设计图,只能先借助其他项目的psd图和图标来用,时间紧迫。
直接把大屏项目的视图代码全拷过去,有报错解决报错,缺库引库,谨慎起见直接按照大屏项目库的原版本安装
大屏项目源码是使用的flexible适配,暂时不知道需不需要对大屏页面单独做适配,图书馆这个适配做的一般,窗口上下缩小字和元素都挤到一块了,正常应该取消或调整一些元素的展示
流畅度
大屏项目的流畅度需要很多插件支持,动画效果常使用的animate动画库如下
import WOW from "wow.js";
mounted里写
- var wow = new WOW({
- boxClass: "wow", // animated element css class (default is wow)
- animateClass: "animated", // animation css class (default is animated)
- offset: 0, // distance to the element when triggering the animation (default is 0)
- mobile: true, // trigger animations on mobile devices (default is true)
- live: true, // act on asynchronously loaded content (default is true)
- callback: function () {
- // the callback is fired every time an animation is started
- // the argument that is passed in is the DOM node being animated
- },
- scrollContainer: null, // optional scroll container selector, otherwise use window,
- resetAnimation: true, // reset animation on end (default is true)
- });
- this.$nextTick(() => wow.init());
最后通过class名wow加开启指定动画的class启用
gsap动效库
wow.js动画库
数字丝滑滚动(vue3 数字滚动插件vue-number-roll-plus - 完竣世界) vue3-number-roll-plus
echarts-wordcloud词云库( 一堆五颜六色的词汇的聚在一块,有大有小的散落着)(相关文章)
项目中获取各类时间的地方不少,用的是dayjs
大屏的页面,需求用到无缝滚动列表vue3-seamless-scroll,这个很好用,常用的属性就那么几个,引入后使用,完成列表滚动,说真的这个滚动一加,那味马上就上来了,高级感,这个插件使用起来特别简单好用
- import {Vue3SeamlessScroll} from "vue3-seamless-scroll";
-
- components: {Vue3SeamlessScroll},
-
-
"0.5" :wheel="true" :hover="true" :list="list" class="tableBody"> -
-
碎碎念
有高级感的大屏需要各种丝滑动效插件,很多本质上就是一些封装好的marquee动画
关于大屏我们很多的element插件都不太实用,像表格样式之类的我们要覆盖很久,所以很多时候不如自己写一些,毕竟大屏一般不会有分页
大屏项目要写很多组件,毕竟一小块一小块的方便维护,我推荐使用vuex做数据传递(
我在这里碰到了vuex自动导入文件内容的坑
写完新文件需要重启项目才能生效,各位如果没有设置自动导入可以忽略
),因为组件封装层次比较深的话会方便祖孙组件通信,组件内通过computed实现监听,两天时间做出两个大屏页面听起来确实有点扯,但大家可以结合很多开源项目,或直接买别人的大屏项目源码,在成型的架子上改动,很快就能完成大屏页面的开发
视觉效果
我们经常看到大屏的一些闪动效果感觉很牛,实际上有些视觉效果是通过一个个图片通过canvas循环播放形成的,就像以前的动画片一样,一帧一帧播放
- <canvas ref="animation_canvas" class="animation_canvas" id="animation_canvas">canvas>
-
- <script>
-
- export default {
- name: "sequence",
- data() {
- return {}
- },
- props: {
- // 文件数量
- fileLength: {
- type: Number,
- default() {
- return 70;
- }
- },
- // 动画间隔
- IntervalTime: {
- type: Number,
- default() {
- return 80;
- }
- },
- },
- async mounted() {
- var that = this;
- await that.Sequence()
- },
- methods: {
- async Sequence() {
- var that = this;
- //初始化参数
- var canvas = null;
- var ctx = null;
- var sources = [];
-
- async function loadImages2() {
- for (let i = 0; i <= 74; i++) {
- const image = await import(`./topbg/topbg_${i}.png`);
- sources.push(image.default);
- }
- }
-
- await loadImages2();
-
- var width = this.$refs.animation_canvas.offsetWidth
- var height = this.$refs.animation_canvas.offsetHeight
- canvas = this.$refs.animation_canvas;
- canvas.width = width;
- canvas.height = height;
-
- ctx = canvas.getContext("2d");
-
- //预加载序列图片
- function loadImages(sources, callback) {
- var loadedImages = 0;
- var numImages = 0;
- var images = [];
- // get num of sources
- numImages = sources.length;
- for (var i = 0, len = sources.length; i < len; i++) {
- images[i] = new Image();
- //当一张图片加载完成时执行
- images[i].onload = function () {
- //当所有图片加载完成时,执行回调函数callback
- if (++loadedImages >= numImages) {
- callback(images);
- }
- };
- //把sources中的图片信息导入images数组
- images[i].src = sources[i];
- // console.log(images);
- }
- }
-
- //播放图片动画
- function playImages(images) {
- var imageNum = images.length;
- var imageNow = 0;
- setInterval(function () {
- ctx.fillStyle = "rgba(0,0,0,0)";
- ctx.clearRect(0, 0, width, height);
- ctx.fillRect(0, 0, width, height);
- ctx.drawImage(images[imageNow], 0, 0, width, height);
- imageNow++;
- if (imageNow >= imageNum) {
- imageNow = 0;
- }
- }, that.IntervalTime)
- }
-
- //ctx.globalAlpha=0.5
- //执行图片预加载,加载完成后执行main
- loadImages(sources, function (images) {
- playImages(images)
- });
- }
- },
- }
- script>
-
- <style lang="scss" scoped>
- .animation_canvas {
- position: absolute;
- left: 0;
- top: 0px;
- width: 100%;
- height: 100%;
- z-index: -1;
- }
- style>
字体
大屏的字体是怎么整出来的
最后设定所有接口5分钟调用一次,给数据重新赋值实现实时刷新