使用ZRender实现护理单折线图功能

公司医院项目,需要定制化显示病人的体温、脉搏、呼吸。由于界面是定义好的,无法使用开源项目来改,干脆自己画一个了。

为什么是ZRender

ZRender 是百度前端团队用于绘制 EChar t的开源库,里面封装了各种对 Canvas 的使用。而且 ZRender 的文档是全中文的,对开发者也非常友好

需求

相对于其他知识点,绘图没什么特别要讲的。无非是不停的画而已。步骤复杂但是实现起来没有什么技术难点。所以直接写下需求,然后贴上代码供大家参考啦~

  • 绘制表格 —— 计算好格子的宽、高、数量,for 循环绘制多条横线、竖线即可实现。
  • 根据体温、脉搏等数据标注相应位置的点,点有各种形状。 —— 形状ZRender 已经提供,直接调用配置即可。
    • 实心圆
    • 空心圆
    • 实心三角形
    • 虚线
    • 特殊符号 —— 其实都不难,慢慢画都能画出来。
  • 纵向绘制文本 —— 没有发现纵向绘制的方式,于是将文本拆分一个一个字画上去。
  • 鼠标 hover 在各个点上需要有文本框显示具体内容。 —— 绘制一个文本,隐藏起来。当触发 hover 事件的时候显示文本,并将文本移动到相应位置。
  • 线段连接 —— 计算一下两个点的x,y连接即可。虚线只需要配置 style: { lineDash: [ 5, 5 ] } 即可实现虚线效果。
  • 将 ZRender 绘制的表格打印出来 —— 转为图片打印,最后会讲。

贴个效果图:


效果图

实现

由于是公司项目,不发布源码啦~以下是demo代码。

table.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Table</title>
    <script src="zrender.js"></script>
    <style>
        #main {
            height: 600px;
            width: 800px;
        }
    </style>
</head>
<body>
<div id="main"></div>
<img src="" id="main_img">
<script src="DrawUtil.js"></script>
<script>
    var zr = zrender.init(document.getElementById('main'))
    const [height, width] = [15, 15]
    var tableGroup = new zrender.Group()
    for (let i = 0; i <= 30; i++) {
        var line1 = new zrender.Line({
            shape: {
                x1: 0,
                y1: height * i,
                x2: width * 30,
                y2: height * i,
            }
        })
        var line2 = new zrender.Line({
            shape: {
                x1: width * i,
                y1: 0,
                x2: width * i,
                y2: height * 30,
            }
        })
        tableGroup.add(line1)
        tableGroup.add(line2)
    }
    tableGroup.attr('position', [10, 10])
    zr.add(tableGroup)

    DrawUtil.initHoverText(zr)
    zr.add(DrawUtil.drawText('你好,在干嘛呐?', 30, 30))
    zr.add(DrawUtil.drawCircle({x: 50, y: 50, txt: '哈哈'}, '#FAD'))
    zr.add(DrawUtil.drawHollowCircle({x: 100, y: 100, txt: '空心圆'}, '#DAF'))
    zr.add(DrawUtil.drawIsogon({x: 200, y: 200, txt: 'jack'}, '#ADF'))

    setTimeout(toImg, 1000)

    function toImg() {
        console.log('to img')
        var canvas = document.querySelector('#main canvas')
        if (canvas) {
            var img = canvas.toDataURL("image/png")
            document.querySelector('#main_img').src = img
        }
    }
</script>
</body>
</html>

DrawUtil.js

// hover 框文本样式
var Text

