我正在编写一个 HTML5 图表应用程序,使用 qooxdoo 作为对象系统和小部件工具包,并将 RaphaelJS 作为绘图后端。图表的数据模型包含高级对象,如 Item、Line 等;这些被实现为具有位置、尺寸、颜色和其他数据属性的 qooxdoo 类。每个类都能够将其实例呈现给 Raphael 论文,例如,使用 render() 方法。此时,创建了一个视觉(拉斐尔术语中的“元素”)。
问题是,应该在创建 Raphael 视觉对象之前设置一些属性。在 Raphael 中,如果不提供圆心坐标和半径,则无法绘制圆;没有路径定义就无法创建路径;您无法创建没有实际文本的文本标签,依此类推。此外,某些属性只能在创建视觉对象后设置:您不能为不存在的视觉对象设置颜色、笔触样式等。所以我们可以想象以下工作流程:
var circle = new my.Circle();
circle.set({ x: 10, y: 20, r: 30 }); // can't set color here - no visual yet
circle.render(paper);
circle.set({ stroke: "red", strokeWidth: 5 });
好的,如果我们手动创建对象,我们可以控制这个工作流程。但是,如果整个场景图从 JSON 中解组(以加载保存的图),则无法控制调用顺序,并且所有属性都将立即设置。members
这就是为什么我的 Circle 类在其部分中包含以下内容:
// Setter for stroke
_applyStroke: function(val, old) {
this.element && this.element.attr({ stroke: val });
}
// The same for fill, stroke width, stroke style, arrowhead style etc.
// ...
render: function(paper) {
this.element = paper.circle(this.getX(), this.getY(), this.getR());
this._applyStroke(this.getStroke());
this._applyStrokeWidth(this.getStrokeWidth());
// repeat for each style property
}
有没有什么方法可以减少样板?我正在考虑创建虚拟 Raphael“元素”以在创建实际元素之前接受样式属性,并在创建后将虚拟属性提交给实际元素。但是这种方法似乎需要对现有代码进行许多更改。我想知道是否有更优雅的方式来实现这一点?基于 AOP 的解决方案是可以接受的,因为 AOP 在 qooxdoo 中运行良好。