用TWaver HTML5定制五彩斑斓的链路

最近有客户提到自定义链路的需求,个人感觉非常有代表意义,现在共享出来给大家参考一下。先来看看需求:
1.  链路要分成两半,用两种颜色填充。
2.  填充百分比在不同值域时,用不同颜色。
3.  显示刻度

4.  有个开关,可以控制链路变短,变短后,链路只画开始和结束部分(相当于原始链路的缩影),中间不画

5.  如果有多条链路,链路合并后两端分别显示这些链路中的最高填充百分比
合并前:

合并后:


6.  进入子网后,节点上显示和上层节点的连线信息
进入子网前,节点2和子网内节点4之间有链路:

进入子网后,节点4上也显示此链路:


先看看实现的效果,后面我们慢慢解释如何定制链路:



前5个需求可以通过自定义Link和LinkUI实现,需要注意:
1.  用Link#getBundleLinks获取所有的捆绑链路
2.  用LinkUI#drawLinePoints画线</li>

完整代码如下:

// 自定义Link构造函数
demo.ScaleLink = function(id, from, to) {
    // 调用基类构造函数
    demo.ScaleLink.superClass.constructor.call(this, id, from, to);
    // 设置链路宽度为10个像素
    this.setStyle('link.width', 10);
    //this.setStyle('link.color', 'rgba(0, 0, 0, 0)');
    // 设置Link类型为平行
    this.setStyle('link.type', 'parallel');
    // 设置链路捆绑的间距为40
    this.setStyle('link.bundle.offset', 40);
    // 设置刻度颜色
    this.setClient('scaleColor', 'black');
    // 设置刻度宽度
    this.setClient('scaleWidth', 1);
    // 设置刻度个数
    this.setClient('scaleNumbers', 4);
    // 设置是否变短
    this.setClient('shortened', false);
    // 设置变短后的长度
    this.setClient('shortenLength', 100);
    // 设置分割线颜色
    this.setClient('splitterColor', 'black');
    // 设置起始填充百分比
    this.setClient('fromFillPercent', 0);
    // 设置结束填充百分比
    this.setClient('toFillPercent', 0);
};
// 设置自定义Link继承twaver.Link
twaver.Util.ext('demo.ScaleLink', twaver.Link, {
    // 重载获取UI类的方法,返回自定义UI类
	getCanvasUIClass : function () {
		return demo.ScaleLinkUI;
	},
	// 根据百分比获取填充颜色
	getFillColor: function(percent) {
		if (percent < 0.25) {
			return 'green';
		}
		if (percent < 0.5) {
			return 'yellow';
		}
		if (percent < 0.75) {
			return 'magenta';
		}
		return 'red';
	},
	// 获取起始填充颜色
	getFromFillColor: function () {
		return this.getFillColor(this.getFromFillPercent());
	},
	// 获取结束填充颜色
	getToFillColor: function () {
		return this.getFillColor(this.getToFillPercent());
	},
	// 获取起始百分比
	getFromFillPercent: function () {
	    // 如果是链路捆绑代理,返回所有捆绑链路中最大填充百分比的值
		if (this.isBundleAgent()) {
			var fromAgent = this.getFromAgent(),
				percentKey, maxPercent = 0, percent;
			this.getBundleLinks().forEachSiblingLink(function (link) {
				percentKey = fromAgent === link.getFromAgent() ? 'fromFillPercent' : 'toFillPercent';
				percent = link.getClient(percentKey);
				maxPercent = percent > maxPercent ? percent : maxPercent;
			});
			return maxPercent;
		} else {
			return this.getClient('fromFillPercent');
		}
	},
	// 获取结束百分比
	getToFillPercent: function () {
	    // 如果是链路捆绑代理,返回所有捆绑链路中填充百分比最大的值
		if (this.isBundleAgent()) {
			var toAgent = this.getToAgent(),
				percentKey, maxPercent = 0, percent;
			this.getBundleLinks().forEachSiblingLink(function (link) {
				percentKey = toAgent === link.getToAgent() ? 'toFillPercent' : 'fromFillPercent';
				percent = link.getClient(percentKey);
				maxPercent = percent > maxPercent ? percent : maxPercent;
			});
			return maxPercent;
		} else {
			return this.getClient('toFillPercent');
		}
	},
	// 重载获取网元名称方法,判断如果是链路捆绑代理,就返回起始和结束代理节点的名称
	getName: function () {
	    if (this.getClient('shortened')) {
	        return null;
	    } else if (this.isBundleAgent()) {
			return this.getFromAgent().getName() + '-' + this.getToAgent().getName();
		} else {
			return demo.ScaleLink.superClass.getName.call(this);
		}
	}
});