var DrawUtil = {
    // 初始化悬浮文本
    initHoverText(zr){
        Text = new zrender.Text({
            style: {
                fontSize: 14,
                textBackgroundColor: '#FFF',
                textBorderColor: '#000',
                textBorderWidth: 1,
                textBorderRadius: 2,
                textPadding: 5,
            },
            zlevel: 100
        })
        zr.add(Text)
        Text.hide()
    },
    // 绘制纵向文本
    drawText (str, dx, dy) {
        let group = new zrender.Group()

        for (var i = 0; i < str.length; i++) {
            var text = new zrender.Text({
                style: {
                    text: str.charAt(i),
                    fontSize: 14,
                    textFill: '#FF4949',
                    textBackgroundColor: '#FFF',
                }
            })
            let y = 14 * i
            text.attr('position', [0, y])
            group.add(text)
        }

        group.attr('position', [dx, dy])
        return group
    },
    // 绘制实心圆
    drawCircle (Obj, Color) {
        return new zrender.Circle({
            shape: {
                cx: Obj.x,
                cy: Obj.y,
                r: 4
            },
            style: {
                fill: Color
            }
        }).on('mouseover', function () {
            Text.show()

            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })
    },
    // 绘制三角形
    drawIsogon (Obj, Color) {
        return new zrender.Isogon({
            shape: {
                x: Obj.x,
                y: Obj.y,
                r: 6,
                n: 3
            },
            style: {
                fill: Color
            }
        }).on('mouseover', function () {
            Text.show()

            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })
    },
    // 绘制空心圆
    drawHollowCircle (Obj, Color) {
        return new zrender.Circle({
            shape: {
                cx: Obj.x,
                cy: Obj.y,
                r: 4
            },
            style: {
                fill: '#FFFFFF',
                stroke: Color
            }
        }).on('mouseover', function () {
            Text.show()

            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })
    },
    // 绘制×
    drawX (Obj, Color) {
        return new zrender.Text({
            style: {
                text: '×',
                fontSize: 20,
                textFill: Color,
            },
            position: [Obj.x - 7, Obj.y - 11]
        }).on('mouseover', function () {
            Text.show()

            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })
    },
    // 绘制圆圈中有点的圆
    drawPointCircle (Obj, Color) {
        var group = new zrender.Group()
        var Point = new zrender.Circle({
            shape: {
                cx: 4,
                cy: 4,
                r: 1
            },
            style: {
                fill: Color
            }
        })
        var OutCircle = new zrender.Circle({
            shape: {
                cx: 4,
                cy: 4,
                r: 4
            },
            style: {
                fill: '#FFFFFF',
                stroke: Color
            }
        })
        group.on('mouseover', function () {
            Text.show()

            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })

        group.add(OutCircle)
        group.add(Point)
        group.attr('position', [Obj.x - 3, Obj.y - 3])

        return group
    },
    // 绘制圆圈中有H的圆
    drawHCircle (Obj, Color) {
        var group = new zrender.Group()
        var h = new zrender.Text({
            style: {
                text: 'H',
                fontSize: 8,
                textFill: Color
            },
            position: [2, -1]
        })
        var OutCircle = new zrender.Circle({
            shape: {
                cx: 5,
                cy: 5,
                r: 5
            },
            style: {
                fill: '#FFFFFF',
                stroke: Color
            }
        })
        group.on('mouseover', function () {
            Text.show()
            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })

        group.add(OutCircle)
        group.add(h)
        group.attr('position', [Obj.x - 4, Obj.y - 4])

        return group
    },
    // 绘制圆圈中有加号的圆
    drawAddCircle (Obj, Color) {
        var group = new zrender.Group()
        var h = new zrender.Text({
            style: {
                text: '+',
                fontSize: 8,
                textFill: Color
            },
            position: [2, -1]
        })
        var OutCircle = new zrender.Circle({
            shape: {
                cx: 5,
                cy: 5,
                r: 5
            },
            style: {
                fill: '#FFFFFF',
                stroke: Color
            }
        })
        group.on('mouseover', function () {
            Text.show()
            Text.attr('position', [Obj.x, Obj.y])
            Text.attr({
                style: {
                    text: Obj.txt
                }
            })
        }).on('mouseout', function () {
            Text.hide()
        })

        group.add(OutCircle)
        group.add(h)
        group.attr('position', [Obj.x - 4, Obj.y - 4])

        return group
    },
}

最后,需要将Canvas打印出来。我的解决方案是将Canvas转为图片。之后将图片放到你想放的地方即可。

    setTimeout(toImg, 1000)

    function toImg() {
        var canvas = document.querySelector('#main canvas')
        if (canvas) {
            var img = canvas.toDataURL("image/png")
            document.querySelector('#main_img').src = img
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,966评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,170评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,909评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,959评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,851评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,583评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,956评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,590评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,878评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,892评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,719评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,501评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,957评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,124评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,440评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,003评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,211评论 2 339

推荐阅读更多精彩内容