Raphael path 拖动实现

让 Raphael 的 Path 动起来

Raphaël 是一个很实用的线上矢量图操作 Javascript 库。使用简单,一个值得一提的卖点是通过抽象出共同的接口屏蔽了 SVG 和 VML 之间的差异,做到了对主流浏览器的支持,包括很不给力的 IE6。(很可惜,并不支持手机 UC 浏览器)

Raphael 对于交互事件也有一定的支持,比如常用的鼠标的拖放操作(Drag and Drop)。在官方网站上也有拖放操作的例子。可惜的是,官方的这个例子的写法只对 Circle,Rect 等有效,但对于 Path 却不起作用。经过一番实践,终于了解了 Raphaël 对于拖放支持的原理,想出了一个通用的拖放操作的写法,支持所有的 Raphael 矢量对象,包括 path。

官方例子之所以不能让 Path 动起来是因为:Path 没有象 Circle 里面的 cx 和 cy 属性,要移动 Path,只能使用 Path.translate() 方法。还有一点要注意的是,Path 必须要先 fill 才能移动。

仿照官方的例子,下面是一个 Path 移动的代码示例:

var R = Raphael("paper", 400, 300);
var p = R.path('M0 0L100 0L50 80Z');
 
p.attr({"fill":"green", 'opacity':0.8});
 
var start = function (x, y) {
  this.attr({opacity: 1});
  this.lastX = x;
  this.lastY = y;
},
move = function (dx, dy, x, y) {
  var deltaX = x - this.lastX;
  var deltaY = y - this.lastY;
  this.translate(deltaX, deltaY);
  this.lastX = x;
  this.lastY = y;
},
up = function () {
  this.attr({opacity: 0.8});
}; 
 
p.drag(move, start, up);

运行效果如下

上面的例子有几点要说明一下

  • 回调函数 move 的第一个和第二个参数永远是鼠标所在的点距移动初始时的鼠标位置的相对位移值。而不是距离上次 move 回调时鼠标位置的相对位移值
  • 我们在 start 和 move 中记录并不断更新相对上次鼠标位置的相对位移值,并保存在 this.lastX 和 this.lastY 中
  • 我们通过 this.translate() 进行实际的移动操作
  • 在一开始,要设置 fill 属性,否则就不能进行移动操作

这个例子不但能工作,更好的是,因为所有的 Raphael 矢量对象都有 translate 方法。所以,它不仅对 path 有效,也对所有的 Raphael 矢量对象有效。那么,是不是能做出来类似 jQuery.ui 里面的 draggble 的函数呢。下面就是一个简单的扩展,为 Raphael 对象加入了 draggable 方法。

(function(R) {
    R.el.draggable = function(move, start, up) {
        this._ui = this._ui || {};
 
        var that = this;
 
        this._ui.onMove = R.is(move, 'function') ?
        move : function(distanceX, distanceY, x, y, deltaX, deltaY) {
            that.translate(deltaX, deltaY);
        };
 
        this._ui.onStart = R.is(start, 'function') ? start : function(x, y) {
        };
 
        function onMove(distanceX, distanceY, x, y) {
            var deltaX = x - that._ui.lastX;
            var deltaY = y - that._ui.lastY;
            that._ui.lastX = x;
            that._ui.lastY = y;
            that._ui.onMove(distanceX, distanceY, x, y, deltaX, deltaY);
            that.paper.safari();
        };
 
        function onStart(x, y) {
            that._ui.lastX = x;
            that._ui.lastY = y;
            that._ui.onStart(x, y);
        };
 
        return this.drag(onMove, onStart, up);
    };
})(Raphael);

上面的一段代码,扩展了 Raphael 对象的方法,让它们拥有了类似 jquery.ui 里 draggable 的能力。下面是用利用这个扩展重新写的拖放 Path 的例子。

var R = Raphael("paper", 400, 300);
R.rect(0, 0, 400, 300);
 
var p = R.path('M0 0L100 0L50 80Z');
 
p.attr({"fill":"green", 'opacity':0.5});
p.draggable();

可以看到,像 jquery.ui 提供的功能一样,只需要简单的调用 .draggable() 就可以让对象被鼠标拖拽

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小白安全

小白博客 MySQL日期时间函数大全

DAYOFWEEK(date) 返回日期date是星期几(1=星期天,2=星期一,……7=星期六,ODBC标准) mysql> select DAYOFWEE...

28510
来自专栏不止是前端

实用主义:JS判断给定日期是第几周

2977
来自专栏有趣的Python和你

Python数据分析之小鲜肉粉丝情况数据预处理数据分析

1286
来自专栏张善友的专栏

如何用微软StreamInsight 处理和分析实时数据

StreamInsight 是 SQL Server 2008 R2 中的新模块,它提供了复杂事件处理(CEP, Complex Event Processin...

1639
来自专栏玄魂工作室

Python黑帽编程2.1 Python编程哲学

本节的内容有些趣味性,涉及到很多人为什么会选择Python,为什么会喜欢这门语言。我带大家膜拜下Python作者的Python之禅,然后再来了解下Python的...

2737
来自专栏飞总聊IT

大数据那些事(10):李逵麻子,李鬼坑人--BigTable的数据模型

今天我们回归技术路线,讲讲Google三驾马车里的BigTable。以前有个说法叫做麻子不叫麻子,叫坑人。取其原意是满脸是坑的人,谐音表示人被坑了。我们知道水浒...

25810
来自专栏JavaQ

深入理解Spring系列之一:开篇

Spring经过大神们的构思、编码,日积月累而来,所以,对其代码的理解也不是一朝一夕就能快速完成的。源码学习是枯燥的,需要坚持!坚持!坚持!当然也需要技巧,第一...

3369
来自专栏数据结构与算法

1010. 邮寄包裹

1010. 邮寄包裹 (Standard IO) 时间限制: 1000 ms  空间限制: 262144 KB  具体限制  题目描述 某邮局对邮寄包裹有如下...

36011
来自专栏小红豆的数据分析

小蛇学python(9)matplotlib的基本使用

matplotlib作为python中可视化最经典的库,是个不得不学习的东西。尽管长江后浪推前浪,涌现出了很多更好的可视化库,比如Plotly。不过,它们几乎全...

1163
来自专栏杨建荣的学习笔记

生产环境sql语句调优实战第十篇(r3笔记第39天)

陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步...

3215

扫描关注云+社区