迅速建立 HTML5 Canvas 电信互联网拓扑图的示例编码

日期:2021-01-19 类型:科技新闻 

关键词:微信小程序页面设计,python小程序,小程序首页模板,如何建立微信小程序,怎么做微信小程序

序言

特性目录想必大伙儿都不容易生疏,一切正常用 HTML5 来做的特性目录大约便是用往下拉菜单之类的,并且许多状况下,往下拉目录还不足漂亮,如何办?我试着用 HT for Web 来完成特性栏点一下按钮弹出智能选框,对传入的数据信息开展挑选的作用,觉得总体实践活动起来還是较为简易便捷的,因此在这边跟大伙儿共享1下。

实际效果图

http://www.hightopo.com/demo/propertyEditor/index.html

编码完成

拓扑图

从上面的实际效果图中大家能够看到,全部网页页面分成 3 个一部分,左侧的 graphView 拓扑图一部分,右下角的 tableView 报表一部分,和右上角的 propertyView 特性一部分。大家先把全部情景区划出来,随后再向各个一部分来加上实际的內容:

gv = new ht.graph.GraphView();
var tablePane = new ht.widget.TablePane(gv.dm());//报表面板组件
propertyView = new ht.widget.PropertyView(gv.dm());//formPane是在propertyView里的,因此要先界定

var rightView = new ht.widget.SplitView(propertyView, tablePane, 'v', 0.4);//切分组件,v分成左右层,占比为0.4:0.6
rightView.getView().style.borderLeft = '1px solid #000';
var borderPane = new ht.widget.BorderPane();//边框面板组件
borderPane.setRightView(rightView, 400);//设定 borderPane 右侧组件为 rightView,宽度为400
borderPane.setCenterView(gv);//设定 borderPane 正中间组件为 gv 
borderPane.addToDOM();//将 borderPane 组件加上进 body 中

上面编码中 new 出来的一部分全是 HT 封裝好的组件,非常于“类”,这里解释1下 SplitView 切分组件,切分组件用于上下或左右切分两个子组件, 子组件可为 HT 架构出示的组件,也可为 HTML 的原生态组件,子组件以 position 为 absolute 方法开展肯定精准定位,这个组件中的主要参数各自为(左组件或上组件, 右组件或下组件,h 表明上下切分 v 表明左右切分,切分部位默认设置值为 0.5,假如设定值为 0~1 则按百分比切分,超过 1 意味着左组件或上组件的肯定宽或高,小于 1 意味着右组件或下组件的肯定宽或高);也有 BorderPane 面板组件为合理布局器皿,可在上、下、左、右、中的5个地区部位放置子组件, 子组件可为 HT 架构出示的组件,也可为 HTML 原生态组件,子组件以 position 为 absolute 方法开展肯定精准定位。这里我融合了 SplitView 和 BorderPane 将情景分为了3个一部分。最终记得1定要将最后的合理布局器皿加上进 body 中或随意1个 HTML 标识中,这样才可以在页面上显示信息,在其中 addToDOM 的界定內容以下:

addToDOM = function(){   
    var self = this,
        view = self.getView(), //获得这个组件的最底层 div 
        style = view.style;//获得最底层 div 的款式 style 特性
    document.body.appendChild(view); //将最底层 div 加上进 body 中
    style.left = '0';//HT 默认设置将组件都界定为决策精准定位 absolute,因此必须设定部位
    style.right = '0';
    style.top = '0';
    style.bottom = '0';      
    window.addEventListener('resize', function () { self.iv(); }, false);            
}

HT 的组件1般都会嵌入 BorderPane、SplitView 和 TabView 等器皿中应用,而最外层的 HT 组件则必须客户手工制作将 getView() 回到的最底层 div 元素加上到网页页面的 DOM 元素中,这里必须留意的是,当父器皿尺寸转变时,假如父器皿是 BorderPane 和 SplitView 等这些 HT 预订义的器皿组件,则 HT 的器皿会全自动递归启用孩子组件 invalidate 涵数通告升级。但假如父器皿是原生态的 html 元素, 则 HT 组件没法得知必须升级,因而最外层的 HT 组件1般必须监视 window 的对话框尺寸转变恶性事件,启用最外层组件 invalidate 涵数开展升级。

情景建立结束。以便显示信息不一样连接点对应的特性的不一样,大家在拓扑图上加上了7个连接点:

