# # 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 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; };