// 自定义LinkUI构造函数
demo.ScaleLinkUI = function(network, element){
    // 调用基类构造函数
    demo.ScaleLinkUI.superClass.constructor.call(this, network, element);
};
// 设置自定义Link继承twaver.canvas.LinkUI
twaver.Util.ext('demo.ScaleLinkUI', twaver.canvas.LinkUI, {
	// 获取Link角度
	getAngle: function () {
		return getAngle(this.getFromPoint(), this.getToPoint());
	},
	// 获取Link中间点
	getMiddlePoint: function (from, to, percent) {
		return {
	    	x: from.x + (to.x - from.x) * percent,
	    	y: from.y + (to.y - from.y) * percent
	    };
	},
	// 画刻度线
	drawScaleLine: function (from, to, angle, length, ctx, percent, lineWidth, lineColor) {
	    var point = this.getMiddlePoint(from, to, percent);
	    var y = length/2 * Math.sin(angle),
	    	x = length/2 * Math.cos(angle);
	    ctx.beginPath();
	    ctx.lineWidth = lineWidth;
	    ctx.strokeStyle = lineColor;
	    ctx.moveTo(point.x + x, point.y + y);
	    ctx.lineTo(point.x - x, point.y -y);
	    ctx.stroke();
	},
	// 获取是否将链路变短
	isShorten: function () {
		var link = this.getElement();
		return link.getClient('shortened') && this.getLineLength() > link.getClient('shortenLength') * 2;
	},
	// 重载画链路函数,用自定义逻辑画链路
	paintBody: function (ctx) {
        var points = this.getLinkPoints(),
        	link = this.getElement();
        if (!points || points.size() < 2) {
            return;
        }

        var lineLength = this.getLineLength(),
        	shortenLength = link.getClient('shortenLength'),
        	percent = shortenLength / lineLength,
	    	from = points.get(0),
	    	to = points.get(1),
	    	angle = this.getAngle() + Math.PI/2;
	    if (this.isShorten()) {
        	fromPoints = new twaver.List([from, this.getMiddlePoint(from, to, percent)]);
        	toPoints = new twaver.List([this.getMiddlePoint(from, to, 1 - percent), to]);
        	this._paintBody(ctx, fromPoints, angle);
        	this._paintBody(ctx, toPoints, angle);

        	// 画文字
			ctx.textAlign = 'center';
			ctx.textBaseline = 'middle';
			ctx.fillStyle = 'black';
			var textCenter = {x: (fromPoints.get(0).x + fromPoints.get(1).x)/2, y: (fromPoints.get(0).y + fromPoints.get(1).y)/2};
			ctx.fillText(link.getName(), textCenter.x, textCenter.y);

			textCenter = {x: (toPoints.get(0).x + toPoints.get(1).x)/2, y: (toPoints.get(0).y + toPoints.get(1).y)/2};
			ctx.fillText(link.getName(), textCenter.x, textCenter.y);

			ctx.fillText(link.getToNode().getName(), fromPoints.get(1).x, fromPoints.get(1).y);
			ctx.fillText(link.getFromNode().getName(), toPoints.get(0).x, toPoints.get(0).y);
        } else {
        	this._paintBody(ctx, points, angle);
        }

		// 画起始箭头
		if (link.getClient('arrow.from')) {
		    twaver.Util.drawArrow(ctx, 12, 9, points, true, 'arrow.standard', true, 'gray', 0, 0, 1, 'black');
        }
	    // 画结束箭头
        if (link.getClient('arrow.to')) {
		    twaver.Util.drawArrow(ctx, 12, 9, points, false, 'arrow.standard', true, 'gray', 0, 0, 1, 'black');
        }
	},
	_paintBody: function (ctx, points, angle) {
        var link = this.getElement(),
        	width = link.getStyle('link.width'),
        	grow = width,
        	outerColor = this.getOuterColor();
        if (outerColor) {
            var outerWidth = link.getStyle('outer.width');
            grow += outerWidth * 2;
        }
        var selectBorder = !this.getEditAttachment() && link.getStyle('select.style') === 'border' && this.getNetwork().isSelected(link);
        if (selectBorder) {
            var selectWidth = link.getStyle('select.width');
            grow += selectWidth * 2;
        }
        ctx.lineCap = link.getStyle('link.cap');
        ctx.lineJoin = link.getStyle('link.join');
        // 画选中边框
        if (selectBorder) {
            this.drawLinePoints(ctx, points, grow, link.getStyle('select.color'));
        }
        // 画边框
        if (outerColor) {
            this.drawLinePoints(ctx, points, width + outerWidth * 2, outerColor);
        }
        // 画Link
        this.drawLinePoints(ctx, points, width, this.getInnerColor() || link.getStyle('link.color'));

		var fromFillPercent = link.getFromFillPercent(),
	    	toFillPercent = link.getToFillPercent(),
	    	fromFillColor = link.getFromFillColor(),
	    	toFillColor = link.getToFillColor(),
	    	from = points.get(0),
	    	to = points.get(1);

	    var x = from.x + (to.x - from.x) / 2 * fromFillPercent,
	    	y = from.y + (to.y - from.y) / 2 * fromFillPercent;
	    var middle = {x: x, y: y};
	    var fromPoints = new twaver.List([from, middle]);
		// 画起始填充色
	    this.drawLinePoints(ctx, fromPoints, width, fromFillColor);

	    from = points.get(1);
	    to = points.get(0);
	    x = from.x + (to.x - from.x) / 2 * toFillPercent;
	    y = from.y + (to.y - from.y) / 2 * toFillPercent;
	    middle = {x: x, y: y};
	    var toPoints = new twaver.List([from, middle]);
	    // 画结束填充色
	    this.drawLinePoints(ctx, toPoints, width, toFillColor);

    	from = points.get(0);
    	to = points.get(1);
	    var scaleWidth = link.getClient('scaleWidth'),
	    	scaleColor = link.getClient('scaleColor');
	    // 画刻度
	    for (var i = 1, n = link.getClient('scaleNumbers') * 2; i < n; i++) {
	    	this.drawScaleLine(from, to, angle, width/2, ctx, i/n, scaleWidth, scaleColor);
	    }
	    // 画分隔线
	    this.drawScaleLine(from, to, angle, width, ctx, 0.5, 3, link.getClient('splitterColor'));
	}
});

 
本文完整代码见附件:见原文最下方

 

