今天我们来画折线图 效果图
以下为模拟数据
[{"time":19,"text":"入 \ n 院 \ n19\n 时 \ n11\n 分","position":42,"cellMin":29.0,"cellSplit":0.2,"type":"text","color":"red","shape":null},{"time":22,"text":"手 \ n 术","position":42,"cellMin":29.0,"cellSplit":0.2,"type":"text","color":"red","shape":null},{"time":129,"text":"手 \ n 术","position":42,"cellMin":29.0,"cellSplit":0.2,"type":"text","color":"red","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":30.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":31.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":32.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":33.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":34.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":35.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":36.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":37.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":38.0,"type":"baseline","color":"#000","shape":null},{"cellMin":28.0,"cellSplit":0.2,"y":39.0,"type":"baseline","color":"red","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":40.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":41.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"y":42.0,"type":"baseline","color":"#000","shape":null},{"cellMin":29.0,"cellSplit":0.2,"array":[{"time":19,"tips":"体温 37.1","value":"37.1","shape":"x","Break":"false","type":"temperature","extraArr":[],"others":[]},{"time":21,"tips":"体温 36.9","value":"36.9","shape":"x","Break":"false","type":"temperature","extraArr":[],"others":[]},{"time":30,"tips":"体温 36.5","value":"36.5","shape":"x","Break":"false","type":"temperature","extraArr":[],"others":[]},{"time":38,"tips":"体温 36.6","value":"36.6","shape":"x","Break":"false","type":"temperature","extraArr":[],"others":[]},{"time":54,"tips":"体温 36.7","value":"36.7","shape":"x","Break":"false","type":"temperature","extraArr":[],"others":[]}],"type":"line","color":"blue","shape":"x-circle"},{"cellMin":-10.0,"cellSplit":2.0,"array":[{"time":19,"shape":"empty-circle","tips":"呼吸 20","value":"20","Break":"false"},{"time":21,"shape":"empty-circle","tips":"呼吸 20","value":"20","Break":"false"},{"time":30,"shape":"empty-circle","tips":"呼吸 19","value":"19","Break":"false"},{"time":38,"shape":"empty-circle","tips":"呼吸 18","value":"18","Break":"false"},{"time":54,"shape":"empty-circle","tips":"呼吸 19","value":"19","Break":"false"}],"type":"line","color":"black","shape":"empty-circle"},{"cellMin":-2.0,"cellSplit":1.0,"array":[{"time":19,"tips":"疼痛 7","value":"7","Break":"false","type":"pain","extraArr":[{"extra":"3","extraColor":"red","extraTips":"疼痛评价 3"}],"others":[]},{"time":23,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[],"others":[]},{"time":27,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[],"others":[]},{"time":33,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[],"others":[]},{"time":39,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[{"extra":"3","extraColor":"red","extraTips":"疼痛评价 3"}],"others":[]},{"time":44,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[],"others":[]},{"time":51,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[],"others":[]},{"time":58,"tips":"疼痛 3","value":"3","Break":"false","type":"pain","extraArr":[{"extra":"3","extraColor":"red","extraTips":"疼痛评价 3"}],"others":[]}],"type":"line","color":"red","shape":"empty-circle"},{"bgColor":"rgba(255,0,0,0.7)","cellMin":30.0,"cellSplit":2.0,"array":[{"time":19,"v1":69,"v1Tips":"心率 69","v2":69,"v2Tips":"脉搏 69","Break":"false"},{"time":21,"v1":70,"v1Tips":"心率 70","v2":70,"v2Tips":"脉搏 70","Break":"false"},{"time":30,"v1":83,"v1Tips":"心率 83","v2":83,"v2Tips":"脉搏 83","Break":"false"},{"time":38,"v1":78,"v1Tips":"心率 78","v2":78,"v2Tips":"脉搏 78","Break":"false"},{"time":54,"v1":77,"v1Tips":"心率 77","v2":77,"v2Tips":"脉搏 77","Break":"false"}],"type":"area","color":"red","shape":null},{"text":null,"y":"28","cellMin":-10.0,"cellSplit":2.0,"array":[],"type":"tag","color":"black","shape":null},{"text":null,"y":null,"cellMin":30.0,"cellSplit":2.0,"array":[],"type":"tag","color":"black","shape":null}]
首先创建 filterData 方法 用于过滤数据 text 文本 line 线段 area 圆 tag 暂时用不到 今天说的是折线所以创建 zrLine 方法
- filterData(){
- const data = chartData
- data.forEach(el => {
- switch (el.type) {
- case "text":
- // this.zrText(el)
- break;
- case "line":
- this.zrLine(el)
- break;
- case "area":
- this.zrPolyline(el)
- break;
- case "tag":
- this.zrTag(el)
- break;
- default:
- break;
- }
- });
- }
我们在新增一个文件夹创建 utli.JS 这个文件夹的作用为我们把创建线创建圆的公共方法写在这个 JS 文件里
utli.JS 我们先说 createLine createCircle
createLine 需要传 5 个参数分别为开始点的横纵坐标 结束点的横纵坐标 还有线的样式
createCircle 需要传 4 个参数分别为 圆点的横纵坐标 圆的半径 和样式
addHover 也需要 这时我们需要在 init 方法里添加一段代码 (上一章创建的初始化方法) 这段代码为创建一个 div 到时我们鼠标移到圆上会弹出文本信息的时候回用到
- var div = document.createElement("div")
- div.classList.add("tips")
- document.getElementById("main").append(div)
- View Code
utli.JS
- // 线段
- export const createLine = (x1,y1,x2,y2,style)=>{
- return new zrender.Line({
- shape:{
- x1:x1,
- y1:y1,
- x2:x2,
- y2:y2
- },
- style:style,
- });
- };
- // cx 横坐标 cy 纵坐标 r 半径 空心圆
- export const createCircle = (cx,cy,r,style)=>{
- return new zrender.Circle({
- shape:{
- cx:cx,
- cy:cy,
- r:r
- },
- style:style,
- zlevel:4
- })
- }
- // 添加 horver 事件 el 元素对象 config 一些配置项 x x 轴坐标 y y 轴坐标 shapeOn 鼠标移入一些属性配置 shapeOn 鼠标移出一些属性配置 shape 配置项看官网
- export const addHover = (el,config,x,y,shapeOn,shapeOut) => {
- const domTips = document.getElementsByClassName("tips")
- el.on('mouseover',function(){
- domTips[0].innerhtml = config.tips
- domTips[0].setAttribute("style",`position:absolute;top:${y-13}px;left:${x}px;display:block;font-size:10px;background-color:rgba(0,0,0,.7);padding:3px;border-radius:3px;color:#fff`)
- el.animateTo({
- shape:shapeOn
- },100,0)
- }).on('mouseout',function () {
- domTips[0].setAttribute("style",`display:none`)
- el.animateTo({
- shape:shapeOut
- },100,0)
- })
- }
- // 多边形
- export const createPolygon = (points,style) => {
- return new zrender.Polyline({
- shape:{
- points:points,
- },
- style:style
- })
- }
zrLine 方法里的第一段代码 判断这个折线拐点是需要空心圆还是实心圆还是其他的形状 都通过 shape 决定 color 为圆的边框颜色填充色为白色 先定义一个 style 变量到时好实现自定义
- var style = {}
- switch (data.shape) {
- case "x-circle":
- style = {
- stroke:data.color,
- fill:"#fff",
- text:"x",
- }
- break;
- case "empty-circle":
- style = {
- stroke:data.color,
- fill:"#fff",
- text:"",
- }
- break;
- default:
- break;
- }
这里需要在添加 2 个方法
getX
- // 获取 X 坐标 data 当前时间点
- getX(data){
- let XShareOne = this.XShareOne()
- return data * XShareOne
- },
- View Code
- transformY
- // 转换 y 轴坐标点为正确坐标点 因为 y 轴坐标是顶点为 0 递增的 所有用总高度减去原来坐标的高度剩下的高度就是正确坐标点
- //i 代表一个格子代表几个高度
- transformY(data,i){
- let YHeight = this.YShareOne()
- // 计算出剩余高度
- let surplusHeight = this.canavsHeight - (YHeight/i) * data
- return surplusHeight
- },
这段代码意思是先把数据遍历出来 在通过 time 属性计算出 x 坐标 value 值计算出 y 坐标 x 轴左边基本是以 time 为基本来计算的 y 轴坐标可能会随数据变化而有所改变 Break 属性为是否断线 如果需要断线就位 true
- data.array.forEach((el,i) =>{
- if (i> 0) {
- let XShareOne = this.XShareOne()
- let firstX = this.getX(data.array[i-1].time)
- let firstY = this.transformY(data.array[i-1].value,1)
- let x = this.getX(data.array[i].time)
- let y = this.transformY(data.array[i].value,1)
- if (data.array[i-1].Break == "false") {
- let line = createLine(firstX,firstY,x,y,{
- stroke:"#af2377",
- lineWidth:2,
- })
- this.zr.add(line)
- }
- }
- if (el.extraArr && el.extraArr.length> 0) {
- el.extraArr.forEach((item,a) => {
- let x = this.getX(el.time)
- let y = this.transformY(el.value,1)
- let lastY = this.transformY(item.extra,1)
- let dottedLine = createLine(x,y,x,lastY,{
- stroke:"#af2377",
- lineWidth:2,
- lineDash:[2,2]
- })
- this.zr.add(dottedLine)
- el.extraArr.forEach((item,a) => {
- let getY = this.transformY(item.extra,1)
- let Circle = createCircle(x,getY,5,{
- stroke:item.extraColor,
- fill:"#fff",
- })
- this.zr.add(Circle)
- addHover(Circle,{
- tips:item.extraTips,
- },x,getY,{
- r:8,
- },{
- r:5,
- })
- })
- })
- }
- let getX = this.getX(el.time)
- let getY = this.transformY(el.value,1)
- let Circle = createCircle(getX,getY,5,style)
- this.zr.add(Circle)
- addHover(Circle,el,getX,getY,{
- r:8,
- },{
- r:5,
- })
- })
这步完成折线图应该就画好了
下次我们讲阴影的画法
来源: https://www.cnblogs.com/hprBlog/p/11770148.html