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() 就可以让对象被鼠标拖拽
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JavaScript 中的函数式编程:函数,组合和柯里化
- 如何设置一个生产级别的高可用etcd集群
- NVIDIA Jetson nano可以处理4K相机吗?来验证编码性能吧(中)
- House Of Lore原理学习
- 使用 rush 进行命令并行处理
- 老生常谈 Spring Aop 日志收集与处理做的工具包,贼好用?
- Kaggle金牌得主的Python数据挖掘框架,机器学习基本流程都讲清楚了
- Go by Example 中文版: 行过滤器
- Elasticsearch重要知识点 | 选举流程详解
- 妹妹问我:Dubbo集群容错负载均衡
- 系统内核溢出提权
- 201312-3 最大的矩形(Python)
- Kafka组消费之Rebalance机制
- Spring:没有人比我更懂Java对象的创建!
- 盘点 Github 上的高仿 app 项目