ython程序開發之簡單小程序實例
(9)利用Canvas繪制圖形和文字
一、項目功能
利用Tkinter組件中的Canvas繪制圖形和文字。
二、項目分析
要在窗體中繪制圖形和文字,需先導入Tkinter組件,然后用Canvas完成繪制。
三、程序源代碼
源碼截圖:
#!/usr/bin/python3.6
# -*- coding: GBK -*-
from tkinter import *
root = Tk()
root.title('繪制圖形與字體')
# 創建畫布,設置其背景色為白色
cv = Canvas(root,bg = 'white', width=500, height=300)
cv.pack(fill=BOTH, expand=YES)
# 創建一個正方形,設置填充色為藍色
cv.create_rectangle(10,10,50,50,fill='blue')
# 創建一個圓形,設置填充色為黑色
cv.create_oval(90, 10, 140, 50,fill='green')
# 創建一個扇形
coord = 300, 10, 180, 100
# 設置扇形的起始角度為30,弧度為120,設置填充色為綠色
cv.create_arc(coord, start=30, extent=120, fill="magenta")
# 在窗體指定位置中插入自定義圖片
mypic = PhotoImage(file="myball.gif")
cv.create_image(370, 35,image=mypic)
# 創建字體
columnFont = ('黑體', 15)
for i, st in enumerate(['大飛狼', '小面羊', '大美呂', '小孔容', '天屎好美']):
cv.create_text((10 + i * 100, 90),
text = st,
font = columnFont,
fill='red',
anchor = W,
justify = LEFT)
cv.pack()
root.mainloop()
top.mainloop()
四、代碼解釋
第一行為引用python版本,本實例為python3.6
第二行是程序編碼引用,因為在程序中包含有中文字符,所以必須引用GBK,否則就會報錯。
第七行至第三十三行為功能實現主體,每段代碼的具體功能可在代碼的注釋中查看。
五、運行
1、在新窗體中繪制圖形和字體
圖形的前三個分別是用Canvas的create_rectangle(繪制矩形)、create_oval(繪制圓形)、create_arc(繪制弧形)實現,第四個為插入的自制GIF圖片。
下一篇:《Python程序開發之簡單小程序實例(10)》
更多精彩內容將在以后的章節分享給朋友們,請添加好友至收藏,歡迎點贊并關注后期內容更新!
Canvas是一個矩形區域的畫布,可以用JavaScript在上面繪畫;
我們今天的目標是使用HTML5畫布技術制作一款拼圖小游戲,要求將圖像劃分為3*3的9塊方塊并打亂排序,用戶可以移動方塊拼成完整圖片。
效果如下所示:
<div id="container">
<!--頁面標題-->
<h3>HTML5畫布綜合項目之拼圖游戲</h3>
<!--水平線-->
<hr />
<!--游戲內容-->
<!--游戲時間-->
<div id="timeBox">
共計時間:<span id="time">00:00:00</span>
</div>
<!--游戲畫布-->
<canvas id="myCanvas" width="300" height="300" style="border:1px solid">
對不起,您的瀏覽器不支持HTML5畫布API。
</canvas>
<!--游戲按鈕-->
<div>
<button onclick="restartGame()">
重新開始
</button>
</div>
</div>
效果如下所示:
我們可以看到頁面的大致結構是已經顯現出來了,就是骨架已經搭建好了,現在我們要使用css強化樣式;
整體背景設置
body {
background-color: silver;/*設置頁面背景顏色為銀色*/
}
游戲界面樣式設置
#container {
background-color: white;
width: 600px;
margin: auto;
padding: 20px;
text-align: center;
box-shadow: 10px 10px 15px black;
}
游戲時間面板樣式設置
#timeBox {
margin: 10px 0;
font-size: 18px;
}
游戲按鈕樣式設置
button {
width: 200px;
height: 50px;
margin: 10px 0;
border: 0;
outline: none;
font-size: 25px;
font-weight: bold;
color: white;
background-color: lightcoral;
}
鼠標懸浮時的按鈕樣式設置
button:hover {
background-color: coral;
}
設置好界面整體樣式之后我們得到完整的界面,如下所示:
可以看到整體的靜態界面已經搭建出來了
目標對象的獲取
var c = document.getElementById('myCanvas'); //獲取畫布對象
var ctx = c.getContext('2d'); //獲取2D的context對象
聲明拼圖的圖片素材來源
var img = new Image();
img.src = "image/pintu.jpg";
img.onload = function() { //當圖片加載完畢時
generateNum(); //打亂拼圖的位置
drawCanvas(); //在畫布上繪制拼圖
}
定義初始方塊位置
var num = [[00, 01, 02], [10, 11, 12], [20, 21, 22]];
打亂拼圖的位置
function generateNum() { //循環50次進行拼圖打亂
for (var i = 0; i < 50; i++) {
//隨機抽取其中一個數據
var i1 = Math.round(Math.random() * 2);
var j1 = Math.round(Math.random() * 2);
//再隨機抽取其中一個數據
var i2 = Math.round(Math.random() * 2);
var j2 = Math.round(Math.random() * 2);
//對調它們的位置
var temp = num[i1][j1];
num[i1][j1] = num[i2][j2];
num[i2][j2] = temp;
}
}
繪制拼圖
自定義名稱的drawCanvas()方法用于在畫布上繪制亂序后的圖片;
function drawCanvas() {
//清空畫布
ctx.clearRect(0, 0, 300, 300);
//使用雙重for循環繪制3x3的拼圖
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (num[i][j] != 22) {
//獲取數值的十位數,即第幾行
var row = parseInt(num[i][j] / 10);
//獲取數組的個位數,即第幾列
var col = num[i][j] % 10;
//在畫布的相關位置上繪圖
ctx.drawImage(img, col * w, row * w, w, w, j * w, i * w, w, w); // w:300 / 3 = 100(小圖寬度)
}
}
}
}
如下所示:
監聽鼠標監聽事件
c.onmousedown = function(e) {
var bound = c.getBoundingClientRect(); //獲取畫布邊界
var x = e.pageX - bound.left; //獲取鼠標在畫布上的坐標位置(x,y)
var y = e.pageY - bound.top;
var row = parseInt(y / w); //將x和y換算成幾行幾列
var col = parseInt(x / w);
if (num[row][col] != 22) { //如果當前點擊的不是空白區域
detectBox(row, col); //移動點擊的方塊
drawCanvas(); //重新繪制畫布
var isWin = checkWin(); //檢查游戲是否成功
if (isWin) { //如果游戲成功
clearInterval(timer); //清除計時器
ctx.drawImage(img, 0, 0); //繪制完整圖片
ctx.font = "bold 68px serif"; //設置字體為加粗、68號字,serif
ctx.fillStyle = "red"; //設置填充色為紅色
ctx.fillText("游戲成功!", 20, 150); //顯示提示語句
}
}
}
點擊方塊移動
function detectBox(i, j) {
//如果點擊的方塊不在最上面一行
if (i > 0) {
//檢測空白區域是否在當前方塊的正上方
if (num[i-1][j] == 22) {
//交換空白區域與當前方塊的位置
num[i-1][j] = num[i][j];
num[i][j] = 22;
return;
}
}
//如果點擊的方塊不在最下面一行
if (i < 2) {
//檢測空白區域是否在當前方塊的正下方
if (num[i+1][j] == 22) {
//交換空白區域與當前方塊的位置
num[i+1][j] = num[i][j];
num[i][j] = 22;
return;
}
}
//如果點擊的方塊不在最左邊一列
if (j > 0) {
//檢測空白區域是否在當前方塊的左邊
if (num[i][j - 1] == 22) {
//交換空白區域與當前方塊的位置
num[i][j - 1] = num[i][j];
num[i][j] = 22;
return;
}
}
//如果點擊的方塊不在最右邊一列
if (j < 2) {
//檢測空白區域是否在當前方塊的右邊
if (num[i][j + 1] == 22) {
//交換空白區域與當前方塊的位置
num[i][j + 1] = num[i][j];
num[i][j] = 22;
return;
}
}
}
游戲成功判定與顯示效果的實現
function restartGame() {
clearInterval(timer); //清除計時器
s = 0; //時間清零
m = 0;
h = 0;
getCurrentTime(); //重新顯示時間
timer = setInterval("getCurrentTime()", 1000);
generateNum(); //重新打亂拼圖順序
drawCanvas(); //繪制拼圖
}
靜態效果如上所示,至于游戲成功這里伙計們可以自行操作;
本次案例我們使用HTML5的新特性canvas畫布標簽打造了簡單的9宮格拼圖游戲,總體來說沒有特別的復雜,主要是圖片的分割方塊移動事件的綁定,以及重新游戲的初始化操作,明確了游戲邏輯之后其實代碼的編寫其實不難。感興趣的小伙伴可以去嘗試一下。
說明:
=====
1.1 Toyplot是一個Python的交互式繪圖庫,可用于數據可視化、繪圖、文字,用各種形式展示。
1.2 為科學家和工程師們提供簡潔的界面。
1.3 可開發美麗的交互式動畫,以滿足電子出版和支持repoducibility的獨特功能。
1.4 創建最佳的數據圖形"out-of-the-box"。
2 準備:
=====
2.1 官網:
https://github.com/sandialabs/toyplot
https://toyplot.readthedocs.io/en/stable/
2.2 安裝:
pip install toyplot
#本機安裝
sudo pip3.8 install toyplot
#推薦國內源安裝
sudo pip3.8 install -i https://mirrors.aliyun.com/pypi/simple toyplot
2.3 環境:
華為筆記本電腦、深度deepin-linux操作系統、谷歌瀏覽器、python3.8和微軟vscode編輯器。
3 折線圖:
=======
3.1 本代碼:為注釋版
#line==折線圖
import toyplot as tp
x=['1','2','3','4','5','6']
#y=[31,22,55,41,66,17] #1組數據
y=[[31,22],[22,17],[55,34],[41,28],[66,43],[17,36]] #2組數據
canvas = tp.Canvas(width=300, height=300,) #方法一,畫布大小設置
#方法二:style=類似與css設置
#canvas = tp.Canvas("6in", "6in", style={"background-color":"pink"})
#坐標軸axes的標簽名
axes = canvas.cartesian(xlabel='序號',ylabel='data')
#線條顏色color設置
#mark = axes.plot(x, y,color='red') #1組顏色設置
mark = axes.plot(x, y,color=['red','green']) #1組顏色設置
#水平圖例==horizontal-legends
markers = [mark + tp.marker.create(shape="o") for mark in mark.markers]
axes.label.text = markers[0] + " dog " + markers[1] + " pig"
#瀏覽器自動打開,推薦這種
import toyplot.browser
tp.browser.show(canvas)
#生成pdf
#import toyplot.pdf
#tp.pdf.render(canvas, "/home/xgj/Desktop/toyplot/1-line.pdf")
#生成png圖片
#import toyplot.png
#tp.png.render(canvas, "/home/xgj/Desktop/toyplot/1-line.png")
#生成html
#import toyplot.html
#tp.html.render(canvas, "/home/xgj/Desktop/toyplot/1-line.html")
'''
#生成svg圖片
import toyplot.svg
svg = tp.svg.render(canvas)
svg.attrib["class"] = "MyCustomClass"
import xml.etree.ElementTree as xml
with open("/home/xgj/Desktop/toyplot/1-line.svg", "wb") as file:
file.write(xml.tostring(svg))
'''
3.2 上述代碼簡潔版:
#line==折線圖
import toyplot as tp
x=['1','2','3','4','5','6']
y=[[31,22],[22,17],[55,34],[41,28],[66,43],[17,36]] #2組數據
canvas = tp.Canvas(width=300, height=300,) #畫布大小設置
#坐標軸axes的標簽名
axes = canvas.cartesian(xlabel='序號',ylabel='data')
#線條顏色color設置
mark = axes.plot(x, y,color=['red','green'])
#水平圖例==horizontal-legends
markers = [mark + tp.marker.create(shape="o") for mark in mark.markers]
axes.label.text = markers[0] + " dog " + markers[1] + " pig"
#瀏覽器自動打開,推薦這種
import toyplot.browser
tp.browser.show(canvas)
3.3 操作和效果圖:
4 散點圖:
========
4.1 代碼:
import toyplot
canvas = toyplot.Canvas(width=500, height=500)
axes = canvas.cartesian()
m0 = axes.scatterplot([0, 1, 2], [0, 1, 2], size=25)
m1 = axes.text([0, 1, 2], [0, 1, 2], ["0", "55", "100"], color="red")
marks = []
for label in ["0", "55", "100"]:
marks.append(toyplot.marker.create(
shape="o",
label=label,
size=25,
))
m2 = axes.scatterplot([0, 1, 2], [1, 2, 3], marker=marks)
#瀏覽器自動打開,推薦這種
import toyplot.browser
toyplot.browser.show(canvas)
4.2 圖:
5 垂直堆砌柱狀圖:
==============
5.1 代碼:
#bars==垂直堆砌柱狀圖=vsbar
import toyplot as tp
x=['1','2','3','4','5','6']
#y=[31,22,55,41,66,17] #1組數據
y=[[31,22],[22,17],[55,34],[41,28],[66,43],[17,36]] #2組數據
canvas = tp.Canvas(width=300, height=300,) #方法一,畫布大小設置
#方法二:style=類似與css設置
#canvas = tp.Canvas("6in", "6in", style={"background-color":"pink"})
#坐標軸axes的標簽名
axes = canvas.cartesian(xlabel='序號',ylabel='data')
#線條顏色color設置,2組顏色設置
mark = axes.bars(x, y,color=['red','green'])
#水平圖例==horizontal-legends
markers = [mark + tp.marker.create(shape="o") for mark in mark.markers]
axes.label.text = markers[0] + " dog " + markers[1] + " pig"
#瀏覽器自動打開,推薦這種
import toyplot.browser
tp.browser.show(canvas)
5.2 圖:
6 顏色條:
=======
6.1 代碼:
#Color Scale
import numpy
import toyplot
colormap = toyplot.color.LinearMap(toyplot.color.Palette(), domain_min=0, domain_max=8)
canvas = toyplot.Canvas(width=400, height=100)
axis = canvas.color_scale(colormap, label="Color Scale", scale="linear")
axis.axis.ticks.locator = toyplot.locator.Extended(format="{:.1f}")
#瀏覽器自動打開,推薦這種
import toyplot.browser
toyplot.browser.show(canvas)
6.2 圖:
7 table-heperlinks:
==============
7.1 表格塊狀圖及鏈接和圖示文字。
7.2 代碼:
#table-heperlinks
import numpy
import toyplot
canvas, table = toyplot.table(rows=4, columns=4)
table.cells.grid.hlines[...] = "single"
table.cells.grid.vlines[...] = "single"
#填充顏色
table.cells.cell[1,1].style = {"fill":"crimson"}
#可以指定鏈接地址
table.cells.cell[1,1].hyperlink = "http://toyplot.readthedocs.io"
table.cells.cell[2,2].style = {"fill":"seagreen"}
#可以指定鏈接地址
table.cells.cell[2,2].hyperlink = "http://www.sandia.gov"
table.cells.cell[3,3].style = {"fill":"royalblue"}
table.cells.cell[3,3].title = "This is a cell!"
#瀏覽器自動打開,推薦這種
import toyplot.browser
toyplot.browser.show(canvas)
7.3 圖:
8 高級作圖之動態散點圖:
====================
8.1 代碼:
#散點動畫圖
import numpy
x = numpy.random.normal(size=100)
y = numpy.random.normal(size=len(x))
import toyplot
canvas = toyplot.Canvas(300, 300)
axes = canvas.cartesian()
mark = axes.scatterplot(x, y, size=10)
for frame in canvas.frames(len(x) + 1):
if frame.number == 0:
for i in range(len(x)):
frame.set_datum_style(mark, 0, i, style={"opacity":0.1})
else:
frame.set_datum_style(mark, 0, frame.number - 1, style={"opacity":1.0})
#保存為mp4
#toyplot.mp4.render(canvas, "/home/xgj/Desktop/toyplot/test.mp4", progress=progress)
#瀏覽器自動打開,推薦這種
import toyplot.browser
toyplot.browser.show(canvas)
8.2 效果圖:
===自己整理并分享出來===
喜歡的人,請點贊、關注、評論、轉發和收藏。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。