申明:本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!
前言
《金融行业前端探索》专题系列文章将构建现代化金融应用的技术与实践,提供理论知识和技术原理,还通过丰富的案例和实例,带大家一步步实现一个简易的金融终端系统,帮助读者将所学知识应用于实际项目中。此系列文章,适用于对金融行业前端感兴趣的同学,以及对前端跨端、可视化、AI技术、大数据等方面感兴趣的同学。需要提前了解技术:electron、vite、vue,canvas和其他前端基础知识等。
本文为《金融行业前端探索》第2篇文章 :使用electron-vite-vue 搭建一个金融终端框架,包含以下内容:
【1】前文《金融行业前端探索》第1篇回顾之登录到系统框架(闪烁问题优化)
【2】系统框架导航和菜单(基于ElementUI实现)
【3】系统底部内容轮播功能设计和实现(纯CSS3方案)
【4】系统实现新手引导功能的设计和实现(canvas遮罩层+DOM方案)
本项目完整代码地址:electron-vite-vue-ft(持续更新代码)
下一篇: 《金融行业前端探索》(2)行情图
一、前文回顾之登录到系统框架-解决登录闪烁问题
上回我们在《金融行业前端探索:开篇使用electron-vite-vue 搭建一个金融终端框架之登录功能》 中讲到了登录,我们要跳转到系统的框架页面。这里我们正常思维是,点击登录按钮做登录校验,随后跳到系统框架页面,使用 Electron 的 remote
模块来获取对主进程中 BrowserWindow
实例的引用,并调用其 setSize
方法来更改宽度和高度。同时,使用 screen
模块获取屏幕尺寸,并计算出居中显示时的坐标位置。
js
const { remote, screen } = require('electron');
const button = document.getElementById('resizeButton');
button.addEventListener('click', () => {
const { BrowserWindow } = remote;
const mainWindow = BrowserWindow.getFocusedWindow();
if (mainWindow) {
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
const newWidth = 800; // 设置新的宽度
const newHeight = 600; // 设置新的高度
const x = Math.floor((width - newWidth) / 2); // 计算居中的 x 坐标
const y = Math.floor((height - newHeight) / 2); // 计算居中的 y 坐标
mainWindow.setSize(newWidth, newHeight); // 设置新的宽度和高度
mainWindow.setPosition(x, y); // 设置窗口位置为居中
}
});
但现实中我们运行的时候发现,从登录页面到首页框架加载页面时出现出现闪烁
于是我们正常思维使用隐藏和显示的方式:在加载新页面之前,将窗口隐藏起来,然后在新页面加载完成后再显示窗口。这样,用户将不会看到加载过程中的闪烁。
js
//
function handleButtonClick() {
// 隐藏窗口
mainWindow.hide();
// 加载新的页面
mainWindow.loadURL(winURL);
// 监听新页面加载完成事件
mainWindow.webContents.once('did-finish-load', () => {
// 显示窗口
mainWindow.show();
});
}
通过验证,这个方式并不理想,于是就使用了另外一个方案,登录和首页实例进行拆分进行处理。在登录切换页面的时候,把登录页面的实例销毁。这样相比看起来体验好一些
js
ipcMain.on('openMainWindow', () => {
if (!mainWindow) {
createMainWindow()
}
loginWindow.destroy()
loginWindow = null
})
二、系统框架导航和菜单
导航栏的默认状态让界面整体的信息从左到右呈现出疏密布局,当用户需更大限度利用屏幕空间浏览内容时,可调整导航栏的宽窄状态,可以拉伸导航栏展示。让内容区域可以最大范围展示出来。
菜单的获取和用户角色对应起来,不同的角色可以配置不同的菜单,所以关于菜单需要有一套配套的用户中心系统搭配。这里是基于ElementUI plus
的el-menu
组件 做了一个简单的实现
实现可以参考代码src\renderer\src\components\Layout\leftMenu.vue
三、系统底部功能实现
底部左侧滚动轮播内容功能
底部左侧功能通常为指数行情或者一些新闻滚动功能。当鼠标经过的时候,内容区域不再滚动,方便使用者看到实时的相关数据。
这里推荐一个最简单的实用css方案,我们以指数行情为例,我们将元素的文本内容水平展示在一行中不换行,并对元素应用名为 myAnimation
的动画效果。该动画效果将在持续 50 秒的时间内,以线性的速度循环播放,从元素的初始位置开始,没有延迟。当鼠标经过的时候动画效果停止在当前内容上。
css
@keyframes myAnimation {
0% {
transform: translate(0);
} /* 初始状态 */
100% {
transform: translate(-50%);
} /* 结束状态 */
}
....
.left-market {
display: flex;
align-items: center;
white-space: nowrap;
transform: translate(0);
animation: myAnimation 50s linear 0s infinite;
&:hover {
animation-play-state: paused;
}
-
white-space: nowrap;
:这个属性指定了元素内文本的处理方式。nowrap
表示文本不换行,将在一行内显示。这通常用于确保文本不会自动换行,而是水平展示。 -
transform: translate(0);
:这个属性通过translate
函数对元素进行平移变换。在这个例子中,translate(0)
表示元素不进行任何平移,保持原始位置不变。 -
animation: myAnimation 50s linear 0s infinite;
:这个属性用于创建和控制动画效果。其中的值解释如下:myAnimation
是指定要应用的关键帧动画的名称。50s
指定动画的持续时间为 50 秒。linear
表示动画的时间函数为线性,即在整个动画过程中速度是恒定的。0s
表示动画延迟开始的时间为 0 秒。这表示动画将立即开始,没有延迟。infinite
表示动画循环次数为无限。动画将一直循环播放,不会停止
-
animation-play-state: paused
用于控制动画的播放状态。当设置为paused
时,动画将被暂停,停留在当前的帧上。
效果如下
为了美观,我们在滚动内容 前后 加上一个内容出现和消失过渡渐变,使得显示更加的平滑,这里我们通过css的伪类和background-image: linear-gradient
背景呈现为一个渐变的背景效果
css
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 100%;
background-image: linear-gradient(90deg, #212529, rgba(33, 37, 41, 0.15) 70%, transparent);
z-index: 1;
}
&:after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 100%;
background-image: linear-gradient(-90deg, #212529, rgba(33, 37, 41, 0.15) 70%, transparent);
z-index: 1;
}
实现可以参考代码src\renderer\src\components\Layout\foot.vue
四、系统实现新手引导功能
系统实现新手引导功能的意义在于提供用户友好的指引和引导,帮助新用户熟悉和金融行业系统的功能和界面。
以下是一些通用的新手引导功能主要的意义和好处:
- 提高用户体验(UX)和用户满意度: 新手引导功能可以帮助用户快速上手和熟悉应用程序,减少用户的困惑和迷失感。通过向用户提供明确的指引和说明,用户可以更轻松地完成任务,并更好地理解应用程序的功能和价值。
- 降低用户学习成本: 对于新用户来说,了解一个全新的应用程序可能需要一定的学习曲线。通过引导功能,用户可以在最初的使用阶段得到指导,从而减少学习成本和学习时间。这可以提高用户的学习效率和使用效果。
- 减少用户错误和操作失误: 新手引导功能可以帮助用户避免常见的错误和操作失误。通过引导用户正确地进行操作和输入,可以减少用户因不熟悉应用程序而导致的错误,从而提高用户的准确性和效率。
- 推广核心功能和价值: 引导功能可以突出和介绍应用程序的核心功能和价值,引导用户关注和了解最重要的功能。这有助于传达应用程序的独特卖点和价值主张,提高用户对应用程序的认知和理解。
- 增加用户参与度和留存率: 通过帮助用户快速熟悉应用程序并获得成功体验,新手引导功能可以增加用户的参与度和留存率。用户在初期获得积极的体验和成就感,更有可能继续使用应用程序并成为忠实用户。
新手引导功能实现思考
- 目前市面上有一些轮子可以用,比如
driver.js
但业务千般万难,一些定制化的情况通用的轮子,无法满足自身的业务需求(样式、配置项多而杂、未知BUG维护),所以自行实现一个新手引导功能很有必要 - 新手引导功能核心点是,配置项的设计,遮罩层的设计,功能的定义(上一步、下一步、窗口变化监听)
新手引导实现具体步骤
配置项设计
配置项这里我们简单设计了支持基本的,新手引导需要的元素为"上一步 "、"下一步 "、"完成 "、"跳过 "、"每一步信息配置"等功能。
js
config = {
prevLabel: '上一步',
nextLabel: '下一步',
skipLabel: '跳过',
doneLabel: '完成',
steps: [
{
domId: 'logoid',
title: 'logo区域',
content: '这里是展示的系统logo,点击可以回到首页内容',
width: 270, //(可选)框选区域自定义宽度,当不指定时,组件自动取目标元素的宽度
height: 120 //(可选)框选区域自定义高度,当不指定时,组件自动取目标元素的高度
}
]
}
遮罩层的设计和实现
如何添加遮罩层? 目前行业上比较多的方案是(1) 通过CSS属性实现 用dom拼成中间留白的阴影(2)也有背景图+DOM的组合等等
我们这里采用 canvas 绘制遮罩层,任意一个dom,通过id,查找到这个dom 的宽高,并插入一个遮罩层canvas,这个dom的区域留白不遮罩,其他地方有遮罩
- 在 Vue 组件中,使用
ref
属性给目标 DOM 元素添加一个引用。例如,给目标 DOM 元素添加ref="targetElement"
。 - 在需要获取宽高并插入遮罩层的逻辑中,可以使用
getBoundingClientRect()
方法来获取目标 DOM 元素的宽高和位置信息。 - 创建一个遮罩层的 Canvas 元素,并设置其样式和大小,使其覆盖整个页面。
- 使用
ctx.clearRect()
方法清除遮罩层 Canvas 上的区域,以实现目标 DOM 元素的区域留白。 - 使用
ctx.fillRect()
方法在遮罩层 Canvas 上绘制需要遮罩的区域
js
const addMask = (domId) => {
const targetElement = document.getElementById(domId)
const maskCanvas = maskCanvasRef.value
console.log('maskCanvas', maskCanvas)
const ctx = maskCanvas.getContext('2d')
// 获取目标 DOM 元素的宽高和位置信息
const { width, height, top, left } = targetElement.getBoundingClientRect()
// 设置遮罩层 Canvas 的样式和大小
maskCanvas.style.position = 'fixed'
maskCanvas.style.top = '0'
maskCanvas.style.left = '0'
maskCanvas.style.width = '100%'
maskCanvas.style.height = '100%'
maskCanvas.width = window.innerWidth
maskCanvas.height = window.innerHeight
// 清除遮罩层 Canvas 上的区域
ctx.clearRect(0, 0, maskCanvas.width, maskCanvas.height)
// 绘制遮罩层 Canvas 上的遮罩区域
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)'
ctx.fillRect(0, 0, maskCanvas.width, maskCanvas.height)
ctx.clearRect(left, top, width, height)
}
说明模块设计和实现
制定宽高的 div 作为说明模块,这个div,根据浏览器大小自适应与之前的targetElement的边上 ,并不遮住targetElement,说明模块位置,优先级:右>左>下>上
js
// 控制 右侧优先 再左侧
const handleLeftOrRight = (infoModule, targetRect, infoModuleRect, innerWidth, innerHeight) => {
// 默认右侧
if (targetRect.right + infoModuleRect.width <= innerWidth) {
infoModule.style.left = targetRect.right + 'px'
} else if (targetRect.left - infoModuleRect.width >= 0) {
// 左侧
infoModule.style.left = targetRect.left - infoModuleRect.width + 'px'
}
}
// 控制上下
const handleTopOrBottom = (infoModule, targetRect, infoModuleRect, innerHeight) => {
let top = 0
if (targetRect.bottom + infoModuleRect.height <= innerHeight) {
top = targetRect.bottom - targetRect.height
} else if (targetRect.top - infoModuleRect.height >= 0) {
// 上方
top = targetRect.top + targetRect.height - infoModuleRect.height
}
infoModule.style.top = top + 'px'
}
说明模块的 <div>
添加了 z-index: 1
的样式属性,以确保说明模块位于遮罩层之上。同时,遮罩层的 <canvas>
元素添加了 z-index: 0
的样式属性,使其位于说明模块之下。
监听窗口变化
因为遮罩层和说明模块的位置都是依赖于浏览器的窗口大小变化,定位的,所以窗口变化的时候,遮罩层和说明模块也要同步的更改相对位置。
js
onMounted(() => {
nextTick(() => {
handleIntro()
window.addEventListener('resize', handleIntro)
})
})
这样一个简易的新手引导功能就完成了,当然其中可以自行进行拓展,比如支持图片设置,支持鼠标上下左右键盘联动等功能。
最后
本文从前文回顾之登录到系统框架、到系统框架导航和菜单、底部内容轮播功能实现、系统实现新手引导功能带大家一一实现了对应的功能。这样一个大概的金融系统的框架已经基本成型。
本项目完整代码地址:electron-vite-vue-ft(持续更新代码)
下一篇: 《金融行业前端探索》(3)玩转可视化图表:Vue3+Echarts绘制k线行情图
ps: 暂未编写,更新速度 1-2周一篇