找回密码
 加入天云!
搜索
查看: 70|回复: 2

通过.svg生成python turtle代码

[复制链接]

66

主题

103

回帖

1058

积分

中级会员

积分
1058
Elan 发表于 2025-2-22 17:12:12 | 显示全部楼层 |阅读模式
原理:解析svg标签并且输出对应代码
用途:糊弄作业doge
目前仅支持circle,rect,line块的解析。
import turtleimport xml.etree.ElementTree as ETprint('自动输出svg转python_turtle脚本(©Elan_x)\n'      'import turtle') def draw_svg(svg_file):    # 创建turtle画布    screen = turtle.Screen()    screen.setup(800, 600)    screen.bgcolor("white")     # 创建turtle对象    t = turtle.Turtle()    t.speed(0)  # 设置速度为最快,如果想要慢慢欣赏可以调节速度    print('''screen = turtle.Screen()screen.setup(800, 600)screen.bgcolor("white")t = turtle.Turtle()t.speed(0)    ''')    # 解析SVG文件    tree = ET.parse(svg_file)    root = tree.getroot()     # 绘制SVG元素    for element in root.iter():        tag = element.tag.split('}')[-1]        if tag == 'circle':            draw_circle(t, element.attrib)        elif tag == 'rect':            draw_rect(t, element.attrib)        elif tag == 'line':            draw_line(t, element.attrib)            # 可以继续添加其他元素的绘制函数     # 隐藏turtle并显示绘制结果    t.hideturtle()    turtle.done()    print('''t.hideturtle()turtle.done()     ''') def draw_circle(t, attribs):    cx = 0 - (float(attribs['cx']) - 400)    cy = 0 - (float(attribs['cy']) - 300)    r = float(attribs['r'])    t.penup()    t.goto(cx, cy)    t.pendown()    t.circle(r)    print(f'''t.penup()t.goto({cx}, {cy})t.pendown()t.circle({r})    ''')  def draw_rect(t, attribs):    x = float(attribs['x']) - 400    y = 0 - (float(attribs['y']) - 300)    width = float(attribs['width'])    height = float(attribs['height'])    t.penup()    t.goto(x, y)    t.pendown()    for _ in range(2):        t.forward(width)        t.right(90)        t.forward(height)        t.right(90)    print(f'''t.penup()t.goto({x}, {y})t.pendown()for _ in range(2):    t.forward({width})    t.right(90)    t.forward({height})    t.right(90)    ''')  def draw_line(t, attrib):    x1 = float(attrib['x1']) - 400    y1 = 0 - (float(attrib['y1']) - 300)    x2 = float(attrib['x2']) - 400    y2 = 0 - (float(attrib['y2']) - 300)    t.penup()    t.goto(x1, y1)    t.pendown()    t.goto(x2, y2)    print(f'''t.penup()t.goto({x1}, {y1})t.pendown()t.goto({x2}, {y2})    ''') # 可以继续添加其他元素的绘制函数 if __name__ == "__main__":    svg_file = r"svg_path"    draw_svg(svg_file)    print('输出完毕')以上是py代码版本,绘制一个ELA成功,效果如下:import turtle screen = turtle.Screen()screen.setup(800, 600)screen.bgcolor("white") t = turtle.Turtle()t.speed(0) t.penup()t.goto(-264.0, 168.0)t.pendown()t.goto(-249.0, -82.0) t.penup()t.goto(-189.0, 167.0)t.pendown()t.goto(-261.0, 164.0) t.penup()t.goto(-178.0, 86.0)t.pendown()t.goto(-248.0, 61.0) t.penup()t.goto(-179.0, -38.0)t.pendown()t.goto(-245.0, -65.0) t.penup()t.goto(-134.0, 149.0)t.pendown()t.goto(-139.0, -42.0) t.penup()t.goto(-135.0, -60.0)t.pendown()t.goto(-78.0, -29.0) t.penup()t.goto(-20.0, 169.0)t.pendown()for _ in range(2):    t.forward(39.0)    t.right(90)    t.forward(301.0)    t.right(90) t.penup()t.goto(-23.0, 209.0)t.pendown()for _ in range(2):    t.forward(142.0)    t.right(90)    t.forward(37.0)    t.right(90) t.penup()t.goto(75.0, 155.0)t.pendown()for _ in range(2):    t.forward(41.0)    t.right(90)    t.forward(291.0)    t.right(90) t.penup()t.goto(28.0, 59.0)t.pendown()for _ in range(2):    t.forward(36.0)    t.right(90)    t.forward(46.0)    t.right(90) t.hideturtle()turtle.done()
我又依照原来的py代码部署到网页上(使用js进行改写),使得使用更为方便。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>SVG to Python Turtle Script Converter</title><style>  body {    font-family: Arial, sans-serif;    margin: 0;    padding: 0;    background-color: #f4f4f4;    display: flex;    justify-content: center;    align-items: center;    height: 100vh;  }  .container {    background-color: white;    border-radius: 8px;    box-shadow: 0 4px 8px rgba(0,0,0,0.1);    padding: 20px;    max-width: 800px;    width: 100%;  }  h1 {    color: #333;  }  form {    margin-top: 20px;  }  input[type="file"] {    display: block;    margin-bottom: 10px;    border: none;    padding: 10px 20px;    text-align: center;    text-decoration: none;    display: inline-block;    font-size: 16px;    margin: 10px 2px;    cursor: pointer;    border-radius: 4px;    transition: background-color 0.3s;  }  button {    background-color: #007BFF;    border: none;    color: white;    padding: 10px 20px;    text-align: center;    text-decoration: none;    display: inline-block;    font-size: 16px;    margin: 10px 2px;    cursor: pointer;    border-radius: 4px;    transition: background-color 0.3s;  }  button:hover {    background-color: #0056b3;  }  pre#output {    margin-top: 20px;    background-color: #f9f9f9;    border: 1px solid #ddd;    border-radius: 4px;    padding: 10px;    overflow-y: auto;    max-height: 300px;    white-space: pre-wrap;    word-wrap: break-word;  }</style></head><body><div class="container">  <h1>SVG 到 Python Turtle 脚本转换器</h1><br><font color='#b1b1b1'>Hi~ o(* ̄▽ ̄*)ブ这里是Elan研发的SVG 到 Python Turtle 脚本转换器,可以将部分svg元素内容转写成turtle代码。可以使用例如:<a href='https://www.jyshare.com/more/svgeditor/'>菜鸟工具svg编辑器</a>之类的网页或软件。</font><br>  <form id="uploadForm" ><input type="file" id="svgFile" name="svgFile" accept=".svg" ><br>    <button type="submit">转换</button><button id='copy'>复制</button>  </form>  <pre id="output"></pre></div><script>document.getElementById('copy').addEventListener('click', async function() {  const output = document.getElementById('output');  try {    await navigator.clipboard.writeText(output.textContent);        document.getElementById('copy').textContent = '复制(ok)';  } catch (err) {    alert('无法复制文本: ' + err); } });document.getElementById('uploadForm').addEventListener('submit', function(event) {  event.preventDefault();        document.getElementById('copy').textContent = '复制';  const fileInput = document.getElementById('svgFile');  const file = fileInput.files[0];  if (!file) {    alert('请选择一个SVG文件!');        document.getElementById('copy').textContent = '复制';    return;  }  const reader = new FileReader();  reader.onload = function(e) {    const svgContent = e.target.result;    const pythonScript = convertSVGToTurtle(svgContent);    document.getElementById('output').textContent = pythonScript;  };  reader.onerror = function(e) {    alert('读取文件出错!');  };  reader.readAsText(file);});function convertSVGToTurtle(svgContent) {  const parser = new DOMParser();  const doc = parser.parseFromString(svgContent, 'image/svg+xml');  const root = doc.documentElement;  let pythonCode = "import turtle\n\n";  pythonCode += "screen = turtle.Screen()\nscreen.setup(800, 600)\nscreen.bgcolor(\"white\")\n";  pythonCode += "t = turtle.Turtle()\nt.speed(0)\n";  // 添加调试信息  console.log(root);  // 处理顶层的 <svg> 元素  pythonCode = handleElement(root, pythonCode);  pythonCode += "\nt.hideturtle()\nturtle.done()";  return pythonCode;}function handleElement(element, pythonCode) {  const tag = element.tagName.toLowerCase();  if (tag === 'svg' || tag === 'g') {    // 处理顶层的 <svg> 或 <g> 元素    for (const child of element.children) {      pythonCode = handleElement(child, pythonCode); // 追加结果并返回    }  } else if (tag === 'circle') {    pythonCode += generateCircleCode(element);  } else if (tag === 'rect') {    pythonCode += generateRectCode(element);  } else if (tag === 'line') {    pythonCode += generateLineCode(element);  } else {    // 如果是不支持的元素,则打印一条消息    console.warn(`Unsupported SVG element: ${tag}`);  }  return pythonCode; // 返回累加结果}function generateCircleCode(element) {  const cx = parseFloat(element.getAttribute('cx')) - 400;  const cy = -(parseFloat(element.getAttribute('cy')) - 300);  const r = parseFloat(element.getAttribute('r'));  return `\nt.penup()\nt.goto(${cx}, ${cy})\nt.pendown()\nt.circle(${r})\n`;}function generateRectCode(element) {  const x = parseFloat(element.getAttribute('x')) - 400;  const y = -(parseFloat(element.getAttribute('y')) - 300);  const width = parseFloat(element.getAttribute('width'));  const height = parseFloat(element.getAttribute('height'));  return `\nt.penup()\nt.goto(${x}, ${y})\nt.pendown()\nfor _ in range(2):\n    t.forward(${width})\n    t.right(90)\n    t.forward(${height})\n    t.right(90)\n`;}function generateLineCode(element) {  const x1 = parseFloat(element.getAttribute('x1')) - 400;  const y1 = -(parseFloat(element.getAttribute('y1')) - 300);  const x2 = parseFloat(element.getAttribute('x2')) - 400;  const y2 = -(parseFloat(element.getAttribute('y2')) - 300);  return `\nt.penup()\nt.goto(${x1}, ${y1})\nt.pendown()\nt.goto(${x2}, ${y2})\n`;}</script></body></html>
回复

使用道具 举报

21

主题

128

回帖

683

积分

中级会员

积分
683
Makotowa 发表于 2025-2-23 20:13:02 | 显示全部楼层


好厉害的样子 但是似乎不知道可以用于什么((

此外推荐楼主用代码标签把代码框起来 看着有点太乱了。。
回复

使用道具 举报

66

主题

103

回帖

1058

积分

中级会员

积分
1058
 楼主| Elan 发表于 2025-2-26 18:49:39 | 显示全部楼层
Makotowa 发表于 2025-2-23 20:13
好厉害的样子 但是似乎不知道可以用于什么((

此外推荐楼主用代码标签把代码框起来 看着有点太乱了。。 ...

确实,但是我是从我的知乎直接复制过来的,见在编辑模式下查看并没有异样便未在意,然鹅……

这个东西主要是用来应付作业的,可以直接生成turtle脚本。如果有兴趣画画,然后用编程炫技或者发文的也可以采用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入天云!

本版积分规则

Archiver|小黑屋|萌ICP备20250701号|天云社区

GMT+8, 2025-4-27 08:05 , Processed in 0.116742 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表