整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Python程序開發之簡單小程序實例(9)利用Canvas繪制圖形和文字

          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簡介

          1. canvas是HTML5提供的一種新標簽,雙標簽;
          2. HTML5 canvas標簽元素用于圖形的繪制,通過腳本 (通常是JavaScript)來完成;
          3. canvas標簽只是圖形容器,必須使用腳本來繪制圖形;

          Canvas是一個矩形區域的畫布,可以用JavaScript在上面繪畫;


          二、案例目標

          我們今天的目標是使用HTML5畫布技術制作一款拼圖小游戲,要求將圖像劃分為3*3的9塊方塊并打亂排序,用戶可以移動方塊拼成完整圖片。

          效果如下所示:


          三、程序流程

          3.1 HTML靜態頁面布局

          <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強化樣式;


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

          設置好界面整體樣式之后我們得到完整的界面,如下所示:

          可以看到整體的靜態界面已經搭建出來了


          3.3 js構建交互效果

          3.3.1 對象的獲取以及圖片的設置

          目標對象的獲取

          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(); //在畫布上繪制拼圖
          }

          3.3.2 初始化拼圖

          • 需要將素材圖片分割成3行3列的9個小方塊,并打亂順序放置在畫布上;
          • 為了在游戲過程中便于查找當前的區域該顯示圖片中的哪一個方塊,首先為原圖片上的9個小方塊區域進行編號;


          定義初始方塊位置

          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(小圖寬度)
                      }
                  }
              }
          }

          如下所示:

          3.3.3 事件綁定

          監聽鼠標監聽事件

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


          3.3.4 游戲計時

          • 自定義函數getCurrentTime()用于進行游戲計時;
          • function getCurrentTime() {
            s = parseInt(s);
            //將時分秒轉換為整數以便進行自增或賦值
            m = parseInt(m);
            h = parseInt(h);
            s++;
            //每秒變量s先自增1

            if (s == 60) {
            s = 0;
            //如果秒已經達到60,則歸0
            m++;
            //分鐘自增1
            }
            if (m == 60) {
            m = 0;
            //如果分鐘也達到60,則歸0
            h++;
            //小時自增1
            }


            //修改時分秒的顯示效果,使其保持兩位數
            if (s < 10)
            s = "0" + s;
            if (m < 10)
            m = "0" + m;
            if (h < 10)
            h = "0" + h;
            time.innerHTML = h + ":" + m + ":" + s;
            //將當前計時的時間顯示在頁面上
            }
          • 在JavaScript中使用setInterval()方法每隔1秒鐘調用getCurrentTime()方法一次,以實現更新效果;var timer = setInterval("getCurrentTime()", 1000);


          3.3.5 游戲成功與重新開始

          游戲成功判定與顯示效果的實現

          • 自定義函數checkWin()用于進行游戲成功判斷;
          function restartGame() {
              clearInterval(timer);  //清除計時器
              s = 0; //時間清零
              m = 0;
              h = 0;
              getCurrentTime();  //重新顯示時間
              timer = setInterval("getCurrentTime()", 1000);
           
              generateNum(); //重新打亂拼圖順序
              drawCanvas(); //繪制拼圖
              
          }
          • 如果成功則使用clearInterval()方法清除計時器。然后在畫布上繪制完整圖片,并使用fillText()方法繪制出“游戲成功”的文字圖樣;if (isWin) { //如果游戲成功
            clearInterval(timer);
            //清除計時器
            ctx.drawImage(img, 0, 0);
            //繪制完整圖片
            ctx.font = "bold 68px serif";
            //設置字體為加粗、68號字,serif
            ctx.fillStyle = "red";
            //設置填充色為紅色
            ctx.fillText("游戲成功!", 20, 150);
            //顯示提示語句
            }

          3.4 最終效果演示

          靜態效果如上所示,至于游戲成功這里伙計們可以自行操作;


          四、總結

          本次案例我們使用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 效果圖:

          ===自己整理并分享出來===

          喜歡的人,請點贊、關注、評論、轉發和收藏。


          主站蜘蛛池模板: 精品一区二区91| 亚洲熟女一区二区三区| aⅴ一区二区三区无卡无码| 精品一区二区三区AV天堂| 国产伦精品一区二区免费| 伊人久久精品无码av一区| 国产AV一区二区三区传媒| 国产美女一区二区三区| 冲田杏梨AV一区二区三区| 一区二区精品久久| 国产福利一区二区三区在线观看| 日韩精品一区二区三区中文3d | 搡老熟女老女人一区二区| 精品国产一区二区三区在线| 欧美成人aaa片一区国产精品| 97久久精品无码一区二区| 国产精品无码一区二区三区不卡 | 日韩精品一区二区三区中文精品| 国产一区二区三区免费| 熟女大屁股白浆一区二区| 亚洲综合一区二区精品久久| 国产精品美女一区二区三区 | 在线视频一区二区三区| 亚洲AV无码一区二区乱子伦 | 色妞色视频一区二区三区四区| 久久一区二区三区免费| 国产精品亚洲产品一区二区三区 | 国产经典一区二区三区蜜芽 | 色偷偷一区二区无码视频| 波多野结衣在线观看一区| 蜜桃传媒视频麻豆第一区| 日韩免费无码视频一区二区三区| 亚洲AV综合色一区二区三区| 精品爆乳一区二区三区无码av| 一色一伦一区二区三区| 国产一区二区三区免费看| 中文字幕无码一区二区免费| 亚洲AV无码一区二区三区系列| 国产成人综合一区精品| 日韩一区二区三区视频久久| 亚洲AV无码一区二区三区DV|