输入fa和xE7;Scala.JS中JS库的ade
我正试图为我的图书馆写一个打印的外观,如下所示 我希望能够翻译的是如下所示的呼叫:输入fa和xE7;Scala.JS中JS库的ade,scala,scala.js,Scala,Scala.js,我正试图为我的图书馆写一个打印的外观,如下所示 我希望能够翻译的是如下所示的呼叫: var Polygon = require('paths-js/Polygon'); var polygon = Polygon({ points: [[1, 3], [2, 5], [3, 4], [2, 0]], closed: true }); 进入 但我不确定我需要做什么才能达到这一点 我所做的事情如下 type Point = (Number, Number) trait PolygonOpt
var Polygon = require('paths-js/Polygon');
var polygon = Polygon({
points: [[1, 3], [2, 5], [3, 4], [2, 0]],
closed: true
});
进入
但我不确定我需要做什么才能达到这一点
我所做的事情如下
type Point = (Number, Number)
trait PolygonOpt {
val points: Array[Point]
val closed: Boolean
}
@JSName("paths.Polygon")
object Polygon extends js.Object {
def apply(options: PolygonOpt): Shape = js.native
}
然后,我可以像这样调用它
class Opt extends PolygonOpt {
val points: Array[Point] = Array((1, 2), (3, 4), (5, 6))
val closed = true
}
val opts = new Opt
val poly = Polygon(opts)
我对此有一些疑问:
- 我正处在一个所有东西都可以编译的时刻,但最终的javascript在调用时失败。我认为这是因为我正在传递一个
的实例,而运行时需要一个javascript对象文本PolygonOpt
点的定义是否转换为包含两个组件的js数组
- 我希望能够重载
像Polygon.apply
,但是scala.js不允许我在def apply(points:Seq[Point],closed:Boolean):Shape
内部编写方法实现,因为它扩展了Polygon
js.Object
标记,将所有内容放在名称空间路径下(这就是我现在使用的)
哪一个更适合Scala.js包装器?首先,请确保阅读,包括。我想你已经这么做了,因为你已经有了一些合理的东西。但是,您应该特别注意那些表示Scala类型和JavaScript类型完全不相关的部分,除非明确提到
因此,Int
是一个合适的JS数字(在Int的范围内)。但是数组[点]
与JavaScript数组无关。一个元组2
(例如(1,3)
)甚至更不如此。因此:
点的定义是否转换为包含两个组件的js数组
不,不是。因此,JavaScript完全无法理解它。是的
更糟糕的是,PolygonOpt
,因为它不扩展js.Object
,在JavaScript中也是完全不透明的,这就解释了为什么不能看到点和关闭的字段
首先要做的是使用JavaScript可理解的类型(扩展js.Object
)准确地键入JSAPI。在这种情况下,它将如下所示:
type JSPoint = js.Array[Int] // or Double
trait PolygonOpts extends js.Object {
val points: js.Array[JSPoint] = js.native
val closed: Boolean = js.native
}
@JSName("paths.Polygon")
object Polygon extends js.Object {
def apply(options: PolygonOpt): Shape = js.native
}
现在,问题是创建PolygonOpts
的实例并不容易。有关此信息,请参阅:
最后,您可以通过隐式扩展公开您首先想要的Scala-esque API:
import js.JSConverters._
object PolygonImplicits {
implicit class PolygonObjOps(val self: Polygon.type) extends AnyVal {
def apply(points: List[(Int, Int)], closed: Boolean): Shape = {
val jsPoints =
for ((x, y) <- points.toJSArray)
yield js.Array(x, y)
Polygon(PolygonOpts(jsPoints, closed))
}
}
}
导入js.jsconverter_
对象多克隆implicits{
隐式类PolygonObjOps(val self:Polygon.type)扩展了AnyVal{
定义应用(点:列表[(Int,Int)],闭合:布尔):形状={
瓦尔jsPoints=
对于((x,y)非常感谢!这看起来像是一种非常常见的情况(将接受对象文字的函数转换为接受命名参数的函数)需要大量的样板文件…我想知道是否值得为此编写一个宏。不幸的是,我不能在名为apply的隐式扩展中有一个方法,因为它已经存在于原始对象上,并且编译器不寻找隐式转换。我可能会放弃使用PolygonOpts并公开更具scalasque的接口。不过,这有点不幸,因为从javascript端传递PolygonOpts
的实例会比较困难,但这种情况不应该经常发生
object PolygonOpts {
def apply(points: js.Array[JSPoint], closed: Boolean): PolygonOpts = {
js.Dynamic.literal(
points = points,
closed = closed
).asInstanceOf[PolygonOpts]
}
}
import js.JSConverters._
object PolygonImplicits {
implicit class PolygonObjOps(val self: Polygon.type) extends AnyVal {
def apply(points: List[(Int, Int)], closed: Boolean): Shape = {
val jsPoints =
for ((x, y) <- points.toJSArray)
yield js.Array(x, y)
Polygon(PolygonOpts(jsPoints, closed))
}
}
}