Im trying to determine how tall a line of text is, before its being drawn on a canvas. c.measure_text(text)
only returns the width, I’m unsure if there’s a hidden or programmatic way to determine the text height before its drawn
Anvil just exposes the HTML5 canvas to you, so doing searches on what other people do for the HTML5 canvas in determining the height of text will give you some things to try. It does seem to be a non-trivial problem that’s highly dependent on browsers supporting newer features of the canvas spec.
Funnily enough I do something close to this in another project, where I resize text to fit inside a div:
while document.getElementById('teamhome').scrollWidth > document.getElementById('teamhome').offsetWidth:
font_size = anvil.js.window.getComputedStyle(document.getElementById('teamhome')).getPropertyValue('font-size')
font_size = float(font_size[:-2]) - 0.5
document.getElementById('teamhome').style.fontSize = f'{font_size}px'
Edit (just for anyone that comes across this code snippet in the future): The scrollWidth
of an element/text is the width in pixels of an HTML element,including any width that spills outside the bounds of its parent. In my specific instance. I had no overflow hence letters being cut off. The offsetWidth
is what part of the element is visible within its parent (not including margin). My example here will check the width of the teamhome
element, then iterate the font-size
down by 0.5
in every iteration. This allows me to fit weird edge case strings inside a fixed size div (Australia has weird place names like Strathfieldsaye
which is super fun to fit inside a div normally designed for 6-12 characters)
I was mostly curious if there was a built in way to do it, or I was missing something. I’ll have a bit of a play with this
Yeah, that’s similar to what I saw a lot of people doing, calculating the height in hidden divs, rather than trying to involve the canvas, since the support for the extra metrics in measure_text
isn’t universal.
Long story short, I wanna have a Canvas that displays an image, then text can be dragged and resized around the image. I’ve got the text dragging working, but next will be trying to figure out the dynamic resizing. There are a couple examples floating around that are semi useful
class manage_scoreboard_overlays(manage_scoreboard_overlaysTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
self.dragging = False
self.img = URLMedia("_/theme/scoreboard.png")
self.w, self.h = anvil.image.get_dimensions(self.img)
self.text_w, self.text_h, self.text_x, self.text_y = 20, 20, 50, 50
def update(self):
c = self.canvas_1
c.clear_rect(0,0,c.get_width(),c.get_height())
c.line_width = 3
c.stroke_rect(0, 0, c.get_width(), c.get_height())
c.font = "36px montserrat"
self.text_w = c.measure_text('Home name')
width = self.text_w
font_size = 36
from math import ceil
self.text_h = ceil(len('Home name') * (width / font_size)/2)
c.draw_image(self.img, 0, 0, self.w/(self.w/c.get_width()), self.h/(self.h/c.get_height()))
c.fill_text("Home name", self.text_x, self.text_y)
def canvas_1_mouse_down(self, x, y, button, **event_args):
"""This method is called when a mouse button is pressed on this component"""
print(x, y)
if x >= self.text_x and x <= self.text_x + self.text_w:
print('x is okay')
if y >= self.text_y - self.text_h and y <= self.text_y:
print('y is okay')
self.dragging = True
def canvas_1_mouse_move(self, x, y, **event_args):
"""This method is called when the mouse cursor moves over this component"""
if self.dragging:
self.text_x = x
self.text_y = y
self.update()
def canvas_1_mouse_up(self, x, y, button, **event_args):
"""This method is called when a mouse button is released on this component"""
if self.dragging:
self.dragging = False
def form_show(self, **event_args):
"""This method is called when the form is shown on the page"""
self.update()
def canvas_1_show(self, **event_args):
"""This method is called when the Canvas is shown on the screen"""
self.update()