import math
import browser.html as html
import browser.svg as svg
colors = ["C8E0A2", "A6BED1", "E4CC85", "D7D7D7", "90AF97", "698EA8",
"BFA166", "A8ADB0", "FF6600"]
def pie_chart(container, data, title="Chart"):
svg_container = html.SVG(xmlns="http://www.w3.org/2000/svg",
width="500",
height="300")
svg_container.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink")
panel = svg.g(Id="panel")
title = svg.text(title, x=150, y=25,
font_size=22, text_anchor="middle",
style={"stroke":"black"})
svg_container <= title + panel
container <= svg_container
# zone for legend
legend = svg.text(x=350, y=150,
font_size=20, text_anchor="middle",
style={"stroke":"black"})
panel <= legend
ray = 100
paths = {}
width = 3.8*ray
height = 2.2*ray
x_center = int(int(svg_container.width) / 2)
y_center = int(int(svg_container.height) / 2)
x = x_center
y = y_center-ray
total = sum(data.values())
items = list(data.items())
cumul = 0
for i,(key,value) in enumerate(items):
angle1 = 2 * math.pi * cumul
cumul += float(value) / total
angle = 2 * math.pi * cumul
angle_mid = (angle + angle1) / 2
x_end = x_center + ray * math.cos((math.pi / 2) - angle)
y_end = y_center - ray * math.sin((math.pi / 2) - angle)
x_mid = x_center + ray * math.cos((math.pi / 2) - angle_mid)
y_mid = y_center - ray * math.sin((math.pi / 2) - angle_mid)
path = "M%s,%s " %(x_center, y_center)
path += "L%s,%s " %(int(x), int(y))
if angle - angle1 <= math.pi:
path += "A%s,%s 0 0,1 " %(ray, ray)
else:
path += "A%s,%s 0 1,1 " %(ray, ray)
path += "%s,%s z" %(int(x_end), int(y_end))
print(x, y, x_end, y_end)
x, y = x_end, y_end
color = colors[i % len(colors)]
# draw circle arc
path = svg.path(d=path, style=dict(fill='#'+color), Class="pie")
path.bind('mouseover',lambda ev,path=path:highlight(path))
path.bind('mouseout',lambda ev:hide_legend)
panel <= path
# draw line to rect
# start is the middle of the circle arc
# end is the homothety of start from circle center
k = 1.2
x2 = k * x_mid + (1 - k) * x_center
y2 = k * y_mid + (1 - k) * y_center
line = svg.line(x1=x_mid, y1=y_mid, x2=x2, y2=y2, stroke="#666")
panel <= line
x3 = x2 + (x2 - x_mid)
y3 = y2 + (y2 - y_mid)
# add label
text = svg.text("{}: {}".format(key, value), x=x3, y=y3,
Class="tag")
panel <= text
bbox = text.getBBox()
w = bbox.width
if bbox.x < x_mid and bbox.x + w > x2:
text.x = x2 - w
paths[key] = path
def set_title(*args):
title.text = title_input.value
def highlight(path):
pass
def show_legend(key):
legend.text = key
def hide_legend(ev):
legend.text = ''
def change(rank,offset):
x = int(cells[int(rank)].text)
if x+int(offset)>=0:
cells[int(rank)].text = x+int(offset)
pie_chart()