twaver-html5-5.9.0-api_html5_-5.9.0-api_twaver_ twaver-html5-5.9.0-api 立即下载

相关推荐

Blender.粒子效果

Blender.粒子效果 ✦ shift+A新建一个棱角球,细分(之后要分解成许多小颗粒) ✦ 给球添加粒子系统,这时播放粒子会向下掉,力场权重☛重力☛0后,粒子会在球体周围运动 ✦ shift+A添加一个力场,调整力场强度 ✦如果粒子运动太快,我们可以在输出属性中调整时间重映射的原始值 ✦想让粒子在球周围运动而不是发散出去,在物理属性找到力场设置,调整流的大小 ✦S键将球形缩小到看不见 ✦给粒子变添加立方体的形状,在粒子属性里找到渲染选项,将“光晕”改为“物体”,在实例物体中选择新建的立方

weixin_46385629的博客 6668

Twaver-HTML5基础学习(4)告警元素(Alarm)

Twaver-HTML5基础学习(4)告警元素(Alarm)

见贤思齐焉,见不贤内自省 1369

光度立体三维重建——光源标定

光源标定的目的是为了确定光源方向或强度,一般利用物体表面的明暗信息、阴影信息或者反射特性三类信息中的其中一种即可,也可以将三种信息结合。采用不同标定物,是利用不同标定物的反射特性获取更加精确的光源信息。

wfengzi5的博客 1560

twaver html5 2d demo,TWaver 2D+GIS+3D的试用和在线Demo

TWaver 3D for HTML5试用下载:各种在线3D Demo:http://idc.servasoft.com:8081/twaver-html5-3d/三维机房、变电站、会议室等都在里面。《zw版&&num;183&semi;Halcon-delphi系列原创教程》 2d照片-3d逆向建模脚本 2d照片-3d逆向建模脚本 3D逆向建模,是逆向工程的核心要素. ...

weixin_35699471的博客 570

MS1861宏晶微视频显示与控制器芯片:开发资料全解析与应用指南

本文全面解析了宏晶微MS1861视频显示与控制器芯片的核心功能与开发流程。该芯片作为高性能的“视频信号翻译官”,支持HDMI、LVDS等多种输入与MIPI、LVDS等输出,集成强大的图像处理与OSD叠加功能。文章详细介绍了从资料获取、环境搭建到以HDMI转MIPI为例的实战配置与调试技巧,为工业HMI、广告机等应用的开发者提供了完整的应用指南。

weixin_29198045的博客 337

免费搞定DWG转DXF:ODA File Converter保姆级配置指南(附常见报错解决)

本文详细介绍了如何使用ODA File Converter免费工具实现DWG到DXF的格式转换,包括环境配置、命令行参数解析、编程集成方案及常见问题解决。特别针对网络访问异常、参数配置等实际痛点提供应对策略,帮助用户高效完成工程设计文件的格式转换。

weixin_29291185的博客 5996

TWaver初学实战——炫动2D机房之连线篇

