【发布时间】:2016-12-24 21:53:38
【问题描述】:
我已经定义了一个 D3 Dart JS 互操作,我用它来设置 D3 对象的值并调用它们,它运行良好。不幸的是,D3 对 setter 和 getter 使用相同的函数,并且取决于参数的数量来将它们分开。
例如,Arc 对象可以像这样(在 JavaScript 中)设置和获取 InnerRadius:
var arc = d3.arc().innerRadius(25);
//arc with innerRadius of 25
var radius = arc.innerRadius();
//radius is 25
我定义的 Dart 包装器如下所示:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external Arc();
}
我想定义一个这样的包装器:
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external num innerRadius();
external Arc();
}
但它抱怨名称已经被定义。如何定义 dart 包装器,以便在输入值的同时设置和调用值?
D3 定义了这样的 Arc:
function arcInnerRadius(d) {
return d.innerRadius;
}
function constant$1(x) {
return function constant() {
return x;
}
}
function arc() {
var innerRadius = arcInnerRadius;
function arc() {
var r0 = +innerRadius.apply(this, arguments);
//calculate and return path
}
arc.innerRadius = function(_) {
if(arguments.length) {
if(_ === "function") {
innerRadius = _;
} else {
innerRadius = constant$1(+_);
}
return arc;
}
return innerRadius;
}
return arc;
}
因此,getter 和 setter 语法没有正确包装它。由于设置 innerRadius 设置的是代码不调用的函数,而不是内部值。
有一个丑陋的解决方案,如果你放弃输入并将参数设为可选,它允许你同时做这两个。所以我目前的解决方案是像这样定义包装器:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc();
external innerRadius([num innerRadius]);
}
这允许你这样称呼它:
Arc arc = new Arc()
..innerRadius(25);
num radius = arc.innerRadius();
这可行,但缺点是我们失去了一些键入的价值,我无法键入强制半径为数字。也就是说,这同样有效:
Point<num> radius = arc.innerRadius();
它直到运行时才会爆炸。
所以这与它正在映射的函数匹配并且它可以工作,但我真正想要的是能够使用类型来完成它,从而定义一个可以返回相同类型的同名函数。
【问题讨论】:
标签: d3.js dart dart-js-interop