Python(Pyodide) 및 WebAssembly로 Dev의 오프라인 페이지 만들기 🦄💡✨

이 게시물에서 영감을 얻음:




Python을 사용해 보기로 결정했습니다.

오랫동안 하고 싶었던 WebAssembly를 작성하는 것은 이번이 처음입니다. 이를 위해 Pyodide 을 사용하고 있습니다.

시작하자



먼저 download Pyodide 파일을 추출하고 현재 디렉터리에 pyodide.js 파일을 복사합니다.

이제 server.py에 서버를 작성해 보겠습니다.

from http.server import BaseHTTPRequestHandler, HTTPServer


class HTTPRequestHandler(BaseHTTPRequestHandler):
    """Request handler class"""

    def do_GET(self):
        """Handler for GET requests."""

        # Send response status code
        self.send_response(200)

        # Send headers
        self.send_header("Cache-Control", "no-cache")

        if self.path.endswith(".wasm"):
            # Header to serve .wasm file
            self.send_header("Content-Type", "application/wasm")
        else:
            self.send_header("Content-Type", "text/html")

        self.end_headers()

        # Serve the file contents
        urlpath = self.path
        if urlpath == "/":
            urlpath = "/index.html"

        with open(f".{urlpath}", "rb") as f:
            content = f.read()

        self.wfile.write(content)


def main():
    print("starting server...")

    # Server settings
    server_address = ("localhost", 8080)
    httpd = HTTPServer(server_address, HTTPRequestHandler)

    print("running server...")
    httpd.serve_forever()


if __name__ == "__main__":
    main()

따라서 pyodide.js , server.py 가 됩니다.
index.html를 쓰자

<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
      <title>Python wasm</title>
   </head>
   <body>
      <script src="pyodide.js"></script>
      <div id="status">Initializing Python...</div>
      <canvas id="draw-here"></canvas>
      <style>
         .color {
         display: inline-block;
         width: 50px;
         height: 50px;
         border-radius: 50%;
         cursor: pointer;
         margin: 10px;
         }
      </style>
      <div id="colors" style="text-align:center"></div>
      <script>
        window.languagePluginUrl = "/pyodide.js";
        languagePluginLoader.then(() => {
          pyodide.runPython(` ! Python code goes here ! `)
        })
      </script>
   </body>
</html>


이제 캔버스용 Python 코드를 작성해 보겠습니다.

from js import document as doc

# Make the "Initializing Python" status disappear
doc.getElementById("status").innerHTML = ""

canvas = doc.getElementById("draw-here")

canvas.setAttribute("width", doc.body.clientWidth)
canvas.setAttribute("height", 300)
ctx = canvas.getContext("2d")
ctx.strokeStyle = "#F4908E"
ctx.lineJoin = "round"
ctx.lineWidth = 5

# Global variables
pen = False
lastPoint = (0, 0)


def onmousemove(e):
    global lastPoint

    if pen:
        newPoint = (e.offsetX, e.offsetY)
        ctx.beginPath()
        ctx.moveTo(lastPoint[0], lastPoint[1])
        ctx.lineTo(newPoint[0], newPoint[1])
        ctx.closePath()
        ctx.stroke()
        lastPoint = newPoint


def onmousedown(e):
    global pen, lastPoint
    pen = True
    lastPoint = (e.offsetX, e.offsetY)


def onmouseup(e):
    global pen
    pen = False


canvas.addEventListener("mousemove", onmousemove)
canvas.addEventListener("mousedown", onmousedown)
canvas.addEventListener("mouseup", onmouseup)

# Colors

div = doc.getElementById("colors")
colors = ["#F4908E", "#F2F097", "#88B0DC", "#F7B5D1", "#53C4AF", "#FDE38C"]

for c in colors:
    node = doc.createElement("div")
    node.setAttribute("class", "color")
    node.setAttribute("id", c)
    node.setAttribute("style", f"background-color: {c}")

    def setColor(e):
        ctx.strokeStyle = e.target.id

    node.addEventListener("click", setColor)
    div.appendChild(node)

이제 AJAX를 통해 이 코드를 텍스트로 가져오고 pyodide.runPython(code) 로 실행할 수 있습니다.

그러나 간단하게 하기 위해 코드를 index.html에 직접 붙여넣겠습니다.


따라서 최종 버전은 다음과 같습니다.

<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
      <title>Python wasm</title>
   </head>
   <body>
      <script src="pyodide.js"></script>
      <div id="status">Initializing Python...</div>
      <canvas id="draw-here"></canvas>
      <style>
         .color {
         display: inline-block;
         width: 50px;
         height: 50px;
         border-radius: 50%;
         cursor: pointer;
         margin: 10px;
         }
      </style>
      <div id="colors" style="text-align:center"></div>
      <script>
         window.languagePluginUrl = "/pyodide.js";
         languagePluginLoader.then(() => {
           pyodide.runPython(`
from js import document as doc

# Make the "Initializing Python" status disappear
doc.getElementById("status").innerHTML = ""

canvas = doc.getElementById("draw-here")

canvas.setAttribute("width", doc.body.clientWidth)
canvas.setAttribute("height", 300)
ctx = canvas.getContext("2d")
ctx.strokeStyle = "#F4908E"
ctx.lineJoin = "round"
ctx.lineWidth = 5

# Global variables
pen = False
lastPoint = (0, 0)


def onmousemove(e):
    global lastPoint

    if pen:
        newPoint = (e.offsetX, e.offsetY)
        ctx.beginPath()
        ctx.moveTo(lastPoint[0], lastPoint[1])
        ctx.lineTo(newPoint[0], newPoint[1])
        ctx.closePath()
        ctx.stroke()
        lastPoint = newPoint


def onmousedown(e):
    global pen, lastPoint
    pen = True
    lastPoint = (e.offsetX, e.offsetY)


def onmouseup(e):
    global pen
    pen = False


canvas.addEventListener("mousemove", onmousemove)
canvas.addEventListener("mousedown", onmousedown)
canvas.addEventListener("mouseup", onmouseup)

# Colors

div = doc.getElementById("colors")
colors = ["#F4908E", "#F2F097", "#88B0DC", "#F7B5D1", "#53C4AF", "#FDE38C"]

for c in colors:
    node = doc.createElement("div")
    node.setAttribute("class", "color")
    node.setAttribute("id", c)
    node.setAttribute("style", f"background-color: {c}")

    def setColor(e):
        ctx.strokeStyle = e.target.id

    node.addEventListener("click", setColor)
    div.appendChild(node)
           `)
         })
      </script>
   </body>
</html>


이제 python server.py로 웹 서버를 실행하고 http://localhost:8080을 열면 됩니다.

문제가 있는 경우 here is the full project .

좋은 웹페이지 즐겨찾기