【Godot4.2】MLTag类:HTML、XML通用标签类

news2024/11/13 16:04:04

概述

HTML和XML采用类似的标签形式。

之前在Godot中以函数库形式实现了网页标签和内容生成。能用,但是缺点也很明显。函数之间没有从属关系,但是多有依赖,而且没有划分出各种对象和类型。

如果以完全的面向对象形式来设计标签类或者元素类,将可以更贴近HTML或XML的本来面目。也更容易生成。

整体思路是设计如下的类继承结构:
在这里插入图片描述

实现之后,将可以充分的定义和生成HTML、XML和SVG标签,并用于内容生成或文档解析。

通用标签类

因为HTML和XML标签的语法格式和要素是类似的,因此可以通过创建一个通用的标签类,来生成HTML或XML标签。

MLtag就是这个通用的标签类,它定义了几个核心的属性:

  • tag_name :标签名称
  • attrs:包含标签所有属性的字典
  • is_single:是否为单标签,默认为false
  • content :标签的子内容,可以直接赋值,也可以使用append()方法追加。单标签(is_singletrue)时被忽略
  • get_end_tag():获取结束标签,单标签时返回空字符串
  • append():追加当前标签的子内容,可以是字符串形式,也可以是SVG标签实例(会自动调用to_string()方法转化为字符串)
# =============================================
# 名称:MLtag
# 类型:类
# 描述:HTMLXML通用标签类,用于定义和生成HTMLXML标签字符串
# 作者:巽星石
# 创建时间:202471617:48:01
# 最后修改时间:202471622:27:53
# =============================================
class_name MLTag

# ====================== 属性 ======================
var tag_name = ""          # 标签名称
var attrs:Dictionary = {}  # 属性字典
var is_single = false      # 是否单标签
var content = ""           # 子内容  

# ====================== 方法 ======================
# 获取结束标签
func get_end_tag() -> String:
	return "" if is_single else "</%s>" % tag_name

# 追加子内容
func append(new_content) -> void:
	if new_content is String:
		content += "\n" + new_content
	else:
		content += "\n" + new_content.to_string()

# ====================== 虚函数 ======================
# 转化为字符串
func _to_string() -> String:
	var tag_str:String
	
	# 获取属性字典的字符串
	var attr = ""
	for key in attrs.keys():
		if attrs[key] != "":
			attr += "%s=\"%s\" " % [key,attrs[key]]
	tag_str = "<%s%s/>" % [tag_name," " + attr] if is_single else "<%s%s>%s</%s>" % [tag_name," " + attr,content,tag_name]
	return tag_str

测试:

@tool
extends EditorScript

func _run() -> void:
	var tag = MLTag.new()    # 创建一个标签
	tag.name = "a"           # 名称
	tag.attrs["id"] = "a1"   # 设定属性
	tag.attrs["href"] = "https://www.runoob.com/"
	tag.content = "菜鸟教程"
	
	print(tag)

默认是双标签,也就是带有起始标签和结束标签的标签对。

<a id="a1" href="https://www.runoob.com/" >菜鸟教程</a>

is_single设为true后,就被认为是单标签:

@tool
extends EditorScript

func _run() -> void:
	var tag = MLTag.new()    # 创建一个标签
	tag.name = "a"           # 名称
	tag.attrs["id"] = "a1"   # 设定属性
	tag.attrs["href"] = "1.com"
	tag.innerHTML = "hahah"
	tag.is_single = true     # 设为标签
	
	print(tag)

打印输出的结果也就变了:

<a id="a1" href="https://www.runoob.com/" />

可以看到没有了结束标签,子内容部分也自动省略。

HTML标签基类

# =============================================
# 名称:HTMLtag
# 类型:类
# 描述:HTML标签基类
# 作者:巽星石
# 创建时间:202471619:05:46
# 最后修改时间:202471619:29:34
# =============================================
class_name HTMLTag extends MLTag

