用zrender制作一个基础的绘图板,绘图板可用于组态界面的基础性开发

zrender制作一个基础的绘图板,绘图板可用于组态界面的基础性开发,本实基于vue基础开发,可用于vue项目组态界面的参考。
zrender开发文档地址:https://ecomfe.github.io/zrender-doc/public/api.html

zrender库的安装:npm install zrender

import zrender from 'zrender'

//绘图板
class DrawingBoard {
    //绘图板容器的id
    constructor(id) {
        this.zr = zrender.init(document.getElementById(id));
    }

    init() {
        sessionStorage.setItem('operate', 'move');//默认绘制圆形
        this.draw('circle');
        this.draw('line');
    }

    //绘制的形状及参数配置,此处以圆的绘制为例
    draw(shape, option) {
        switch (shape) {
            case 'circle':
                new Circle(this.zr, option);
                break;
            case 'line':
                new Line(this.zr, option);
                break;
            default:
                break;
        }
    }
}

//圆的绘制
class Circle {
    constructor(zr, option) {
        if (option == undefined) {
            option = {
                borderColor: 'red',
                fillColor: 'orange'
            }
        }
        this.option = option;
        this.zr = zr;
        this.group = new zrender.Group();//用于存放所有圆
        this.position = [];//圆心位置
        this.movePosition = this.position;//鼠标移动的位置
        this.r = 1;//半径
        this.result = null;//绘制的结果
        this.zr.on('mousedown', e => {
            let id = '';
            if (e.target != undefined) {
                id = e.target.id;
            }
            switch (sessionStorage.getItem('operate')) {
                case "circle":
                    this.position.length == 0 ? this.start(e) : this.end();
                    break;
                case "delete":
                    this.delete(id);
                    break;
                default:
                    this.end();
                    break;
            }
        })
        this.zr.on('mousemove', e => {
            this.move(e)
        })
    }

    //点击绘图板获得圆心坐标
    start(e) {
        if (this.position.length == 0) {
            this.position = [parseInt(e.offsetX), parseInt(e.offsetY)]
        }
    }

    //鼠标移动时计算圆的半径并刷新绘制的图形
    move(e) {
        if (this.position.length != 0) {
            this.movePosition = [parseInt(e.offsetX), parseInt(e.offsetY)]
            this.r = zrender.vector.distance(this.position, this.movePosition)
            this.draw()
        }
    }

    //鼠标中键滚动时结束图形绘制
    end() {
        this.position = []
        this.result = null
    }

    //图形绘制及刷新方法
    draw() {
        if (this.result == null) {
            this.result = new zrender.Circle({
                shape: {
                    cx: this.position[0],
                    cy: this.position[1],
                    r: this.r
                },
                draggable: true,
                style: {
                    fill: this.option.fillColor,
                    stroke: this.option.borderColor,
                    opacity: 0.6
                }
            });
            this.result.on('click', function (e) {
                window.console.log(e);
            })
            this.group.add(this.result)
            this.zr.add(this.group)
        } else {
            this.result.attr({shape: {r: this.r}})//修改对象关键代码
            this.zr.refresh();
        }
    }

    //删除一个图形对象
    delete(id) {
        let group = this.group.children();
        group.forEach(elm => {
            if (elm.id == id) {
                this.group.remove(elm);
            }
        })
    }
}

//线的绘制
class Line {
    constructor(zr, option) {
        if (option == undefined) {
            option = {
                borderColor: 'red',
                fillColor: 'orange'
            }
        }
        this.option = option;
        this.zr = zr;
        this.group = new zrender.Group();//用于存放所有线
        this.movePosition = this.position;//鼠标移动的位置
        this.points = [];//绘制线的点集合
        this.result = null;//绘制的结果

        // 事件名称,支持: 'click'、 'mousedown'、 'mouseup'、 'mousewheel'、 'dblclick'、 'contextmenu'。
        this.zr.on('mousedown', e => {
            let id = '';
            if (e.target != undefined) {
                id = e.target.id;
            }
            switch (sessionStorage.getItem('operate')) {
                case "line":
                    this.start(e);
                    break;
                case "delete":
                    this.delete(id);
                    break;
                default:
                    this.end();
                    break;
            }
        })
        this.zr.on('mousemove', e => {
            this.move(e)
        })
        this.zr.on('dblclick', () => {
            this.end()
        })
    }

    //点击绘图板获得坐标
    start(e) {
        this.points.push([parseInt(e.offsetX), parseInt(e.offsetY)]);
        if (this.points.length == 1) {
            this.points.push([parseInt(e.offsetX), parseInt(e.offsetY)]);
        }
    }

    //鼠标移动时刷新绘制的图形
    move(e) {
        if (this.points.length != 0) {
            this.movePosition = [parseInt(e.offsetX), parseInt(e.offsetY)];
            this.points[this.points.length - 1][0] = this.movePosition[0];
            this.points[this.points.length - 1][1] = this.movePosition[1];
            this.draw()
        }
    }

    //结束图形绘制
    end() {
        this.points = []
        this.result = null
    }

    //绘制及刷新方法
    draw() {
        if (this.result == null) {
            this.result = new zrender.Polyline({
                shape: {
                    points: this.points
                },
                draggable: true,
                style: {
                    // fill: this.option.fillColor,
                    stroke: this.option.borderColor,
                    opacity: 0.6
                }
            });
            this.result.on('click', function (e) {
                window.console.log(e);
            })
            this.group.add(this.result)
            this.zr.add(this.group)
        } else {
            this.result.attr({shape: {points: this.points}})//修改对象关键代码
            this.zr.refresh();
        }
    }

    //删除一个对象
    delete(id) {
        let group = this.group.children();
        group.forEach(elm => {
            if (elm.id == id) {
                this.group.remove(elm);
            }
        })
    }
}


export const canvas = function (id) {
    return new DrawingBoard(id);
}

页面调用,vue项目调用时最好在mounted钩子中进行调用,因为绘图板必须要dom元素绘制完成,下面是调用代码:

<template>
    <div class="hello">
        <ul class="tool">
            <li @click="operate('move')" :class="operateType=='move'?'selected':''">移动</li>
            <li @click="operate('line')" :class="operateType=='line'?'selected':''">线</li>
            <li @click="operate('circle')" :class="operateType=='circle'?'selected':''">圆</li>
            <li @click="operate('delete')" :class="operateType=='delete'?'selected':''">删除</li>
        </ul>
        <div id="main">
        </div>
    </div>
</template>

<script>
    import {canvas} from '../units/draw'

    export default {
        name: 'HelloWorld',
        data() {
            return {
                operateType: 'move'
            }
        },
        created() {

        },
        methods: {
            operate: function (operateType) {
                this.operateType=operateType
                sessionStorage.setItem('operate', operateType);
            }
        },
        mounted() {
            canvas('main').init();
        }
    }
</script>

<style scoped>
    #main {
        width: 100%;
        height: 400px;
        border: 2px solid olive;
        box-shadow: 5px 5px 10px #f5f5f5;
        margin: 10px auto;
    }

    .tool {
        display: block;
        list-style: none;
        overflow: hidden;
        margin: 0;
    }

    .tool li {
        float: left;
        width: 40px;
        cursor: pointer;
    }

    .tool .selected {
        background: #2c3e50;
        color: #FFFFFF;
    }
</style>

draw.js库中为方便文章书写圆与直线类放到了一起,实际项目中可各自单独写js文件存放管理。扩展的图形添加新类进行管理即可。本文由作者原创,仅供项目参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值