first commit

main
yumoqing 2021-12-28 10:48:22 +08:00
parent d76ba4c673
commit c273e4bb8a
31 changed files with 2370 additions and 0 deletions

View File

85
kivycharts/bar.py 100644
View File

@ -0,0 +1,85 @@
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle
from kivyblocks.colorcalc import *
from kivyblocks.charts.chart import Chart,ChartPart
class BarPart(ChartPart):
def __init__(self,widget,pos,size,color,data_offset):
self.widget = widget
self.pos = pos
self.size = size
self.color = color
self.data_offset = data_offset
def collide_point(self,x,y):
minx = self.widget.pos[0] + self.pos[0]
maxx = minx + self.size[0]
miny = self.widget.pos[1] + self.pos[1]
maxy = miny + self.size[1]
if minx <= x and x <= maxx and \
miny <= y and y <= maxy:
return True
return False
def draw(self):
with self.widget.canvas:
Color(*self.color)
Rectangle(pos=(self.widget.pos[0] + self.pos[0],
self.widget.pos[1] + self.pos[1]),
size = self.size)
def mark(self):
rcolor = reverseColor(self.color)
rcolor.append(0.8)
with self.widget.canvas.after:
Color(*reverseColor(self.color))
Rectangle(pos=(self.widget.pos[0] + self.pos[0],
self.widget.pos[1] + self.pos[1]),
size = self.size)
class Bar(Chart):
"""
a BAR class
"""
def __init__(self,**options):
"""
options={
width,
height,
title,
keyField,
valueField,
color1:
color2
data=[
{
name,
value,
},{
}
]
}
"""
self.data = None
super().__init__(**options)
def data2part(self):
data = self.data
kvs = [ [i[self.options['keyField']],i[self.options['valueField']]] for i in data ]
m = max([i[1] for i in kvs ])
cnt = len(kvs)
points = divide([0,0],[self.width,0],cnt)
color1='8833ee'
color2='ed8234'
colors = divideColor(color1,color2,cnt-1)
for i in range(cnt):
h = self.height * kvs[i][1] / m
c = colors[i]
part = BarPart(self,
points[i],
(points[i+1][0] - points[i][0],h),
colors[i],
i
)
self.chartparts.append(part)

View File

@ -0,0 +1,79 @@
from kivy.app import App
from kivy.graphics import Color, Rectangle
from kivy.uix.widget import Widget
from kivyblocks.colorcalc import toArrayColor
class ChartPart(object):
def __init__(self,pos,width,height):
self.pos = pos
self.width = width
self.height = height
def collide_point(self,x,y):
raise NotImplementedError
def draw(self):
raise NotImplementedError
def mark(self):
raise NotImplementedError
class Chart(Widget):
def __init__(self,**options):
super().__init__()
self.options = options
self.bg_color = toArrayColor(self.options.get('bg_color',[0.3,0.3,0.3,1]))
self.markpart = None
self.bind(size=self.onSize,pos=self.onSize)
self.register_event_type("on_press")
def unmark(self):
self.canvas.after.clear()
def getData(self):
url = self.options.get('url')
if url:
hc = App.get_running_app().hc
params = self.options.get('params',{})
d = hc.get(url,parms=param)
self.data = d.get('data',[])
else:
self.data = self.options.get('data',[])
self.chartparts = []
def on_touch_down(self,touch):
if touch.is_mouse_scrolling:
return False
if not self.collide_point(touch.x,touch.y):
return False
self.markpart = None
self.unmark()
for part in self.chartparts:
if part.collide_point(touch.x,touch.y):
self.markPart(part)
self.dispatch('on_press',self,self.data[part.data_offset])
return super(Chart, self).on_touch_down(touch)
def on_press(self,o,data):
print('data=',data)
def draw(self):
with self.canvas.before:
Color(*self.bg_color)
Rectangle(pos=self.pos,size=self.size)
self.canvas.clear()
for part in self.chartparts:
part.draw()
def markPart(self,part):
self.markpart = part
part.mark()
def onSize(self,o,v):
self.build()
def build(self):
self.getData()
self.data2part()
self.draw()

