前端开发常见问题及数据可视化经验分享

前端技术分享交流会

主题:前端开发常见问题及数据可视化经验分享

分享者:刘松

日期:2024-06-06


一、开发工具分享

1.Form Generator

  • form-generator是基于vue框架的Element UI表单设计及代码生成器
  • 一键生成代码,可以直接放到Vue项目中,提高开发效率
  • Form Generator Gitee仓库地址 链接地址
  • vscode配套插件-Form Generator Plugin

Form Generator

form-generator工具的使用

2.浏览器扩展插件vue-devtools

  • 用于调试 Vue 应用程序的浏览器扩展
  • 快速定位组件位置并自动打开
  • 调试数据、事件追踪、性能分析
  • 预览vuex仓库数据

vue-devtools调试工具的使用

// 如无法自动定位组件文件,需要添加额外依赖包支持
npm install launch-editor-middleware -D

const openInEditor = require('launch-editor-middleware');

module.exports = {
  devServer: {
    before (app) {
      app.use('/__open-in-editor', openInEditor('code'));
    }
  }
}

二、页面开发技巧

1.样式重置

每个浏览器都有一套自己的默认样式,使用CSS来重置浏览器的默认样式时,你将能够确保你的网页在所有浏览器中看起来更加一致

  • 使用通配符(简单粗暴,迅速实现,但影响网页性能)
* {
    margin: 0;
    padding: 0;
    border:0;
}
  • 自定义样式重置表
html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a,abbr,acronym, address, big, cite, code,del, dfn, em, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td,article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary,time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
}
  • 使用normalize.css(推荐使用)

2.html高度问题

  • 块级元素不设置宽高时,宽度默认是全屏宽度,高度是由子元素撑起来
  • 元素高度值为百分比时,需要向上遍历父标签要找到一个定值高度才能起作用,如果中途有个height为auto或是没有设置height属性,则高度百分比不起作用
  • 针对大屏页面或需要全屏展示的页面,需要设置html和body的高度
html, body {
    height: 100%;
}

3.margin系列问题

  • margin百分比问题
/*
	1.普通元素的百分比margin都是相对于容器宽度计算的;
	2.绝对定位的百分比margin是相对于第一个定位祖先元素(relative/absolute/fixed)的宽度计算的;
*/
.container {
    margin-left: 10%;
    margin-top: 10%;	/* 慎用 */
    padding-top: 10%;
    padding-left: 10%;	/* 慎用 */
}
  • margin塌陷问题

1.兄弟元素之间的塌陷问题

<div style="margin-bottom:30px">层1</div>
<div style="margin-top:20px">层2</div>
<!-- 
	3种解决方法:
	1.只设置层1的margin-bottom值
	2.只设置层2的margin-top值
	3.在层2那层再包裹一层,设置属性overflow:hidden
-->

在这里插入图片描述

2.父子元素之间的塌陷问题

<div class="box1">
	<div class="box2" style="margin-top: 50px">
</div>
<!-- 
	6种解决方法:
	1.给父元素添加一个透明边框;
	2.给父元素添加一个overflow: hidden
	3.给父元素添加一个position: fixed
	4.给父元素添加一个display: table
	5.将子元素的margin改为父元素的padding
	6.给子元素添加一个兄弟元素属性为content:"";overflow: hidden
-->

4.inline、inline-block元素间隙

  • img 和 iframe 等使用display为inline-block或inline布局的元素

  • 元素标签之间的不可见符号会被保留父层字体的1/3大小的空间
    在这里插入图片描述

  • 六种解决方法

<style>
    img, iframe {
        display: block; 	/* 方案一:将图片转换为块级别元素 */
    }
    img, iframe {
        vertical-align: bottom;	 /* 方案二:设置图片对齐方式 */
    }
    img, iframe {
      margin-bottom: -4px;	/* 方案三:使用负边距离 */
    }
    .parent-box {
        font-size: 0;	/* 方案四:父级盒子设置font-size: 0, 子元素需要重置font-size */
    }
    .parent-box {
        display: flex;	/* 方案五:父级盒子使用flex布局 */
    }
</style>
<!-- 方案六:标签之间没有空格或换行 -->
<img src="image1.jpg"><img src="image2.jpg">

5.CSS属性书写顺序

  • 减少浏览器reflow(回流),提升浏览器渲染dom的性能
  • 提高代码的可读性和可维护性
    在这里插入图片描述