# ====================== 属性 ======================
# ID
var id:String:
	set(val):
		attrs["id"] = val
	get:
		return attrs["id"]
# name
var name:String:
	set(val):
		attrs["name"] = val
	get:
		return attrs["name"]
# css类名
var className:String:
	set(val):
		attrs["class"] = val
	get:
		return attrs["class"]
# 行内CSS样式
var style:String:
	set(val):
		attrs["style"] = val
	get:
		return attrs["style"]
# ====================== 初始化 ======================
func _init() -> void:
	# HTML标签通用属性
	attrs = {
		"id" = "",    # ID
		"name" = "",  # name属性
		"class" = "", # css类名
		"style" = "", # 行内样式
	}

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var tag = HTMLTag.new()  # 创建一个标签
	tag.tag_name = "a"           # 名称
	# 设定HTML标签通用属性
	tag.id = "a2"
	tag.name = "a2"
	tag.className = "url"
	tag.style = "font-size:16px;"
	tag.innerHTML = "一个超链接"
	
	print(tag)

输出:

<a id="a2" name="a2" class="url" style="font-size:16px;" >一个超链接</a>

HTML<a>标签

# =============================================
# 名称:HTMLtagA
# 类型:类
# 描述:HTML<a>标签类
# 作者:巽星石
# 创建时间:202471619:32:47
# 最后修改时间:202471622:30:57
# =============================================
class_name HTMLTagA extends HTMLTag

# ====================== 属性 ======================
# 链接地址
var href:String:
	set(val):
		attrs["href"] = val
	get:
		return attrs["href"]
# 指定链接如何在浏览器中打开
var target:String:
	set(val):
		attrs["target"] = val
	get:
		return attrs["target"]
# 鼠标提示文本
var title:String:
	set(val):
		attrs["title"] = val
	get:
		return attrs["title"]
# 指定与链接目标的关系,如 nofollow、noopener 等
var rel:String:
	set(val):
		attrs["rel"] = val
	get:
		return attrs["rel"]

# ====================== 初始化 ======================
func _init() -> void:
	super()   # 初始化父类,否则无法继承相关的默认属性
	# 确定标签名称以及是否单标签
	tag_name = "a"
	is_single = false
	# <a>标签可用属性
	attrs["href"] = ""     # 链接地址
	attrs["target"] = ""   # 指定链接如何在浏览器中打开
	attrs["title"] = ""    # 鼠标提示文本
	attrs["rel"] = ""      # 指定与链接目标的关系,如 nofollow、noopener 等

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var link = HTMLTagA.new()  # 创建一个标签
	# 设定<a>标签属性
	link.href = "https://www.runoob.com/"
	link.innerHTML = "菜鸟教程"
	
	print(link)

输出:

<a href="https://www.runoob.com/" >菜鸟教程</a>

SVG标签类

在这里插入图片描述

我发现专门做一个XML标签基类是没有必要的,XML本身就没有固定的标签,所以由MLTag定义完全可以解决XML标签定义和生成的功能。

<svg>本身既可以算HTML标签,也可以看做是XML标签。这里为了简化,我创建SVG类,代表<svg>标签,并直接继承自MLTag类型。

# =============================================
# 名称:SVG
# 类型:类
# 描述:SVG<svg>标签类
# 作者:巽星石
# 创建时间:202471621:37:24
# 最后修改时间:202471621:44:04
# =============================================
class_name SVG extends MLTag

# ====================== 属性 ======================
# SVG画布宽度
var width:String:
	set(val):
		attrs["width"] = val
	get:
		return attrs["width"]
# SVG画布高度
var height:String:
	set(val):
		attrs["height"] = val
	get:
		return attrs["height"]

# ====================== 初始化 ======================
func _init() -> void:
	tag_name = "svg"
	# HTML标签通用属性
	attrs = {
		"version"="1.1",
		"baseProfile"="full",
		"width"="200",
		"height"="200",
		"xmlns"="http://www.w3.org/2000/svg",
	}

SVGShape