View File

@ -0,0 +1,81 @@
import math
import numpy as np
class Point(object):
def __init__(self, x=0, y=0):
super().__init__()
self.x = x
self.y = y
class Line(object): # 直线由两个点组成
def __init__(self, p1, p2):
if isinstance(p1,list) or isinstance(p1,tuple):
self.p1 = Point(*p1)
else:
self.p1 = p1
if isinstance(p2,list) or isinstance(p2,tuple):
self.p2 = Point(*p2)
else:
self.p2 = p2
def vector(self):
return self.p1.x - self.p2.x,self.p1.y - self.p2.y
def lenght(self):
return math.sqrt(pow((self.p1.x - self.p2.x), 2)
+ pow((self.p1.y - self.p2.y), 2))
def get_cross_angle(self, l):
# 向量a
arr_a = np.array(self.vector())
# 向量b
arr_b = np.array(l.vector())
cos_value = float(arr_a.dot(arr_b)) / (np.sqrt(arr_a.dot(arr_a)) \
* np.sqrt(arr_b.dot(arr_b)))
# 注意转成浮点数运算
return np.arccos(cos_value) * (180 / np.pi)
# 两个向量的夹角的角度,
# 余弦值cos_value, np.cos(para),
# 其中para是弧度不是角度
class EllipseUtils(object):
def __init__(self,pos,size):
self.pos = Point(pos)
self.size = size
self.slides = []
super().__init__()
def split(self,data,colors):
self.slides = []
kvs = [ [i[self.options['keyField']],i[self.options['valueField']]] for i in data ]
total = sum([i[1] for i in kvs ])
start_degree = 0
cnt = len(kvs)
for i in range(cnt):
degree = start_degree + 360 * kvs[i][1] / total
self.slides.append((degress,colors[i]))
start_degree = degree
def isInside(self,a,b,x,y):
if a>b:
return x**x / a**a + y**y/b**b <= 1
return x**x / b**b + y**y / a**a <= 1
def collide_point(self,x,y):
a = float(self.size[0] / 2)
b = float(self.size[1] / 2)
x = x - self.pos[0]
y = y - self.pos[1]
if not self.isInside(a,b,x,y):
return -1
start_degress = 0
l = Line((a,b),(a,b*2))
l1 = Line((a,b),(x,y))
degress = l.get_cross_angle(l1)
if x < a:
degress = 360 - degress
for i in range(len(self.slides)):
if start_degress <= degress and degress < self.slides[i][0]:
return i
start_degress += self.slides[i][0]
return -1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
__version__ = '0.4.1.dev0'

View File

@ -0,0 +1,13 @@
# arc.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.r number 0 半径
opts.shape.startAngle number 0 起始弧度
opts.shape.endAngle number Math.PI * 2 终止弧度
opts.shape.clockwise boolean true 顺时针方向
"""

View File

@ -0,0 +1,14 @@
# briercurve.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.x1 number 0 起始点横坐标
opts.shape.y1 number 0 起始点纵坐标
opts.shape.x2 number 0 终止点横坐标
opts.shape.y2 number 0 终止点纵坐标
opts.shape.cpx1 number 0 控制点横坐标
opts.shape.cpy1 number 0 控制点纵坐标
opts.shape.percent number 1 已显示的百分比用于绘制动画
"""

View File

@ -0,0 +1,10 @@
# circle.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.r number 0 半径
"""

View File

@ -0,0 +1,7 @@
# compoundpath.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape.paths Path[] null 路径数组
"""

View File

@ -0,0 +1,5 @@
# displayable.py
"""
base class for all the plot class
"""

View File

@ -0,0 +1,11 @@
# droplet.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.width number 0 宽度
opts.shape.height number 0 高度
"""

View File

@ -0,0 +1,11 @@
# ellipse.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.rx number 0 横向半径
opts.shape.ry number 0 纵向半径
"""