其实能真正体现TWaver特色的,不是之前的机柜和设备面板的绘制,而是今天要实现的端口连线。 制作连线前,首先要增加个“连线模式”的开关。方案很多种,我选择灵活简洁的 右键菜单 popupMenu.isVisible = function(menuItem) { var item = visibleGroup(lastData); var visible = menu...

weixin_30553065的博客 400

别再让C盘爆红了!手把手教你将Anaconda虚拟环境迁移到其他盘(附权限问题解决)

本文详细指导如何将Anaconda虚拟环境从C盘迁移到其他驱动器,解决C盘空间不足问题。通过conda config命令和直接修改.condarc配置文件两种方法,确保环境迁移顺利进行,同时提供权限问题解决方案和长期维护技巧,帮助用户高效管理虚拟环境。

weixin_42525289的博客 420

Twaver-HTML5基础学习(14)连线(Link)连线类型(直线、延伸直线、正交直线)

Twaver-HTML5基础学习(14)连线(Link)连线类型(直线、延伸直线、正交直线)

见贤思齐焉,见不贤内自省 2108

渲染TA实战:冰面效果制作分享

这里画一张图:我们可以看到,如果深度图的范围没有进过缩放,那就是0-1,但是归一化的-viewDir的向量长度为1,如果-viewDir不和表面垂直(这是绝大多数的情况),那么viewDir.z的分量就是一个不定值,我们不好确定需要走多少步,viewDir才能和底面相交。然后我们需要冰面的Alpha图:因为冰是透明物体,所以相对于Albedo,我们更需要的是一张冰面裂纹的蒙版图,这张图需要记录冰面的裂纹走向和深浅、冰封的气泡、以及因为压力或气体等原因产生的类似雾的效果。

qq_41166022的博客 1025

天融信防火墙NGFW4000(TG-4628)安装配置笔记

配置一台全新的天融信防火墙NGFW4000,配置完后,内网用户10.10.1.0/24和10.10.2.0/24可以通过防火墙上网,外网用户可以通过访问防火墙的外网接口地址来访问内网的WEB服务器10.10.1.200,并且内网用户也可以通过WEB服务器的外网地址进行访问。 网络说明: 防火墙外网接口地址:218.90.123.121/30 防火墙内网接口地址:19...

weixin_33671935的博客 4454

TWaver图形界面之道(五)Hello TWaver

继续上一章的介绍TWaver图形界面之道(四)如何申请与技术支持 本章将以一个入门示例开始,介绍TWaver的基本使用,设计思想以及开发流程,如果你已经熟悉了TWaver的使用,熟悉了TWaver的MVC的设计模式,可跳过本章节。 Hello TWaver 以一个经典示例开始,创建两个节点和一条连线,并在不同组件中展现,然后我们会追加告警,观察界面的变化。 开发环境 ...

web开发自学 501

通过Langchain实现大模型完成测试用例生成的代码(可集成到各种测试平台)

代码中使用的是讯飞spark3.0版本,其中版本在的控制已经封装到了langchain对应的讯飞的iflytek的类中,可以在调用的时候显示控制,默认是spark2.0版本。

Criss@陈磊 2361

Twaver 中link流动效果,tooltip显示/隐藏

1.设置link的流动效果有时发现单纯设置link.setStyle('link.flow', true);并没有起作用,这时需要检查之前是否设置://流动线条network.setLinkFlowEnabled(true);2.设置toolTip的显示与隐藏    network.setToolTipEnabled(true);    network.setToolTipEnabled(fals...

Keep moving on. 1656

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Twaver-HTML5基础学习(32)Network样式andTree样式

Twaver-HTML5基础学习(32)Network样式andTree样式

见贤思齐焉,见不贤内自省 1068

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

html5怎么给表格设置分页,如何让HTML5的表格支持后台排序与分页

TWaver HTML5发布已有一段时间,使用的客户也是逐渐增加,于是我也迫不及待地申请了一个试用版来写一个小网页,最近正在写到数据查询,表格显示的功能。表格组件在HTML5中是提供的,查看TWaver提供的Demo,表格的使用还是比较多的,于是参考了其中的一个Demo,新建一个表格,并给表格赋值。很快一张表格就生成了。 但是想想,如果数据库中有几千甚至几万条数据,一下子显示出来也是不现实的,立马...

weixin_35011300的博客 1049

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Twaver demo

TWaver中有一个平行四边形的Group对象,适合做上图中的“层”的概念。先如下封装并设置属性: package demo;      import java.awt.Color;   import twaver.Group;   import twaver.TWaverConst;      public class LayerGroup extends Group {   ...

Ljh435870628的专栏 535

twaver 内容导出图片不清晰解决方案

twaver转换为canvas导出图片时模糊问题解决

YSTXDONG的专栏 356

HTML5画布路径教程

创建一个路径与HTML5画布,我们可以连接多个子路径。终点的每一个新的subpath成为新的上下文。我们可以用画线(),arcTo(),quadraticCurveTo(),和bezierCurveTo()方法来构建每个subpath占我们的路径。我们还可以使用beginPath()方法每次我们想开始画一个新的路径。 HTML5画布路径图 body {

limeiyans喜欢编程的那些事 911

Twaver-HTML5基础学习(7)Layer图层元素

Twaver-HTML5基础学习(7)Layer图层元素

见贤思齐焉,见不贤内自省 1393

Twaver-HTML5基础学习(11)形状节点(ShapeNode)

Twaver-HTML5基础学习(11)形状节点(ShapeNode)

见贤思齐焉,见不贤内自省 1444

如何实现TWaver 3D颜色渐变

一般而言,需要实现3D物体的渐变,通常的思路就是通过2D绘制一张渐变canvas图片作为3D对象的贴图,这种方式是可以解决这类问题的,不过对于一般用户而言,通过2D生成一张渐变的图片,有一定的难度,另外如果要生成的图片比较多,性能效率上会成为一个瓶颈,特别是渐变随着条件在不断变化的情况下,就需要每次绘制的时候都去生成一张渐变的canvas图,效率极其低。

TWaver可视化 1534
上一篇: 使用3D呈现拓扑的多层次结构
下一篇: 自定义Background
subnetwork
博客等级 码龄17年 17粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值