SVG的形状和路径有许多共同的属性,所以抽象出一个SVGShape类型,用来承载共同属性。

# =============================================
# 名称:SVGShape
# 类型:类
# 描述:SVG所有形状和路径标签类的基类,承载共同属性
# 作者:巽星石
# 创建时间:202471621:51:00
# 最后修改时间:202471623:07:46
# =============================================
class_name SVGShape extends MLTag

# ====================== 属性 ======================
# 填充颜色
var fill:String:
	set(val):
		attrs["fill"] = val
	get:
		return attrs["fill"]

# 描边颜色
var stroke:String:
	set(val):
		attrs["stroke"] = val
	get:
		return attrs["stroke"]

# 描边宽度
var stroke_width:int:
	set(val):
		attrs["stroke-width"] = str(val)
	get:
		return int(attrs["stroke-width"])

# ====================== 初始化 ======================
func _init() -> void:
	tag_name = "svg"
	# svg形状和路径标签通用属性
	attrs["fill"] = "#fff"
	attrs["stroke"] = "#000"
	attrs["stroke-width"] = "1"

矩形

基于SVGShape类型,我们可以创建SVG具体的形状和路径类型。SVGRect就是SVG矩形 标签对应的类。

# =============================================
# 名称:SVGRect
# 类型:类
# 描述:SVG<rect>标签类
# 作者:巽星石
# 创建时间:202471621:47:43
# 最后修改时间:202471622:16:54
# =============================================
class_name SVGRect extends SVGShape

# ====================== 属性 ======================

# ---------------------- 位置 ---------------------- 
# 矩形左上角x坐标
var x:String:
	set(val):
		attrs["x"] = val
	get:
		return attrs["x"]

# 矩形左上角y坐标
var y:String:
	set(val):
		attrs["y"] = val
	get:
		return attrs["y"]
# ---------------------- 尺寸 ---------------------- 
# 矩形宽度
var width:String:
	set(val):
		attrs["width"] = val
	get:
		return attrs["width"]

# 矩形高度
var height:String:
	set(val):
		attrs["height"] = val
	get:
		return attrs["height"]
# ---------------------- 圆角 ---------------------- 
# 矩形圆角半径(水平方向)
var rx:String:
	set(val):
		attrs["rx"] = val
	get:
		return attrs["rx"]

# 矩形圆角半径(垂直方向)
var ry:String:
	set(val):
		attrs["ry"] = val
	get:
		return attrs["ry"]

# ====================== 初始化 ======================
func _init() -> void:
	super()   # 初始化父类,否则无法继承相关的默认属性
	tag_name = "rect"
	# HTML标签通用属性
	attrs["x"] = "0"
	attrs["y"] = "0"
	attrs["width"] = "100"
	attrs["height"] = "100"
	attrs["rx"] = "0"
	attrs["ry"] = "0"

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var svg = SVG.new()          # 创建SVG标签
	var rect  = SVGRect.new()    # 创建矩形
	svg.append(rect)
	print(svg)

获得的SVG代码:

<svg version="1.1" baseProfile="full" width="200" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="#000" stroke-width="1" x="0" y="0" width="100" height="100" rx="0" ry="0" ></rect></svg>

SVG预览如下:
image.png

@tool
extends EditorScript

func _run() -> void:
	var svg = SVG.new(100,200)                    # 创建SVG标签
	var rect  = SVGRect.new(0,0,100,200,12,12)    # 创建矩形
	# 设定矩形属性
	rect.stroke = "red"
	rect.stroke_width = 2
	# 将矩形追加到svg内容的末尾
	svg.append(rect)
	print(svg)           # 打印SVG代码

获得的SVG代码:

<svg version="1.1" baseProfile="full" width="100" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="red" stroke-width="2" x="0" y="0" width="100" height="200" rx="12" ry="12" ></rect></svg>

预览如下:
image.png

