项目介绍

124 阅读3分钟

项目介绍:

我在华为深度参与开发了基于低代码平台的数据可视化构建平台的研发工作,该项目主要使用React作为前端框架,HTML5、CSS3、js以及TS构建网页和实现用户交互效果,UI组件库用的是华为内部的Eview-react,采用Echart实现数据的可视化工作,Git作为版本控制工具,该项目分为DashBoard设计器和运行时两种状态,非专业的工程师可以通过DashBoard设计器去拖拽组件到设计区去搭建专业水准的可视化大屏应用,目前该项目已经支持几十种组件,比如柱状图、饼图、报表等,同时组件也支持多种数据源,比如api请求数据,静态配置数据等,用户在搭建完成以后,可以将应用选择发布,此时,大屏应用会进入运行时状态,这时候,一款简单实时数据展示的大屏应用就搭建完成了,整个搭建的过程可以实现无代码。

实现base64格式的svg图片变换颜色。

答:

我在项目开发的过程中,遇到一个比较记忆深刻的难点是,实现一个base64格式的svg图片去动态变换颜色。首先,这个功能的需求是,我们的dashboard设计器,有个Text组件,该组件可以绑定不同的数据源,从而从服务器请求不同的数据,给大屏做展示动态数据的作用。我们为了更加直观看到数据的实时变化,于是新增了一个阈值染色的功能,工程师可以在阈值染色的面板配置不同条件,比如我们配置当 当前数据大于0时,我们给Text组件展示数据前增加一个向上的红色箭头,当数据小于0时,给数据前增加一个向下的绿色箭头,用户可以配置箭头的颜色。这就引出了我遇到的难点,因为我们在公司的内部使用的是华为的图标库,一般要使用图标的话,都是通过import的方式导入一张base64编码的svg图片,我们该如何去实现将base64格式的svg图片动态变换颜色呢。 后面我通过以下几个步骤去解决了这个问题:

  • 首先我们可以发现svg是由xml代码去绘制实现的,打开一个svg的xml代码可以发现,他的颜色是fill属性填充的,只要修改fill属性的颜色值,就可以实现颜色替换了。
  • 于是,我把base64编码的图片,以字符串'base64'分割成两部分,头部以及图片内容部分。
  • 然后,我将base64编码图片内容部分转换成xml编码,我们使用Buffer.from(data, 'base64').toString('binary')实现转换。
  • 这时候我们得到了一个xml格式的字符串,使用正则匹配,去找到'#开头'格式的内容,这个内容就是决定svg图片颜色的,我们将其替换成新的颜色。
  • 最后将之前得到的头部以及替换后的尾部拼接新的字符串,再转换成新的base64格式的svg图片。
const BASE_64_SIGN = 'base64,'

const base64Atob =  (data: string) => Buffer.from(data, 'base64').toString('binary');

const base64Btoa = (data: string) => Buffer.from(data, 'binary').toString('base64');

