为了更好的提升用户体验,移动端逐渐出了许多的移动端的框架,比如Sencha Touch、JQTouch、Jquery-moblie、jqMobi等等。这些框架都有优缺点,不同的框架应用在不同的项目中。现简单阐述一下各框架的优缺点: 一、Sencha Touch框架是一个重量级的框架、它上手较难,代码复杂,并且需要较强的程序基础才能学习,最开始的时候因为一个项目,想使用Sencha Touch框架,后来工期实在太紧张,根本没时间学习它并使用。所以最后转投其他框架。这个框架兼容性很高,运行起来的速度一般,需要长时间的学习且需要水平较高的程序基础才行。所以不太适合前端制作人员的使用。我会在以后的机会单开一篇关于它的使用demo。 二、JQTouch是一个轻量级框架、纯jquery写法,上手比较容易,代码容易理解,加载速度也很快,缺点是配合的移动端效果插件较少,需要很多外部的插件相结合,另外,个别插件还需要解决与框架之间的兼容问题。它的最大的一个弊端就是可利用和变通的布局较少。 三、Jquery-moblie也是一个轻量级框架、纯jquery写法,上手容易,代码容易理解,但由于其绑定的前端效果插件过多,且代码结构有些臃 肿,造成加载速度很慢。尤其是在android系统上测试,速度很慢。用户体验效果不太好,它比较适合开发IPAD或是IOS系统的高端机型。 四、jqMobi也是一个轻量级框架、它的语言基于jquery语言。并对其进行了简化,更有利于在移动设备上进行应用,并且速度很流畅。上手也比较容…
使用js实现思维导图
本文主要阐述使用js实现思维导图的关键技术点,如果还不知道什么是思维导图的同学,请自行度娘。以下是demo和源码的传送门:
demo:http://sources.ikeepstudying.com/mindmaptree-master/
源码:http://github.com/RockyRen/mindmaptree/tree/master
在源码中我使用了svg绘制思维导图。与canvas相比,svg将图像当成对象,我们可将思维导图中节点和线等图形表现为对象,而且svg更适合用于动态交互的应用
下面介绍几个关键技术点:
子节点位置的重绘
一个基本的思维导图工具应该拥有增加节点和删除节点的功能。在某个节点上增删节点时,为了使得所有子节点的高度相对于该节点垂直居中,都会重新渲染子节点的垂直位置。
如图1所示,首先求得父节点的中心点F的坐标为(hfx, hfy),设父节点与子节点的水平距离为interval,父节点的宽为parentWidth。作水平线段FC,C点的横坐标即为子节点的横坐标childX。如下图所示:

为了让子节点间垂直隔开,每一个子节点上下都有补白,所以一个子节点所占的区域高度为该子节点的节点高度加上两个补白高度。迭代所有子节点,求取所有子节 点的区域高度areaHeight,然后在线段FC的C点上作一条长度为areaHeight的垂直平分线AB,所有子节点的垂直区域都在垂直平分线AB 内,这样可以保证所有子节点的高度相对于该节点垂直居中。如下图所示:

我们需要求得每一个子节点的垂直坐标childY。首先求得A点的垂直坐标startY = hfy – areaHeight / 2,第一个子节点的垂直坐标由startY加padding可得。求第二个子节点的垂直坐标时,startY累加上一个子节点的区域高度,则第二个子节点 的垂直坐标等于当前startY加上padding。之后的子节点通过迭代相同的操作可得。在每一轮迭代中,根据求得的子节点坐标(childX, childY)渲染节点的位置。如下图所示:

实现代码如下:
/ 以下变量请自行求得 var hfx, // 父节点的中心x轴坐标 hfy, // 父节点的中心y轴坐标 parentWidth, // 父节点的宽度 children, // 子节点列表 padding, // 子节点垂直间距 interval; // 节点间水平间距 var childX, // 子节点的x轴坐标 startY, // 子节点区域的起始坐标 childrenAreaHeight = 0; // 子节点总区域高度 childX = hfx + parentWidth / 2 + interval; // 迭代子节点,求得子节点总区域高度 children.forEach(function(child){ var curAreaHeight = getNodeHeight(child) + padding * 2; childrenAreaHeight += curAreaHeight; }); startY = hfy - childrenAreaHeight / 2; // 迭代子节点,求得每个子节点的垂直坐标 children.forEach(function(child){ var childY = startY + padding; // 已经求得当前子节点坐标(childX, childY),在这里作渲染操作 var curAreaHeight = getNodeHeight(child) + padding * 2; startY += curAreaHeight; // 其实高度累加 }); /** * 获取节点的高度 */ function getNodeHeight(){ // ... }
祖先节点的同级节点的垂直位置调整
如下图所示,当增加一个节点时,该节点父节点的同级节点需要被“撑开”:设该节点的1/2区域高度为moveY,在父节点的同级节点中,比父节点高的向上 偏移一个moveY,比父节点低的向下偏移一个moveY。父节点的父节点的同级节点也做相同的处理,一直递归到根节点为止。当删除一个节点时,节点的父 节点的同级节点会被“压低”,“压低”操作和上述操作相似。注意,当增加第一个子节点和删除最后一个子节点时,不会进行“撑开”和“压低”操作。

实现源码如下:
/** * 调整当前的父节点的同级节点的位置 * @param node 当前的父节点, 以下为该节点需要用到的属性 * node.father: 节点的父节点,为null时表示父节点为根节点 * node.children: 节点的子节点列表 * node.x: 节点的x轴坐标 * node.y: 节点的y轴坐标 * * @oaram areaHeight 被操作节点的区域高度 */ function resetBrotherPosition(node, areaHeight){ var brother, // 同级节点 moveY = areaHeight / 2; // 需要移动的高度 if(node.father){ node.father.children.forEach(function(curNode){ // 遍历同级节点 if(curNode != node){ if(brother.y < node.y){ // 向上移动brother节点的代码写在这 } else { // 向下移动brother节点的代码写在这 } } } ); } // 递归父节点 if(node.father){ resetBrotherPosition(node.father, areaHeight); } }
拖动节点
当拖动根节点时,通过改变svg的视口坐标来实现拖动整个思维导图的效果。当拖动
非根节点时,会按顺序触发mouseup、mousemove、mousedown三个事件,分别对应按下鼠标、鼠标移动和放下鼠标三个状态。在按下鼠标 状态下,会以当前节点为原型克隆一个节点用于占位。在拖动鼠标状态下,通过改变节点的坐标实现节点位置的改变。在放下鼠标状态下,会判断当前节点是否与其 他节点重叠,如果重叠则使重叠节点变为当前节点的父节点,否则,当前节点返回原来的位置。
其他技术点我就不一一列出来了,有兴趣的同学可以到上面的传送门看看源码。
本文:使用js实现思维导图
Related Posts
- 移动前端工作的那些事---前端制作篇之框架篇
-
【漫画详解】用iframe障眼法,骗取用户点击
做过Web开发的朋友曾经都有过这么个念头:在自己的页面里内嵌一个其他网站的网页,然后可以用脚本去获取他们页面里的信息,甚至可以。。。 显然,有这么好的事也肯定轮不到你来尝了:)一个叫沙箱模型的东西被发明出来,就是防止有这种想法的人搞破坏。。。所以现在的我们只能远观,不可亵玩也。 不过,这些规定只是针对脚本而已。假如让用户自己乖乖的去点,那当然是没问题的。但有多少人会去点呢!! 所以,我们需要施一些特殊的障眼法,让用户在不经意间,就点了我们想让他点的东西:) 就拿上面那个来说吧,如果直接把这个大页面赤果果的硬塞进网页,无论你怎么提示他点,或者说多少好话,大家见了就烦,就是不点:) 所以说,我们必须得修饰修饰,不然人家见了就吓跑了。首先也是最关键的就是这身材问题,突然冒出个这么肥硕的一个页面,看的人眼花缭乱,不知道 发送什么情况啦。我们要好好修剪一下,把没用的部分统统去掉,只留下我们想要的“精华”。这个简单,只要把框架先放到一个层里面,然后把层的尺寸固定好,…
- jQuery地图插件-jqvmap
用法: <script src="js/jquery.vmap.js"></script> <script src="js/jquery.vmap.world.js"></script> <script src="js/jquery.vmap.sampledata.js"></script> <script> jQuery('#vmap').vectorMap({…