簡體   English   中英

在 Roassal3 中使用多個繪圖時如何在行尾添加水平線標簽

[英]How to add horizontal line labels at end of line when using multiple plots in Roassal3

我正在嘗試使用 Pharo 10 中的 Roassal3 來可視化多個系列的數據。 我已經成功地繪制了圖表,但想要標記線條。 我嘗試使用 RSLegend 來顯示帶有相應顏色框(對應於線條顏色)的文本,但它們會顯得太大,最終會縮小圖形以適應畫布。 如果我可以操縱圖例以不同的方式顯示,那將有所幫助,但我記得看到過一個示例,使用的是 Roassal 的早期版本,它在行尾為每一行顯示一個標簽。 這將是理想的,所以我嘗試添加一個 RSLabel 作為繪圖的 markerEnd。 除了標簽都以不同的角度出現(大概是情節線的角度,最后)之外,這很有效。 如何讓結束標記標簽水平顯示? Roassal3 的文檔仍在進行中,所以我找不到任何示例。

我已經更新了示例代碼,以展示我對結束標記、圖例和裝飾器的嘗試(沒有一個是理想的,但我可以使用裝飾器):

| chart plot dates values firstDate labels legend offset plotLabel renderedLabel canvasCopy |
chart := RSChart new.
canvasCopy := chart canvas copy.
dates := (20 to: 1 by: -1) collect: [ :i | Date today subtractDays: i ]. 
firstDate := dates first.
offset := 20 @ -50.
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').
values with: labels do: [ :series :label | 
   plot := RSLinePlot new markerEnd: (RSLabel new text: label).
   plot 
       x: (dates collect: [ :date | date julianDayNumber - firstDate julianDayNumber ])
       y: series.
   chart addPlot: plot.
    plotLabel := RSYLabelDecoration new right; 
        title: '~' , label;
        fontSize: 12;
        rotationAngle: 90;
        color: (chart colorFor: plot);
        offset: offset;
        yourself.
    chart addDecoration: plotLabel.
    renderedLabel := (plotLabel copy renderIn: canvasCopy) label.
    offset := (0 - renderedLabel textWidth) @ (offset y + renderedLabel textHeight + 4). 
 ].
canvasCopy shapes copy do: [ :shape | canvasCopy removeShape: shape ].
chart addDecoration: (RSHorizontalTick new labelConversion: [ :value | 
    Date julianDayNumber: firstDate julianDayNumber + value ]; useDiagonalLabel; yourself).
chart addDecoration: RSVerticalTick new.
chart ylabel: 'The values'.
chart build.
legend := RSLegend new.
legend container: chart canvas.
labels with: chart plots do: [ :c : p |
    legend text: c withBoxColor: (chart colorFor: p) ].
legend layout horizontalCompactTree .
legend build.
^chart canvas open

根據 Alexandre Bergel 的提示,我現在有一種合理的方法可以在情節線的末尾繪制標簽。 出於興趣,我在下面的操場代碼中包含了三種識別情節線的方法,使用情節標簽的結尾,使用右側裝飾和使用更標准的圖例。 它在某些地方很亂,但可以通過將代碼移動到更合適的對象來清理很多。

| chart plot dates values firstDate labels legend offset plotLabel renderedLabel canvasCopy maxOffset |
chart := RSChart new.
canvasCopy := RSCanvas new.
dates := (10 to: 1 by: -1) collect: [ :i | Date today subtractDays: i ]. 
firstDate := dates first.
offset := 20 @ -50.
maxOffset := 0.
values := #(
    #(3.72 4.27 3.99 4.91 5.09 4.91 5.09 4.91 4.44 4.91)
    #(4.29 4.01 3.82 3.91 4.01 3.73 4.47 4.28 4.18 4.00)
    #(1.98 2.04 2.12 2.12 2.21 2.27 2.27 2.10 2.19 1.95)
    #(2.5 2.3 2.7 2.73 2.15 2.6 2.63 2.57 2.4 2.8)
    #(2.0 1.98 1.98 1.98 1.99 1.96 2.07 1.96 1.90 1.95)
    ).
