热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Raphael绘制流程图,自绘动态箭头,可拖动,有双击事件,纯前端,兼容各种浏览器...

关于RaphalRaphal是一个在网页上绘图的js类库,非常小压缩版只有89k左右官方宣称兼容各种主流浏览器,据笔者测试在IE6下尚有一些问题

关于Raphaël

Raphaël是一个在网页上绘图的js类库,非常小压缩版只有89k左右

官方宣称兼容各种主流浏览器,据笔者测试在IE6下尚有一些问题(不过这些与本文无关)

他是使用js来创建vml或svg来绘图的

缘起

项目中不能使用Silverlight或者flash来解决绘图和拖动的问题

而且为了项目效果较好,要求拖动的时候箭头能动态改变起点和重点,别且箭头要改变方向

所以只能考虑JS了

效果

image

演示

http://www.mrlh.net/flowchart/demo.htm[已经不能访问了]

源码

引用

这两个东西是不相干的,引用先后顺序也无所谓

页面加载完成后的代码

$(function () {//用来存储节点的顺序var connections = [];//拖动节点开始时的事件var dragger = function () {this.ox = this.attr("x");this.oy = this.attr("y");this.animate({ "fill-opacity": .2 }, 500);};//拖动事件var move = function (dx, dy) {var att = { x: this.ox + dx, y: this.oy + dy };this.attr(att);$("#test" + this.id).offset({ top: this.oy + dy + 10, left: this.ox + dx + 10 });for (var i = connections.length; i--; ) {r.drawArr(connections[i]);}};//拖动结束后的事件var up = function () {this.animate({ "fill-opacity": 0 }, 500);};//创建绘图对象var r = Raphael("holder", $(window).width(), $(window).height());//绘制节点var shapes = [r.rect(190, 100, 60, 40, 4),r.rect(290, 80, 60, 40, 4),r.rect(290, 180, 60, 40, 4),r.rect(450, 100, 60, 40, 4)];//定位节点上的文字$("#test1").offset({ top: 100 + 10, left: 190 + 10 });$("#test2").offset({ top: 80 + 10, left: 290 + 10 });$("#test3").offset({ top: 180 + 10, left: 290 + 10 });$("#test4").offset({ top: 100 + 10, left: 450 + 10 });//为节点添加样式和事件,并且绘制节点之间的箭头for (var i = 0, ii = shapes.length; i

这些代码注释比较详细,就不多说了

在这些代码中涉及到操作的界面元素HTML代码如下

测试1
测试2
测试3
测试4

其中关键元素的样式如下

#holder{top: 0px;left: 0px;right: 0px;bottom: 0px;position: absolute;z-index: 999;}test{position: absolute;width: 80px;height: 30px;top: 0px;z-index: 0;}

在拖动事件中,动态改变了节点文本元素的位置

并且重绘了节点和箭头

drawArr是一个自定义方法,负责修改箭头的方向,代码如下

//随着节点位置的改变动态改变箭头Raphael.fn.drawArr = function (obj) {var point = getStartEnd(obj.obj1, obj.obj2);var path1 = getArr(point.start.x, point.start.y, point.end.x, point.end.y, 8);if (obj.arrPath) {obj.arrPath.attr({ path: path1 });} else {obj.arrPath = this.path(path1);}return obj;};

首先需要确定箭头的起始位置,

point包含两个点,

point.start为起点,

point.end为终点,

然后需要确定箭头的绘图路径

一个箭头包含三个线段,四个点

1:起点,2:终点,3:箭头终点1,4:箭头终点2

image

在此函数中,判断如果箭头已经被绘制过,

只要修改属性即可

如果没有被绘制过,则需要重新绘制

 

下面来看一下动态确定起点和终点的代码

function getStartEnd(obj1, obj2) {var bb1 &#61; obj1.getBBox(),bb2 &#61; obj2.getBBox();var p &#61; [{ x: bb1.x &#43; bb1.width / 2, y: bb1.y - 1 },{ x: bb1.x &#43; bb1.width / 2, y: bb1.y &#43; bb1.height &#43; 1 },{ x: bb1.x - 1, y: bb1.y &#43; bb1.height / 2 },{ x: bb1.x &#43; bb1.width &#43; 1, y: bb1.y &#43; bb1.height / 2 },{ x: bb2.x &#43; bb2.width / 2, y: bb2.y - 1 },{ x: bb2.x &#43; bb2.width / 2, y: bb2.y &#43; bb2.height &#43; 1 },{ x: bb2.x - 1, y: bb2.y &#43; bb2.height / 2 },{ x: bb2.x &#43; bb2.width &#43; 1, y: bb2.y &#43; bb2.height / 2 }];var d &#61; {}, dis &#61; [];for (var i &#61; 0; i <4; i&#43;&#43;) {for (var j &#61; 4; j <8; j&#43;&#43;) {var dx &#61; Math.abs(p[i].x - p[j].x),dy &#61; Math.abs(p[i].y - p[j].y);if ((i &#61;&#61; j - 4) ||(((i !&#61; 3 && j !&#61; 6) || p[i].x p[j].x) &&((i !&#61; 0 && j !&#61; 5) || p[i].y > p[j].y) &&((i !&#61; 1 && j !&#61; 4) || p[i].y

这段代码来自Raphael官方demo

不是我写的

也一时半会说不清楚&#xff0c;

大家还是自己去研究吧

 

确定箭头路径的代码如下

//获取组成箭头的三条线段的路径function getArr(x1, y1, x2, y2, size) {var angle &#61; Raphael.angle(x1, y1, x2, y2);//得到两点之间的角度var a45 &#61; Raphael.rad(angle - 45);//角度转换成弧度var a45m &#61; Raphael.rad(angle &#43; 45);var x2a &#61; x2 &#43; Math.cos(a45) * size;var y2a &#61; y2 &#43; Math.sin(a45) * size;var x2b &#61; x2 &#43; Math.cos(a45m) * size;var y2b &#61; y2 &#43; Math.sin(a45m) * size;var result &#61; ["M", x1, y1, "L", x2, y2, "L", x2a, y2a, "M", x2, y2, "L", x2b, y2b];return result;}

此函数把箭头路径作为数组反馈给调用函数

数组中

M表示画笔起点移动到此点

L表示从某点绘制到某点&#xff0c;绘制直线

以上函数反馈结果的意思是&#xff1a;

画笔从&#xff08;x1,y1&#xff09;开始绘制直线到(x2,y2),然后从(x2,y2)绘制直线到(x2a,y2a)然后画笔移动到(x2,y2)然后从(x2,y2)绘制直线到(x2b,y2b)

在确定这几个点的过程中

用到了一些数学知识&#xff0c;具体原理也不多说了

 

 

喜欢的朋友请点支持&#xff01;谢谢大家&#xff01;

转:https://www.cnblogs.com/liulun/archive/2012/05/18/2507472.html



推荐阅读
author-avatar
mobiledu2502878383
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有