function initModel(){
    var name = "机器设备";
    var count = 0;
    var root = createNode(name + count++, name + (++count));//主要参数1为name,主要参数2为tag
    root.setImage('./symbols/主机房/服务器.json');
    root.setName('服务器');
    root.s('label.position', 3);
    gv.sm().ss(root);//默认设置选定root连接点

    for (var i = 0; i < 2; i++) {
        var iNode = createNode(name + count++, name + (++count));//主要参数1为name,主要参数2为tag
        createEdge(root, iNode);
        for (var j = 0; j < 2; j++) {
            var jNode = createNode(name + count++, name + (++count));
            createEdge(iNode, jNode);
        }
    }
}

createNode 涵数的申明以下:

function createNode(name, tag){//建立Node连接点
    flag++;
    var node = new ht.Node();
    node.setName(name);
    node.setTag(tag);
    node.setImage('./symbols/主机房/XX分系统软件.json');
    node.a('hidden', false);//自定特性,能够操纵node.a('hidden')来操纵连接点显隐

    node.a('插口种类', 'SATA');
    node.a('显卡', 'Nvidia');
    if(flag % 2 === 0){
        node.a('插口种类', 'IDE');
        node.a('显卡', 'ATI');
    }
    node.s('label.position', 11);
    gv.dm().add(node);//将连接点加上进数据信息器皿DataModel中

    node.tablePane1 = createTableView(serviceType, dataModel1);//建立报表面板
    node.tablePane2 = createTableView(serviceSize, dataModel2);
    node.tablePane3 = createTableView(version, dataModel3);

    node.formPane1 = createFormPane(node.tablePane1);//建立表单面板
    node.formPane1.title = '种类';//以便给后边dialog会话框的题目做提前准备
    node.formPane2 = createFormPane(node.tablePane2);
    node.formPane2.title = '运行内存';
    node.formPane3 = createFormPane(node.tablePane3);
    node.formPane3.title = '型号规格';

    if(flag % 3 === 0){
        node.formPane3.v('tag', '想到(Lenovo)服务器X3650M5 8871');
    }else{
        node.formPane3.v('tag', 'Lenovo IBM X3250 5458I21');
    }
    node.a('型号规格', node.formPane3.v('tag'));
    return node;
}

大家根据操纵这个连接点的 hidden 特性,运用 graphView 中的可视性过虑器 setVisibleFunc 涵数来操纵连接点的显隐:

gv.setVisibleFunc(function(data){
    if(data.a('hidden')){
        return false;
    }
    return true;
});

特性面板

有了连接点当然就必须显示信息特性了,再加下面的 tablePane 报表面板中的值,1共加上了7种特性:

function createProperty(){//建立特性
    propertyView.addProperties([
        {
            name: 'name',//获得 name 特性,融合 accessType 特性最后完成对连接点特性的存储,accessType 默认设置值为 null,如name为age,选用getAge()和setAge(98)的get/set或is/set方法存储(这边name为name,因此根据 getName() 获得)
            displayName: '名字'//设定特性名的显示信息文字值
        },
        {
            name: 'hidden',//获得 hidden 特性
            displayName: '掩藏这个连接点',
            accessType: 'attr',//如name为hidden,选用getAttr('hidden')和setAttr('hidden', false)的方法存储
            icon: 'images/alert.gif',//设定特性名左边显示信息的标志
            valueType: 'boolean',//用于提醒组件出示适合的renderer3D渲染 布尔运算种类,显示信息为勾选框
            editable: true//设定该特性是不是可编写
        },
        {
            name: 'grade',
            displayName: '种类',
            accessType: 'attr',
            drawPropertyValue: function(g, property, value, rowIndex, x, y, w, h, data, view){//自定特性值3D渲染涵数
                var cb = function(v) {
                    data.a('grade', v);
                }
                return fillFormPane(data.formPane1, w, h, data.tablePane1, serviceType, cb);
            }
        },
        {
            name: 'number',
            displayName: '运行内存',
            accessType: 'attr',
            drawPropertyValue: function(g, property, value, rowIndex, x, y, w, h, data, view){
                var cb = function(v) {
                    data.a('number', v);
                }
                return fillFormPane(data.formPane2, w, h, data.tablePane2, serviceSize, cb);
            }
        },
        {
            name: '插口种类',
            accessType: 'attr',
            displayName: '插口种类'
        },
        {
            name: '显卡',
            accessType: 'attr',
            displayName: '显卡'
        },
        {
            name: '型号规格',
            accessType: 'attr',
            displayName: '型号规格',
        }
    ]);
}

第3第4个特性中 drawPropertyValue 特性的回到值为 fillFormPane 涵数,这个涵数的主要参数各自为(表单组件 formP,表单组件宽 w,表单组件高 h,表单组件中按钮点一下转化成弹出框中的报表组件 tableP,报表组件中的数字能量数组內容 arr,cb 涵数将双击鼠标报表组件中的行回到的值取值给 form 表单中的 ht.widget.TextField 文字框)。