总结

  • 纯面向对象的设计,尤其是基于继承的多个类组成的体系在某些方面还是很有用的。比如HTML、XML、SVG这样本身就很明显的继承设计。
  • 基于继承或许会写出一堆类,但是辅以类图和文档,还是能让别人比较轻松的理解和掌握的。
  • 静态函数库则完全是一个很差的设计形式,很有可能会被一堆函数搞得特别臃肿。
  • 适当的用类和类的继承形式取代静态函数库形式是我正在做的尝试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1930612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Android】常见控件及使用

视图的设置 控件与布局都继承于视图&#xff0c;因此视图的设置方式对其作用都是一样的&#xff0c;接下来就先讲述视图的不同设置方式 设置视图的宽高&#xff1a; 对视图的宽高进行设置&#xff0c;首先确保XML中的宽高属性值为wrap_content&#xff0c;接着打开该页面对应…

MySQL第七次作业

Product表内容 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 产品编号 Int(10) 是 否 是 是 否 Name 产品功能 Varchar(20) 否 否 是 否 否 Function 主要功能 Varchar(50) 否 否 否 否 否 Company 生产厂家 Varchar(20) 否 否 是 否 否 Address 家庭住址 Varchar(20…

VS2022配置Qt环境

文章目录 前言VS2022写Qt的好处下载插件前提条件离线下载在线安装配置VS For Qt 创建项目总结 前言 在许多开发环境中&#xff0c;Visual Studio 2022&#xff08;VS2022&#xff09;和Qt都是非常重要的工具。VS2022是微软开发的一款强大的集成开发环境&#xff08;IDE&#x…

学习面向对象笔记

1. 面向对象三大特性 特性说明例子接口作为方法的标识&#xff0c;只要调用即可&#xff0c;不需要关心接口后是怎样实现的最常见的USB接口&#xff0c;只要插上对应的鼠标、键盘就可以使用&#xff0c;因为他们都是统一使用这个USB接口的继承子类继承父类的功能&#xff0c;子…

React工程化笔记

脚手架可以帮助我们快速的搭建一个项目结构&#xff0c;在我们之前学习 webpack 的过程中&#xff0c;每次都需要配置 webpack.config.js 文件&#xff0c;用于配置我们项目的相关 loader 、plugin&#xff0c;这些操作比较复杂&#xff0c;但是它的重复性很高&#xff0c;而且…

Spring Cloud Eureka快读入门Demo

1.什么是Eureka&#xff1f; Eureka 由 Netflix 开发&#xff0c;是一种基于REST&#xff08;Representational State Transfer&#xff09;的服务&#xff0c;用于定位服务&#xff08;服务注册与发现&#xff09;&#xff0c;以实现中间层服务的负载均衡和故障转移&#xff…

弹性网络回归(Elastic Net Regression)

弹性网络回归&#xff08;Elastic Net Regression&#xff09;的详细理论知识推导 理论背景 弹性网络回归结合了岭回归&#xff08;Ridge Regression&#xff09;和Lasso回归&#xff08;Lasso Regression&#xff09;的优点&#xff0c;通过引入两个正则化参数来实现特征选择…

vue3+TS从0到1手撸后台管理系统

1.路由配置 1.1路由组件的雏形 src\views\home\index.vue&#xff08;以home组件为例&#xff09; 1.2路由配置 1.2.1路由index文件 src\router\index.ts //通过vue-router插件实现模板路由配置 import { createRouter, createWebHashHistory } from vue-router import …

解决jupyter argparse报错

jupyter argparse报错 文章目录 一、jupyter argparse报错 一、jupyter argparse报错 args parser.parse_args()这行代码改为&#xff1a; args parser.parse_args(args[])完整的代码为&#xff1a; import argparseparser argparse.ArgumentParser() parser.add_argumen…

【Dison夏令营 Day 21】用Python编写绘图

绘画 - 在屏幕上绘制线条和形状。单击标记形状的起点&#xff0c;再次单击标记形状的终点。可使用键盘选择不同的形状和颜色。 """Paint, for drawing shapes.Exercises1. Add a color. 2. Complete circle. 3. Complete rectangle. 4. Complete triangle. 5. A…

DICOM CT\MR片子免费在线查看工具;python pydicom包加载查看;mayavi 3d查看

DICOM CT\MR片子免费在线查看工具 参考&#xff1a; https://zhuanlan.zhihu.com/p/668804209 dicom格式&#xff1a; DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff09;是医学数字成像和通信的标准。它定义了医学图像&#xff08;如CT、MRI、X…

MySQL ON DUPLICATE KEY UPDATE影响行数

背景 经常使用 ON DUPLICATE KEY UPDATE 来插入数据或者更新已存在的记录&#xff08;不推荐&#xff0c;如性能问题&#xff09;&#xff0c;今天联调时发现使用到 MySQL 一个 INSERT ... ON DUPLICATE KEY UPDATE 的语法&#xff0c;明明只更新了两条记录&#xff0c;返回的…

JMeter接口测试之文件上传(参数提取与传递)

参考文档&#xff1a; Jmeter接口测试-文件上传&#xff08;全网最详细的教程&#xff09;_jmeter 文件上传-CSDN博客 1、首先通过fiddler抓取文件上传接口&#xff0c;在Raw的tab页中查看默认请求头以及请求参数 如图所示 2、在jmeter中导入抓取的接口&#xff0c;首先需要配…

ENSP中VLAN的设置

VLAN的详细介绍 VLAN&#xff08;Virtual Local Area Network&#xff09;即虚拟局域网&#xff0c;是一种将一个物理的局域网在逻辑上划分成多个广播域的技术。 以下是关于 VLAN 的一些详细介绍&#xff1a; 一、基本概念 1. 作用&#xff1a; - 隔离广播域&#xff1a…

怎样在 PostgreSQL 中优化对多表关联的连接条件选择?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对多表关联的连接条件选择一、理解多表关联的基本概念二、选择合适的连接条件…

钡铼Modbus TCP耦合器BL200实现现场设备与SCADA无缝对接

前言 深圳钡铼技术推出的Modbus TCP耦合器为SCADA系统与现场设备之间的连接提供了强大而灵活的解决方案&#xff0c;它不仅简化了设备接入的过程&#xff0c;还提升了数据传输的效率和可靠性&#xff0c;是工业自动化项目中不可或缺的关键设备。本文将从Modbus TC、SCADA的简要…

去除重复字母

题目链接 去除重复字母 题目描述 注意点 s 由小写英文字母组成1 < s.length < 10^4需保证 返回结果的字典序最小&#xff08;要求不能打乱其他字符的相对位置&#xff09; 解答思路 本题与移掉 K 位数字类似&#xff0c;需要注意的是&#xff0c;并不是每个字母都能…

牛客周赛 Round 51 (C++)

目录 A-小红的同余_牛客周赛 Round 51 (nowcoder.com) 思路&#xff1a; 代码&#xff1a; B-小红的三倍数_牛客周赛 Round 51 (nowcoder.com) 思路&#xff1a; 代码&#xff1a; C-小红充电_牛客周赛 Round 51 (nowcoder.com) 思路&#xff1a; 代码&#xff1a; …

css - - - - - 环形倒计时进度条实现

css - - - - - 环形倒计时进度条实现 1. 效果图展示2. 代码展示 1. 效果图展示 2. 代码展示 // html <view class"father"><view class"progress" style"--progress:{{red}}; --last:{{gray}}"></view> </view>// css …

【区块链 + 智慧政务】澳门:智慧城市建设之证书电子化项目 | FISCO BCOS应用案例

2019 年 2 月 27 日&#xff0c;澳门政府设立的澳门科学技术发展基金与微众银行达成合作&#xff0c;通过区块链、人工智能、大数据、 云计算等创新技术&#xff0c;共同推进澳门特区的智慧城市建设与未来型城市发展&#xff0c;提升粤港澳大湾区的科创能力。在澳 门智慧城市建…