/* 
	css书写顺序规范
	1. 位置属性(position, top, right, z-index,display, float等)
    2. 大小(width, height, padding, margin)
    3. 文字系列(font, line-height, letter-spacing, color-text-align等)
    4. 背景(background, border等)
    5. 其他(animation, transition,transform等)
*/
{
    display: block;
    position: relative;
    float: left;
    width: 100px;
    height: 100px;
    margin: 0 10px;
    padding: 20px 0;
    font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
    color: #333;
    background: rgba(0,0,0,.5);
    border-radius: 10px;
    transition: transform 0.5s linear;
 } 

6.hover伪类替代mouseover

  • :hover是一个样式伪类,而mouseover是一个JavaScript事件
  • :hover伪类用于选择鼠标悬停在元素上方的元素
  • 使用:hover伪类的好处是,它不需要JavaScript就能提供视觉效果,并且可以利用CSS的过渡和动画功能
<style>
    .demo-box {
        position: relative;
        left: 0;
        top: -80px;
        transition: transform 0.5s linear;
        /* ...... */
    }
    .demo-content {
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background-color: skyblue;
    }
    .demo-box:hover {
        transform: translateY(80px);
    }
    .demo-box:hover .demo-content {
        background-color: orange;
    }
</style>
<div class="demo-box">
    <div class="demo-content"></div>
</div>

在这里插入图片描述

  • 结合:hover伪类实现一个简单的html+css三级菜单效果
    在这里插入图片描述

三、数据可视化-CSS

1.数据可视化常用的CSS属性

  • box-shadow
/* 
	h-shadow:水平阴影位移,大于0时阴影右移,小于0时阴影左移;
    v-shadow:垂直阴影位移,大于0时阴影下移,小于0是阴影上移;
    blur:可选参数,阴影模糊半径,值越大颜色越淡,阴影越模糊,为正值,默认为0;
    spread:可选参数,阴影扩散半径,值越大阴影面积越大,可正可负,默认为0;
    color:可选参数,阴影颜色,默认为黑色;
    inset:可选参数,内阴影,一般放在开头或末尾
*/
box-shadow: (inset) h-shadow v-shadow blur spread color inset;

在这里插入图片描述

  • linear-gradient、radial-gradient、conic-gradient
/* 线性渐变 */
background-image: linear-gradient([渐变的方向或角度,] 颜色1 [位置1], 颜色2 [位置2], ...);
background-image: linear-gradient(to right, blue, green 40%, red);
/* 径向渐变 */
background-image: radial-gradient([形状] [大小] [at 中心位置,] 颜色1 [位置1], 颜色2 [位置2], ...);
background-image: radial-gradient(circle closest-side at 50% 50%, red 5%, green 15%);
/* 角向渐变 */
background-image: conic-gradient([起始角度] [at 中心位置,] 颜色1 [位置1],  颜色2 [位置2], ...);
background-image: conic-gradient(from 90deg at 50% 50%, red, yellow, green);

在这里插入图片描述

  • mask

mask 属性允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。

mask 属性主要基于遮罩图像进行操作,通过将遮罩图像应用于元素的内容部分来达到蒙版效果。遮罩图像可以是一张图片、一个渐变或者一个 SVG 矢量图形,即可应用于 CSS background 的属性值。