labels := #('first series' 'second series' 'series number 4' 'the third series' 'a fifth series').
values with: labels do: [ :series :label | 
   plot := RSLinePlot new.
   plot 
       x: (dates collect: [ :date | date julianDayNumber - firstDate julianDayNumber ])
       y: series.
   chart addPlot: plot.
    "If adding a legend to the right, RSYLabel decoration is needed but with modified offsets to get them to lay out vertically."
    plotLabel := RSYLabelDecoration new right; 
        title: '~' , label;
        fontSize: 12;
        rotationAngle: 90;
        color: (chart colorFor: plot);
        offset: offset;
        yourself.
    chart addDecoration: plotLabel.
    renderedLabel := (plotLabel renderIn: canvasCopy) label.
    maxOffset := maxOffset max: renderedLabel textWidth.
    offset := (0 - maxOffset) @ (offset y + renderedLabel textHeight + 4).
 ].
canvasCopy := nil.
chart addDecoration: (RSHorizontalTick new labelConversion: [ :value | 
    Date julianDayNumber: firstDate julianDayNumber + value ]; useDiagonalLabel; yourself).
chart addDecoration: RSVerticalTick new.
"When adding labels at the end of the plot lines, the right hand line of the chart box will overlay the labels so alter the
spine to a polygon which only draws the x and y axes. "
spine := chart decorations
        detect: [ :d | d class == RSChartSpineDecoration ].
spine shape: (RSPolygon new points: {(0 @ 0). (0 @ 0). (0 @ (chart extent y)). (chart extent x @ (chart extent y)). (chart extent x @ (chart extent y)). (0 @ (chart extent y)) }; noPaint; withBorder; yourself).
chart ylabel: 'The values'.
chart build.
"To use standard legend under the chart"
legend := RSLegend new defaultLabel: (RSLabel new fontSize: 8; yourself).
legend container: chart canvas.
labels with: chart plots do: [ :c : p |
    legend text: c withShape: (RSPolygon new points: { 0 @ -2. 10 @ -2. 10 @ 2. 0 @ 2 }; color: (chart colorFor: p))
    ].
legend layout grid.
legend build.

rsLabels := Dictionary new: chart plots size.
chart plots with: labels do: [ :plot :label | rsLabels at: plot put: ((RSLabel text: label) fontSize: 5) ].
lastys := chart plots collect: [ :pl | 
    Association key: pl value: (pl yScale scale: pl yValues last) ].
lastys sort: [ :el1 :el2 | 
    el1 value = el2 value 
        "If the last y coordinate is the same for both plots, order by the second last y point (reverse ordering)"
        ifTrue: [ (el1 key yValues at: el1 key yValues size - 1) > (el2 key yValues at: el2 key yValues size - 1) ] 
        ifFalse: [ el1 value < el2 value ] ].
lastys withIndexDo: [ :lasty :index |
        numPlots := lastys size.
        plot := lasty key.
        label := rsLabels at: plot.
        label color: plot color.
        chart canvas add: label.
        yPoint := lasty value.
        textHeight := label textHeight.
        index < numPlots ifTrue: [ 
            "Reset the y point to be about textHeight away from the next one, if they are close"
            (diff := (yPoint - (lastys at: index + 1) value) abs) < textHeight 
                ifTrue: [ yPoint := yPoint - (textHeight / 2) + (diff / 2) ] ].
        index > 1 ifTrue: [ 
            "Reset the y point to be about textHeight away from the last one, if they are close"
            (diff := ((lastys at: index - 1) value - yPoint ) abs) < textHeight 
                ifTrue: [ yPoint := yPoint + (textHeight / 2) - (diff / 2) ] ].
        label translateTo: ((plot xScale scale: plot xValues last) + (label textWidth / 2) + 1) @ yPoint.
    ].
^chart canvas

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM