Source canvas draw scales.nas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#
# canvas.draw library - scale module for speed tape etc.
# created 12/2018 by jsb
#
# The Scale class combines draw.marks* with text labels to create scales/gauges
# to build speed tape, compass etc.
var Scale = {
# see also canvas.draw.marksStyle
Style: {
new: func() {
var obj = {
parents: [Scale.Style, canvas.draw.marksStyle.new()],
orientation: "u",
spacing: 20, # spacing in pixel
label_interval: 1, # one txt every n marks
label_distance_abs: 0, # distance between ticks and text labels in px
label_distance_rel: 1.1, # distance in %mark_length
mark_color: [255,255,255,1],
label_color: [255,255,255,1],
fontsize: 16, # fontsize for labels
};
return obj;
},
# the 'draw direction' for a linear scale (up, down, left, right)
setOrientation: func(value) {
me.orientation = chr(string.tolower(value[0]));
if (me.orientation == "v") me.orientation = "d";
if (me.orientation == "h") me.orientation = "r";
return me;
},
setFontSize: func(value) {
me.fontsize = num(value) or 16;
return me;
},
setSpacing: func(value) {
me.spacing = num(value) or 10;
return me;
},
# draw one text label every <value> marks
setLabelInterval: func(value) {
me.label_interval = num(value) or 1;
return me;
},
# Distance of text label to mark in pixel (be careful when resizing).
# See also setLabelDistanceRel()
setLabelDistanceAbs: func(value) {
me.label_distance_abs = num(value) or 0;
return me;
},
# Distance of text label to mark in %mark_length (easy scaling).
setLabelDistanceRel: func(value) {
me.label_distance_rel = num(value) or 1.1;
return me;
},
# get alignment of text label for linear scales based on style params
getAlignmentString: func() {
if (me.orientation == "d") {
return (me.mark_offset < 0 ? "right" : "left")~"-center";
}
elsif (me.orientation == "u") {
return (me.mark_offset < 0 ? "right" : "left")~"-center";
}
elsif (me.orientation == "r") {
return "center-"~(me.mark_offset > 0 ? "top" : "bottom");
}
elsif (me.orientation == "l") {
return "center-"~(me.mark_offset > 0 ? "top" : "bottom");
}
else {
return "center-center";
}
},
},
};
# draw a scale on canvas group
# start first value of scale
# count number of values to draw
# increment value to add (can be negative)
Scale.draw = func(cgroup, start, count, increment, style=nil) {
if (style == nil) {
style = me.Style.new();
}
var label_count = count; #math.floor(math.abs(stop - start) / increment);
if (label_count < 2) {
return false;
}
var marks = canvas.draw.marksLinear(cgroup, style.orientation, label_count * style.label_interval, style.spacing, style);
marks.setStrokeLineWidth(style.mark_width);
var labels = cgroup.createChild("group", "labels")
.createChildren("text", label_count);
var length = style.spacing * style.mark_length;
var offset = style.mark_offset * length * style.label_distance_rel;
offset += (offset > 0) ? style.label_distance_abs : -style.label_distance_abs;
var alignment = style.getAlignmentString();
forindex (i; labels) {
var txt = sprintf("%d", start + i * increment);
var translation = i * style.spacing * style.label_interval;
labels[i]
.setText(txt)
.setAlignment(alignment)
.setFontSize(style.fontsize)
.setColor(style.label_color);
if (style.orientation == "d") {
labels[i].setTranslation(offset, translation);
}
elsif (style.orientation == "u") {
labels[i].setTranslation(offset, -translation);
}
elsif (style.orientation == "r") {
labels[i].setTranslation(translation, offset);
}
elsif (style.orientation == "l") {
labels[i].setTranslation(-translation, offset);
}
}
return cgroup;
};