前端技术分享交流会
主题:前端开发常见问题及数据可视化经验分享
分享者:刘松
日期:2024-06-06
一、开发工具分享
1.Form Generator
form-generator
是基于vue
框架的Element UI
表单设计及代码生成器- 一键生成代码,可以直接放到Vue项目中,提高开发效率
- Form Generator
Gitee仓库地址
链接地址 - vscode配套插件-Form Generator Plugin
form-generator工具的使用
2.浏览器扩展插件vue-devtools
- 用于调试 Vue 应用程序的浏览器扩展
- 快速定位组件位置并自动打开
- 调试数据、事件追踪、性能分析
- 预览vuex仓库数据
vue-devtools调试工具的使用
// 如无法自动定位组件文件,需要添加额外依赖包支持
npm install launch-editor-middleware -Dconst 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.兄弟元素之间的塌陷问题
<divstyle="margin-bottom:30px">层1</div><divstyle="margin-top:20px">层2</div><!--
3种解决方法:
1.只设置层1的margin-bottom值
2.只设置层2的margin-top值
3.在层2那层再包裹一层,设置属性overflow:hidden
-->
2.父子元素之间的塌陷问题
<divclass="box1"><divclass="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><!-- 方案六:标签之间没有空格或换行 --><imgsrc="image1.jpg"><imgsrc="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><divclass="demo-box"><divclass="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可视化案例
- 线形进度条的几种实现方式-CSDN博客
- CSS锥形渐变实现环形进度条-CSDN博客
- CSS实现个性化水球图-CSDN博客
- CSS实现渐变仪表盘的简单尝试-CSDN博客
四、数据可视化地图-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.代码结构
- 封装地图工具类
classCanvasMap{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){}}exportdefault CanvasMap
- 使用方式
// vue组件使用import CanvasMap from"./map.js";mounted(){this.myChart1 =newCanvasMap({el:this.$refs.mapbox1,callBack:(message)=>{ console.log(message)}// 接收地图事件消息});this.myChart1.setOption({tooltip:{},geo:{},itemStyle:{}});}// html使用var myChart1 =newCanvasMap({el: document.getElementById('mapbox1'),callBack:(message)=>{ console.log(message)}// 接收地图事件消息});
myChart1.setOption({tooltip:{},geo:{},itemStyle:{}});// 其它使用方式。。。。。。
使用方式
// vue组件使用import CanvasMap from"./map.js";mounted(){this.myChart1 =newCanvasMap({el:this.$refs.mapbox1,callBack:(message)=>{ console.log(message)}// 接收地图事件消息});this.myChart1.setOption({tooltip:{},geo:{},itemStyle:{}});}// html使用var myChart1 =newCanvasMap({el: document.getElementById('mapbox1'),callBack:(message)=>{ console.log(message)}// 接收地图事件消息});
myChart1.setOption({tooltip:{},geo:{},itemStyle:{}});// 其它使用方式。。。。。。
6.地图可视化案例
- Canvas绘制地图-CSDN博客
版权归原作者 青春~不散 所有, 如有侵权,请联系我们删除。