function replaceColorForBase64Svg(svgBase64: string, newColor:string):string {
    if(!newColor) {
        return svgBase64;
    }
    const [head, svgBase64Content] = svgBase64.split(BASE_64_SIGN);
    const svgConetent = base64Atob(svgBase64Content);
    let formatColor = newColor;
    if (colorUtils.isHexColor(newColor)) {
        if (newColor.startsWith('#')) {
        formatColor = newColor.tuUpperCase();
       } else {
       formatColor = `#&{newColor.toUpperCase()}`;
       }
}

// 替换掉以#开头的颜色值
let newContent = svgContent.replace(/(.*)(#[a-f\d]{3,8})(.*)/gi, (match, before, foundColor, end) => {
    return colorUtils.isTransparentColor(foundColor) ? match : `${before}${formatColor}${end}`;
});

// 替换掉以rgb开头的颜色值
newContent = newContent.replace(/(.*)(rgba?([\d,\s]{5,}))(.*)/gi, (match, before, foundColor, end) => {
    const hexColor = colorUtils.rgbToHexColor(foundColor);
    return colorUtils.isTransparentColor(hexColor) ? match : `${before}${formatColor}${end}`;
 })
 return `${head}${BASE_64_SIGN}${base64Btoa(newContent)};`

实现一个时间轴组件

首先在Echart中,目前是没单独提供带时间刻度的时间轴组件的,只有在例如柱状图等图表中的x轴和y轴有类似时间轴的功能,但是x轴所带有的时间轴是带有dataZoom缩放功能的,且没法禁用。最终我们通过叠加两个x轴的方式,将第一个x轴绑定dataZoom缩放,且隐藏不展示,第二个x轴作为真正的数据展示,然后再把y轴隐藏即可。关于时间刻度的话,我们是用js动态计算的,比如,我们的需求是做一个展示最近时间范围的时间轴,我们通过js计算出开始时间和结束时间,然后,将开始和结束时间的区间均分成10等份,生成10个刻度值,将刻度值数组赋值给x轴的Data即可。

组件优化问题

比如我们当时实现的时间轴组件他不是单独使用的,他的作用是与其他组件进行联动操作,我们会将时间轴选中的时间范围作为其他组件的过滤条件,带入到请求体中,发送请求到后台,当我们不停的拖动brush去选中某个时间范围时,我们可以从network面板中可以看到,不停的再发送请求,这样会导致http请求过多,导致页面卡顿。于是,我通过实现防抖函数,去降低不停拖动带来的请求过多问题,每次拖动只在结束的时候发送一次请求,页面卡顿明显得到优化。

职业规划是什么?

答:

目前作为一名刚毕业的学生,比较缺乏工作经验,近一两年的职业规划,主要还是集中于技术的提升,比如多看一些技术书籍以及优质的技术博客,多在团队跟同事交流,深入到团队的业务中。如果是3-4年以后的话,我会朝着前端开发领域专家的方向努力,掌握一些高级的框架开发,开始尝试可以独立的领导一个小型的项目开发。如果更长远一步来看的话,8-10年,我规划是能成为前端架构师,能够设计和规划前端系统的整体架构。总之,如果可以的话,我会打算在一家公司,深耕业务,深耕技术,与公司一起进步。

如何去实现大屏屏幕自适应的?

答: 首先这个问题产生的根源是,由于我们搭建的是大屏应用,他的应用场景非常多,可以是很小的pc机,也可以很大的大屏幕,为了良好适配各种屏幕,主要用以下方式去实现适配:

  • 1.第一步,我们首先已知两个属性,设计稿宽高,我们分别把他定义为designDraftWidth和designDraftHeight。顾名思义,他就是设计师给我们出的那个设计稿的宽高。

  • 2.第二步,我们需要去计算出实时屏幕的比例,通过document.documentElement.clientWidth和document.documentElement.clientHeight去计算出一个比例值scale,然后将该比例值去与设计稿的比例值去比较。

    • 如果当前屏幕比例<设计稿比例,那么我们就需要缩放的比例就是屏幕宽度除以设计稿宽度。
    • 如果当前屏幕比例>设计稿比例,那么我们需要缩放的比例就是屏幕高度除以设计稿高度。
  • 3.最后,我们通过window.onresize函数去实现缩放的效果,可以保证适配任何场景。

 const handleScreenAuto = () => {
        const designDraftWidth = 1920;//设计稿的宽度
        const designDraftHeight = 960;//设计稿的高度
        //根据屏幕的变化适配的比例
        const scale = document.documentElement.clientWidth / document.documentElement.clientHeight < designDraftWidth / designDraftHeight ?
            (document.documentElement.clientWidth / designDraftWidth) :
            (document.documentElement.clientHeight / designDraftHeight);
        //缩放比例
        (document.querySelector('#screen') as any).style.transform = `scale(${scale}) translate(-50%)`;
    }