View File

@ -0,0 +1,11 @@
# heart.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.width number 0 宽度
opts.shape.height number 0 高度
"""

View File

@ -0,0 +1,12 @@
# image.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.style Object 样式
opts.style.image string|HTMLImageElement|HTMLCanvasElement 图片的内容可以是图片的 URL也可以是 dataURI
opts.style.x number 图片左上角相对于父节点的横坐标
opts.style.y number 图片左上角相对于父节点的纵坐标
opts.style.width number 图片宽度
opts.style.height number 图片高度
"""

View File

@ -0,0 +1,12 @@
# line.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.x1 number 0 起始点横坐标
opts.shape.y1 number 0 起始点纵坐标
opts.shape.x2 number 0 终止点横坐标
opts.shape.y2 number 0 终止点纵坐标
opts.shape.percent number 1 已显示的百分比用于绘制动画
"""

View File

@ -0,0 +1,10 @@
# lsogon.py
"""
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.x number 0 圆心横坐标
opts.shape.y number 0 圆心纵坐标
opts.shape.r number 0 半径
opts.shape.n number 0 边数
"""

View File

@ -0,0 +1,14 @@
# path.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
"""
"""
path.extend
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.type string 类型自定义的名称
opts.init Function 初始化时调用的函数
opts.buildPath Function 如何构建 Path 的函数在绘制时候会调用
"""

View File

@ -0,0 +1,10 @@
# polygon.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.points number[][] 0 每个元素是一个横纵坐标的数组
opts.shape.smooth number|string 0 圆滑程度取值范围为 0 1 之间的数字0 表示不圆滑也可以是特殊字符串 'spline' 表示用 Catmull-Rom spline 插值算法否则默认用贝塞尔曲线插值算法
opts.shape.smoothConstraint number[][] 0 将计算出来的控制点约束在一个包围盒内比如 [[0, 0], [100, 100]]这个包围盒会与整个折线的包围盒做一个并集用来约束控制点
"""

View File

@ -0,0 +1,10 @@
# polyline.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.points number[][] 0 每个元素是一个横纵坐标的数组
opts.shape.smooth number|string 0 圆滑程度取值范围为 0 1 之间的数字0 表示不圆滑也可以是特殊字符串 'spline' 表示用 Catmull-Rom spline 插值算法否则默认用贝塞尔曲线插值算法
opts.shape.smoothConstraint number[][] 0 将计算出来的控制点约束在一个包围盒内比如 [[0, 0], [100, 100]]这个包围盒会与整个折线的包围盒做一个并集用来约束控制点
"""

View File

@ -0,0 +1,12 @@
# rectangle.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.r number|number[] 0 用于创建圆角矩形左上右上右下左下角的半径依次为 r1 r2 r3 r4r 缩写为 1 相当于 [1, 1, 1, 1]r 缩写为 [1] 相当于 [1, 1, 1, 1]r 缩写为 [1, 2] 相当于 [1, 2, 1, 2]r 缩写为 [1, 2, 3] 相当于 [1, 2, 3, 2]
opts.shape.x number 0 左上角的横坐标
opts.shape.y number 0 左上角的纵坐标
opts.shape.width number 0 宽度
opts.shape.height number 0 高度
"""

View File

@ -0,0 +1,12 @@
# rose.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.r number[] [] 半径
opts.shape.k number 0 玫瑰线参数参见 wiki
opts.shape.n number 1 花瓣数
"""

View File

@ -0,0 +1,14 @@
# sector.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.r number 0 半径
opts.shape.r0 number 0 内半径
opts.shape.startAngle number 0 起始弧度
opts.shape.endAngle number Math.PI * 2 终止弧度
opts.shape.clockwise boolean true 顺时针方向
"""

View File

@ -0,0 +1,13 @@
# star.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.n number 3 瓣数 n 等于 5 是我们熟悉的五角星
opts.shape.r number 0 半径
opts.shape.r0 number 0 内半径
"""

