Pharo10中Roassal3多折线图如何在线条末端添加水平标签
Pharo 10 Roassal3 多序列折线标签实现方案
问题说明
在Pharo 10中使用Roassal3做多序列折线可视化时,三类常规标签实现都存在明显缺陷:
- 直接使用
RSLegend生成的默认图例尺寸过大,会自动压缩绘图区适配画布 - 将
RSLabel绑定到折线markerEnd属性时,标签会跟随折线末端的倾斜角度旋转,无法保持水平 - 基于
RSYLabelDecoration实现的侧边标签偏移逻辑繁琐,显示效果达不到折线末端直连标签的预期 - 目前Roassal3官方文档尚未完善,没有对应场景的公开示例。
方案1:折线末端水平标签(推荐,匹配旧版Roassal展示效果)
markerEnd属性的设计逻辑就是跟随附着的路径端点旋转,所以直接给它传RSLabel必然会出现倾斜,不需要在这个属性上硬改。
正确的实现逻辑是等图表完成所有坐标映射(执行完build方法)后,直接读取每条折线终点的画布像素坐标,在该位置做微小偏移后添加独立的水平文本标签即可,标签不会受折线角度影响。
可直接运行的实现代码:
| chart dates values firstDate labels | chart := RSChart new. dates := (20 to: 1 by: -1) collect: [ :i | Date today subtractDays: i ]. firstDate := dates first. values := #( #(4.29 4.01 3.82 3.91 4.01 3.73 4.47 4.28 4.18 4.00 3.72 4.27 3.99 4.91 5.09 4.91 5.09 4.91 4.44 4.91) #(2.0 1.98 1.98 1.98 1.99 1.96 2.07 1.96 1.90 1.95 1.98 2.04 2.12 2.12 2.21 2.27 2.27 2.10 2.19 1.95) ). labels := #('series 1' 'series 2'). " 先绘制所有基础折线,不设置markerEnd " values with: labels do: [ :series :label | | plot | plot := RSLinePlot new. plot x: (dates collect: [ :date | date julianDayNumber - firstDate julianDayNumber ]) y: series. chart addPlot: plot. ]. chart addDecoration: (RSHorizontalTick new labelConversion: [ :value | Date julianDayNumber: firstDate julianDayNumber + value ]; useDiagonalLabel; yourself). chart addDecoration: RSVerticalTick new. chart ylabel: 'The values'. " 必须先完成build,此时所有折线的像素坐标才会计算完成 " chart build. " 遍历折线,在终点位置添加水平标签 " chart plots with: labels do: [ :plot :label | | endPoint lineColor textLabel | endPoint := plot points last. lineColor := chart colorFor: plot. textLabel := RSLabel new text: label; fontSize: 12; color: lineColor; " 右侧偏移3像素,垂直方向和终点对齐,避免和折线端点重叠 " position: (endPoint x + 3) @ endPoint y; yourself. chart canvas add: textLabel. ]. ^chart canvas open
如果出现标签和其他折线交叉的情况,可以给标签加一个同色描边的白色背景,或者微调垂直偏移量即可,调整成本远低于装饰器方案。
方案2:优化RSLegend布局避免压缩绘图区
如果更习惯传统图例的展示形式,不需要修改图例本身的样式,只要把图例设置为悬浮定位,就不会触发绘图区的自动收缩逻辑:
" 原有chart build逻辑不变,替换原来的legend初始化代码即可 " legend := RSLegend new. legend container: chart canvas. labels with: chart plots do: [ :text :plot | legend text: text withBoxColor: (chart colorFor: plot) ]. legend layout vertical. " 设置图例悬浮在画布右上角,不占用绘图区空间 " legend location outer; right; top; offset: 10@10. legend build.
可以根据实际需求把图例调整到左上、右下等任意位置,不会再出现压缩折线显示区域的问题。
内容的提问来源于stack exchange,提问作者Tony Weddle
相关产品推荐
相关产品推荐