第1个主要参数 formP 表单组件的建立,表单组件的建立便是建立1个表单组件,在表单组件中加上1个文字框和1个按钮,这个流程在 HT 中也是非常的简易:

function createFormPane(tPane) {//建立表单面板
    var formPane = new ht.widget.FormPane();
    formPane.setPadding(0);//设定表单4周与组件內容的间隔
    var tField = new ht.widget.TextField();//建立1个文字框
    tField.setText('');//文字框的內容为空
    tField.setDisabled(true);//文字框不能实际操作
    formPane.addRow([//向表单中加上行
        {
            id: 'tag',//唯1标识特性,可根据formPane.getItemById(id)获得加上到对应的item目标
            element: tField//特性值可为 HTML原生态元素、FormPane內部自绘图的文字信息内容和HT自带组件如Button、CheckBox和ComboBox等
        },
        {
            button:{//设定了该特性后HT将依据特性值全自动搭建ht.widget.Button目标,并储存在element特性上
                label:'...',//按钮上的文字內容
                onClicked: function(){//按钮点一下恶性事件
                    for(var i = 0; i < tPane.dm().size(); i++){//设定tablePane默认设置选定formPane对应的值
                        var data = tPane.dm().getDatas().get(i);
                        if(data.a('value') === formPane.v('tag')){
                            tPane.sm().ss(data);
                        }
                    }
                    return createDialog(tPane, formPane);//回到的是建立1个会话框,会话框的內容为报表面板
                }
            }
        }
    ], [0.5, 0.1]);//设定报表组件中第1个元素和第2个元素的显示信息占比。这个报表组件1共仅有两个元素,1个文字框1个按钮,占有率各自为 0.5 和 0.1
    return formPane;
}

createDialog 涵数建立的全过程也是简约明了,根据 setConfig(config) 方式配备会话框的题目,规格,內容等,我给 createDialog 传了1个主要参数 tPane 报表组件,用作会话框显示信息的內容:

function createDialog(tPane){//建立弹出框
    dialog.setConfig({
        title: gv.sm().ld().getName()+"的"+formPane.title,//会话框的题目
        content: tPane, //立即将弹出框的內容设定为报表面板
        width: 400,//特定会话框的宽度
        height: 200,
        draggable: true,//特定会话框是不是可拖拽调剂部位
        closable: true,//表明是不是显示信息关掉按钮
        maximizable: true,//表明会话框是不是可被最大化
        resizeMode: "wh",//电脑鼠标挪动到会话框右下角可更改会话框的尺寸,wh表明宽高都可以调剂
        buttons: [//加上两个按钮
            {
                label: '撤销',
                action: function(){
                    dialog.hide()
                }
            },
            {
                label: '明确',
            }
        ]
    });
    dialog.show();//显示信息会话框
}

第4个主要参数 tableP 报表组件,也沒有甚么非常的,便是建立1个表单组件,随后向表单组件中加上列,流程简易,编码也非常简易:

function createTableView(arr, dm){//建立报表组件
    var tableView = new ht.widget.TableView(dm);
    tableView.addColumns([//用json的数字能量数组主要参数方法大批量加上列信息内容
        {
            displayName: 'ID',//获得表头的列名內容
            drawCell: function(g, data, selected, column, x, y, w, h, tableView){//自定模块格3D渲染方法
                var id = tableView.getRowIndex(data);//回到data目标所属的行数据库索引
                ht.Default.drawText(g, 'row' + (id + 1), null, null, x, y, w, h, 'center');//绘图文本主要参数(g画笔目标,value文本內容,font文本字体样式,color文本色调,x绘图刚开始的x座标,y绘图刚开始的y座标,w绘图的宽度,h绘图的高宽比,align文本水平对齐方法,vAlign文本竖直对齐方法)
            }
        },
        {
            displayName: 'Name',
            drawCell: function(g, data, selected, column, x, y, w, h, tableView){
                var id = tableView.getRowIndex(data);
                var info = arr[id];
                ht.Default.drawText(g, info, null, null, x, y, w, h, 'center');
            }
        }
    ]);
    return tableView;
}

解释完 fillFormPane 中的主要参数,看来看这个涵数是怎样界定的,基础上只差最终1步,点一下 tablePane 报表组件中的元素,将这个元素回到给 formPane 表单组件中的 textField 文字框:

function fillFormPane(formP, w, h, tableP, arr, cb){//右侧的formpane
    if(formP === undefined){
        return;
    }
    formP.setWidth(w);
    formP.setHeight(h);
    formP.setHGap(0);

    if(formP.v('tag') === 'undefined' || formP.v('tag') === '') {
        formP.v('tag', arr[0]);
    }

    tableP.onDataDoubleClicked = function(data){//报表组件中的data所属行被双击鼠标时回调函数
        var v = arr[data.a('index')];
        formP.v('tag', v);//依据id设定对应item元素值 为 setValue 的简写,这个id为tag的元素便是文字框
        dialog.hide();
        if (cb){cb(v);} //假如传入了cb主要参数,则设定data.a('number')/data.a('helloName')的值为报表中被双击鼠标的那1行的值,即取值给第3第4特性
    }

    tableP.onDataClicked = function(data){//报表组件中的data所属行被点击时回调函数
        dialog.getConfig().buttons[1].action = function(){//点一下“明确”才开展下面的实际操作
            var v = arr[data.a('index')];
            formP.v('tag', v);
            dialog.hide();
            if (cb){cb(v);} 
        }
    };
    return formP.getView();
}
function fillFormPane(formP, w, h, tableP, arr, cb){//右侧的formpane
    if(formP === undefined){
        return;
    }
    formP.setWidth(w);
    formP.setHeight(h);
    formP.setHGap(0);

    if(formP.v('tag') === 'undefined' || formP.v('tag') === '') {
        formP.v('tag', arr[0]);
    }

    tableP.onDataDoubleClicked = function(data){//报表组件中的data所属行被双击鼠标时回调函数
        var v = arr[data.a('index')];
        formP.v('tag', v);//依据id设定对应item元素值 为 setValue 的简写,这个id为tag的元素便是文字框
        dialog.hide();
        if (cb){cb(v);} //假如传入了cb主要参数,则设定data.a('number')/data.a('helloName')的值为报表中被双击鼠标的那1行的值,即取值给第3第4特性
    }

    tableP.onDataClicked = function(data){//报表组件中的data所属行被点击时回调函数
        dialog.getConfig().buttons[1].action = function(){//点一下“明确”才开展下面的实际操作
            var v = arr[data.a('index')];
            formP.v('tag', v);
            dialog.hide();
            if (cb){cb(v);} 
        }
    };
    return formP.getView();
}

右上方特性栏的显示信息到这里就所有完毕了,右正下方的报表面板的建立方法也是雷同的,大伙儿能够自主看编码了解。

全自动合理布局

最终说1下全部页面连接点的排布,HT 中的 autolayout 全自动合理布局组件,即依据连接点和连线关联,出示多种多样种类优化算法开展全自动排布连接点部位。 全自动合理布局常见于图元较多,或联接关联教繁杂时,不容易于人力拖拽放置的情景。我把各个合理布局方法根据按钮的方法展现出来了,点一下对应的按钮,合理布局方法就会依据按下的按钮设定的排布方法来全自动合理布局:

最先,建立1个新的案例,传入必须全自动合理布局的目标,能够为 DataModel、graphView 和 graph3dView 3种,随后设定默认设置的排布方法:

autoLayout = new ht.layout.AutoLayout(gv);
setTimeout(function(){
    layout('towardsouth', true);//由于照片还没载入出来的情况下,全自动合理布局就依照连接点的默认设置尺寸来合理布局的
}, 200);

接着建立 formPane 表单面板,加上进 body 中,放在 body 左上角,我不将全部编码粘出来了,就显示信息第1个合理布局的按钮就好:

function createDirectionForm(){
    var form = new ht.widget.FormPane();
    form.setWidth(200);//设定表单宽度
    form.setHeight(80);
    document.body.appendChild(form.getView());
    form.getView().style.background = '#fff';
    form.getView().style.boxShadow = '4px 16px 16px rgba(0, 0, 0, 0.1)';//设定黑影款式
    form.addRow([//这1行独立拿出来,做为题目
        {
            element: '全自动合理布局:',//显示信息的文本
        }
    ], [0.1]);//数字能量数组内仅有1个目标,就只设定1个目标的宽度就好
    form.addRow([
        {
            button: {
                icon: '合理布局/南合理布局.json',
                onClicked: function(){
                    layout('towardsouth', true);
                },
                background: null,
                labelColor: '#fff',
                groupId: 'btn',
                toolTip: '朝南合理布局',
                borderColor: null
            }
        },
        //....接下来加上剩余的6个按钮
    ], [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]);//数字能量数组中有7个目标,就要设定7个目标的宽度
    return form;
}

较为趣味的一部分便是这些啦,谢谢大伙儿的阅读文章,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。