View File

@ -0,0 +1,6 @@
import pytest
def test_flower():
from kivy_garden.graph import Graph
widget = Graph()

View File

@ -0,0 +1,9 @@
# text.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
?text
font_size
?
"""

View File

@ -0,0 +1,12 @@
# touchoid.py
"""
名称 类型 默认值 描述
opts Object 配置项继承得到的配置项参见 zrender.Displayable
opts.shape Object 形状属性
opts.shape.cx number 0 圆心横坐标
opts.shape.cy number 0 圆心纵坐标
opts.shape.r number 0 半径
opts.shape.r0 number 0 内半径
opts.shape.d number 0 内外旋轮曲线参数参见 wiki
opts.shape.n location 'out' out in表示曲线在内部还是外部
"""

66
kivycharts/pie.py 100644
View File

@ -0,0 +1,66 @@
import math
import numpy as np
from kivy.uix.widget import Widget
from kivyblocks.charts.geometry import EllipseUtils
class PiePart(ChartPart):
def collide_point(self,x,y):
if not self.isInSideEllipse(x,y):
return False
return self.isInSidePart(x,y)
def isInSideEllipse(self,x,y):
a = self.width / 2
b = self.height / 2
v = x ** x / a ** a + y**y / b ** b
if v <= 1:
return True
return False
class Pie(Widget):
def __init__(self,**options):
"""
options={
width,
height,
title,
keyField,
valueField,
data=[
{
name,
value,
},{
}
]
}
"""
self.options = options
self.initflag = False
super().__init__()
self.bind(size=self.onSize,pos=self.onSize)
def data2pie(self):
data = self.options.get('data',[])
kvs = [ [i[self.options['keyField']],i[self.options['valueField']]] for i in data ]
total = sum([i[1] for i in kvs ])
start_degree = 0
cnt = len(kvs)
color1='8833ee'
color2='ed8234'
colors = divideColor(color1,color2,cnt-1)
self.canvas.clear()
for i in range(cnt):
degree = start_degree + 360 * kvs[i][1] / total
with self.canvas:
Color(*colors[i])
Ellipse(pos=self.pos,
size=self.size,
angle_start=start_degree,
angle_end= degree)
start_degree = degree
def onSize(self,o,v):
self.data2pie()

10
requirements.txt 100644
View File

@ -0,0 +1,10 @@
jinja2
kivy
ffpyplayer
qrcode
pillow
requests
plyer
python-osc
bs4
lxml

60
setup.py 100644
View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import codecs
from distutils.core import setup
from setuptools import setup, find_packages
from Cython.Build import cythonize
from version import version
# usage:
# python setup.py bdist_wininst generate a window executable file
# python setup.py bdist_egg generate a egg file
# Release information about eway
# version = "0.0.4"
description = "kivy charts is a tool to build kivy data plot"
author = "yumoqing"
email = "yumoqing@icloud.com"
depandent_packages = []
with codecs.open('./requirements.txt', 'r', 'utf-8') as f:
b = f.read()
depandent_packages = b.split(',')
packages=find_packages()
package_data = {
"kivyblocks":[
'imgs/*.png',
'imgs/*.atlas',
'imgs/*.gif',
'imgs/*.jpg',
'ttf/*.ttf',
'ui/*.uidesc',
],
}
setup(
name="kivycharts",
ext_modules=cythonize(
[
]),
version=version,
# uncomment the following lines if you fill them out in release.py
description=description,
author=author,
author_email=email,
install_requires=depandent_packages,
packages=packages,
package_data=package_data,
keywords = [
],
classifiers = [
'Development Status :: 3 - Alpha',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3.5',
'Topic :: Software Development :: Libraries :: Python Modules'
],
platforms= 'any'
)

1
version.py 100644
View File

@ -0,0 +1 @@
version = '0.0.5'