mask: url(mask.png);                       	/* 使用位图来做遮罩 */
mask: url(masks.svg#star);                 	/* 使用 SVG 图形中的形状来做遮罩 */
mask: linear-gradient(transparent, #fff); 	/* 渐变背景,这里的#fff换成任意颜色均可 */
/* 以下案例是使用渐变+蒙版遮罩实现简单的圆环进度条 */
.ring-chart {
  width: 200px;
  height: 200px;
  background: conic-gradient(transparent 0%, #2ec4a7 100%);
  /* 此写法圆环边缘有锯齿 */
  mask: radial-gradient(closest-side circle, transparent 50%, #000 50% 100%, transparent 100%);
}
/* 边缘锯齿优化,这里的#000可以替换成任意非透明颜色,不影响使用效果 */
mask: radial-gradient(closest-side circle, transparent 50%, #000 51% 99%, transparent 100%);

在这里插入图片描述

  • clip-path

clip-path 是一个css属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐藏。通过定义这个剪切路径(clipping path),您可以创造出非矩形的裁剪形状,使元素内容按特定的几何形状展示

CSS3剪切路径(clip-path)在线生成器

clip-path: <clip-source> | [ <basic-shape> || <geometry-box> ] | none
/* 以下案例为使用clip-path实现图形裁剪 */
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);  /* 裁剪三角形 */
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); /* 裁剪菱形 */
/* 裁剪五角星 */
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); 

在这里插入图片描述

  • transform
/* 水平移动 */
transform: translate(200px, 100px);
/* 扩大缩小 */
transform: scale(1.5);
/* 旋转 */
transform: rotate(45deg);
/* 倾斜变形 */
transform: skew(30deg);

在这里插入图片描述

  • transition

允许元素从一种样式状态平滑地改变为另一种样式状态。这种变化通常会在一段时间内完成,而不是立即生效。

transition可以应用于大多数CSS属性,包括但不限于颜色、尺寸、位置等

.chart-pointer {
  transform: var(--pointer-rotate);
  transition: transform 1s linear;
}

在这里插入图片描述

  • animation

使元素从一种样式逐渐变化为另一种样式的效果

animation: move 1s infinite 动画的第一部分,用于描述动画的各个规则;

@keyframes move {} 动画的第二部分,用于指定动画开始、结束以及中间点样式的关键帧;

在这里插入图片描述

2.案例剖析及讲解

/* 序号1 */
border-radius: 50%;
background-color: #fbedea;
background-image: conic-gradient(#d5f4ee 0%, #2ec4a7 88.88%, transparent 88.88%);
/*  序号2	  mask和background-color认选其一即可*/
background-color: #fff;
mask: radial-gradient(closest-side at center center, transparent 90%, #fff 90%);
border-radius: 50%
/* 序号3 */
transform-origin: center center;
transform: rotate(320deg);
/* 序号6-7 */
transform-origin: center center;
transform:rotateY(180deg)

在这里插入图片描述

3.CSS可视化案例

四、数据可视化地图-Canvas

在这里插入图片描述

1.绘制地图涉及Canvas的api

  • 填充和描边
ctx.fillStyle = '#000'		 	// 填充样式。默认值是#000000纯黑色。
ctx.fill()					   	// 填充。
ctx.lineWidth = 2				// 描边线条粗细
ctx.strokeStyle = '#000'		// 描边样式。默认值是#000000纯黑色。
ctx.stroke()				   	// 描边。
  • 绘制路径
// 绘制多边形
ctx.beginPath()			// 开始一个新路径。
ctx.moveTo(0, 0); 		// 把画笔移动到指定的坐标
ctx.lineTo(10, 50);  	// 绘制一条从当前位置到指定坐标(10, 50)的直线
ctx.lineTo(70, 25); 	// 继续从(10, 50)位置绘制到(70, 25)位置
ctx.closePath()		    // 闭合一个路径。
  • 绘制文字
// 设置文本颜色
ctx.fillStyle = '#000'
// 设置文字像素,及字体
ctx.font = "100px Microsoft YaHei"
// 填充文字(绘制的文字内容,开始绘制的x坐标,开始绘制的y坐标)
ctx.fillText('河南省', 200, 200)
// 文字描边(绘制的文字内容,开始绘制的x坐标,开始绘制的y坐标)
ctx.strokeText("河南省", 10, 90)
// 设置文字对齐的方式可选 start(默认),end,left,right,center
ctx.textAlign = 'center'
// 设置文字对准基线的方式 值包括:top,hanging,middle, alphabetic,ideographic,bottom
ctx.textBaseline = 'top'
// 设置文字的放方向 值包括:ltr, rtl, inherit
ctx.direction = 'rtl'
  • 变换及状态管理
// 重新映射画布上的 (0, 0) 位置,此时所有坐标点都是以此为基准
ctx.translate(50, 50)

// 使用rotate、scale、translate、transform的地方务必在使用前先save(),使用结束务必restore()
ctx.save()		// 存储当前Canvas的状态。
ctx.restore()	// 恢复Canvas到前一次存储的状态。
  • 位置检测
/*
	因为Canvas整体相当于一张图片,鼠标事件并不像操作dom那么简单
	所以,鼠标交互操作一定会涉及到重绘
	先获取鼠标位置,然后重新绘制图形元素,判断鼠标位置是否位于图形元素上
*/
ctx.isPointInPath(mouseX, mouseY)		//当前点是否在指定路径内。
ctx.isPointInStroke(mouseX, mouseY)	//当前点是否在指定路径描边上。

2.地图资源及服务获取方式

DataV.GeoAtlas地理小工具系列 (aliyun.com)

GeoJSON专题 - ECharts图表集,ECharts demo集,echarts gallery社区,Make A Pie,分享你的可视化作品isqqw.com

免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合__HashTang (hxkj.vip)

3.基础知识了解

  • GeoJSON地图数据经纬度坐标自左至右依次递增,自上至下依次递减

  • Canvas默认坐标系为窗口坐标系,自左至右依次递增、自上至下依次递增
    在这里插入图片描述

  • GeoJSON地图数据格式,注意“MultiPolygon”与“Polygon”数据格式

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "adcode": 110000,		  	 // 行政区域编码
                "name": "北京市",			  // 行政区域名称
                "center": [					// 中心点经纬度
                    116.405285,
                    39.904989
                ],
                "level": "province",		// 层级
                "parent": {					// 父级行政区域编码
                    "adcode": 100000
                }
            },
            "geometry": {
                "type": "MultiPolygon",		// 经纬度数据集类型
                "coordinates": [			// 经纬度坐标集合
                    [
                        [
                            [
                                117.348611,
                                40.581141
                            ],
                           ......
                        ], 
                        [
                            [
                                117.348611,
                                40.581141
                            ],
                           ......
                        ]
                    ]
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "adcode": 150000,
                "name": "内蒙古自治区",
                "center": [
                    111.670801,
                    40.818311
                ],
                "level": "province",
                "parent": {
                    "adcode": 100000
                }
            },
            "geometry": {
                "type": "Polygon",		// 比MultiPolygon少一层,需特殊处理
                "coordinates": [
                    [
                        [
                            97.172903,
                            42.795257
                        ],
                        [
                            97.371235,
                            42.457076
                        ]
                        ......
                    ]
                ]
            }
        }
    ]
}

4.实现思路

  • 页面元素初始化(画布、提示信息、元素样式等)

  • 个性化配置项的处理(借鉴echarts的配置化方式)

  • 抓取GeoJSON格式的地图数据

  • 解析地图数据,计算包围盒、确定中心点坐标,计算地图缩放系数

  • 遍历地图数据,经纬度坐标转换屏幕坐标,结合绘图api将坐标映射到画布上

  • 各类鼠标事件的添加及响应(点击下钻,滚轮缩放、悬浮区域高亮,悬浮信息展示等)

在这里插入图片描述

5.代码结构

  • 封装地图工具类
class CanvasMap {
    constructor(options) {}
    // 初始化dom节点-创建画图和提示信息
    initDomElement(el) {}
    // 初始化各类鼠标事件
    initMouseEvent() {}
    // 默认配置参数
    defaultConfig() {}
    // 设置个性化地图参数,将传入配置和默认配置进行合并
    setOption(options) {}
    // 抓取地图GeoJSON格式数据
    getGeoAreas() {}
    // 计算包围盒,确定中心点坐标,计算地图缩放系数
    getBoxArea() {}
    // 清空画布、设置背景、绘制地图区域、标注名称
    drawMap() {}
    // 绘制地图各子区域
    drawArea() {}
    // 标注地图上的城市名称
    drawText() {}
    // 将经纬度坐标转换为屏幕坐标
    toScreenPosition(horizontal, vertical) {}
    // 窗口大小发生变化时重绘地图方法
    resize() {}
    // 鼠标悬浮提示信息
    showHoverTip() {}
    // 深拷贝
    deepCopy(result, obj) {}
    // 批量设置样式
    setStyle(obj, sty) {}
}
export default CanvasMap
  • 使用方式
// vue组件使用
import CanvasMap from "./map.js";
mounted() {
    this.myChart1 = new CanvasMap({
        el: this.$refs.mapbox1,
        callBack: (message) => { console.log(message) }	 // 接收地图事件消息
    });
    this.myChart1.setOption({tooltip:{}, geo: {}, itemStyle: {}});
}
// html使用
var myChart1 = new CanvasMap({
    el: document.getElementById('mapbox1'),
    callBack: (message) => { console.log(message) }	 // 接收地图事件消息
});
myChart1.setOption({tooltip:{}, geo: {}, itemStyle: {}});

// 其它使用方式。。。。。。

使用方式

// vue组件使用
import CanvasMap from "./map.js";
mounted() {
    this.myChart1 = new CanvasMap({
        el: this.$refs.mapbox1,
        callBack: (message) => { console.log(message) }	 // 接收地图事件消息
    });
    this.myChart1.setOption({tooltip:{}, geo: {}, itemStyle: {}});
}
// html使用
var myChart1 = new CanvasMap({
    el: document.getElementById('mapbox1'),
    callBack: (message) => { console.log(message) }	 // 接收地图事件消息
});
myChart1.setOption({tooltip:{}, geo: {}, itemStyle: {}});

// 其它使用方式。。。。。。

6.地图可视化案例

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值