Files
endorphin-tessera-gui/examples/source-hit.endor
T

37 lines
2.4 KiB
Plaintext

// 自定义形状命中:对象原始矩形宽 160,但 paint 只画左侧直径 80 的圆,hitTest 也只接受圆内。
// 圆外部分可落到父容器监听器;按下与释放须经相同合法目标复核。
// 扩展矩形的绘制、命中和事件方法,用同一个 hits 状态观察交互结果。
class CircleTarget: RectBlock {
// hits 由下面顶层 state 提供,源命中只读它所需的几何,计数写入留给 onEvent。
hits: Object
// point 已转换到该出现位置局部坐标;使用圆心(40,40)、半径40,而不是整个 160x80 外框。
function hitTest(self: CircleTarget, mount: Mount, point: Point): Bool {
// source_hit 在候选出现的命中阶段调用,point 已转换为局部坐标,不应再减 geometry.x/y。
return point.inCircle(40, 40, 40)
}
// 把原生命令宽度缩为 80、圆角半径设为 40,得到与 hitTest 对应的圆形区域。
function paint(self: CircleTarget, mount: Mount, geometry: Bounds): DisplayList {
// source_paint 调用此覆盖;修改新生成的第一条矩形命令,不把共享对象的原生 width 从 160 改成 80。
drawing = RectBlock.paint(self, mount, geometry)
drawing.commands.at(0).width = 80
drawing.commands.at(0).radius = 40
return drawing
}
// 圆内点击递增自身计数并停止向祖先传播;父容器不会为同一次点击再递增。
function onEvent(self: CircleTarget, event: Event): Unit {
// 此示例的点击分发选中圆后调用对象方法;stopPropagation 只阻止后续祖先组,不撤销已经执行的捕获处理。
self.hits.increment()
event.stopPropagation()
}
}
hits = ui.state(0)
// 父监听器单独计数;它和圆形目标显示在同页,便于比较穿过透明区的输入。
background = ui.state(0)
circle = CircleTarget(160, 80, 0, "#237A45", hits)
// 布局仍给 circle 原生的 160×80 盒,只有绘制和形状命中缩成左侧圆;透明右半部并非不存在的布局区域。
root = Column(24, 16, circle, TextBlock("点击圆内计入圆;透明右半区域交给父容器"), TextBlock("圆内点击"), ui.textOf(hits, "value"), TextBlock("父容器点击"), ui.textOf(background, "value"))
// 订阅在父 Column 上,圆外有效区域可回退到父目标;源命中只读检查不执行这些业务回调。
connection = root.on("click", background.increment)
page = Page()
page.render(root)