怎么做交易貓釣魚網(wǎng)站短視頻剪輯培訓(xùn)班速成
概述
HTML和XML采用類似的標(biāo)簽形式。
之前在Godot中以函數(shù)庫(kù)形式實(shí)現(xiàn)了網(wǎng)頁(yè)標(biāo)簽和內(nèi)容生成。能用,但是缺點(diǎn)也很明顯。函數(shù)之間沒(méi)有從屬關(guān)系,但是多有依賴,而且沒(méi)有劃分出各種對(duì)象和類型。
如果以完全的面向?qū)ο笮问絹?lái)設(shè)計(jì)標(biāo)簽類或者元素類,將可以更貼近HTML或XML的本來(lái)面目。也更容易生成。
整體思路是設(shè)計(jì)如下的類繼承結(jié)構(gòu):
實(shí)現(xiàn)之后,將可以充分的定義和生成HTML、XML和SVG標(biāo)簽,并用于內(nèi)容生成或文檔解析。
通用標(biāo)簽類
因?yàn)镠TML和XML標(biāo)簽的語(yǔ)法格式和要素是類似的,因此可以通過(guò)創(chuàng)建一個(gè)通用的標(biāo)簽類,來(lái)生成HTML或XML標(biāo)簽。
MLtag
就是這個(gè)通用的標(biāo)簽類,它定義了幾個(gè)核心的屬性:
tag_name
:標(biāo)簽名稱attrs
:包含標(biāo)簽所有屬性的字典is_single
:是否為單標(biāo)簽,默認(rèn)為false
content
:標(biāo)簽的子內(nèi)容,可以直接賦值,也可以使用append()
方法追加。單標(biāo)簽(is_single
為true
)時(shí)被忽略get_end_tag()
:獲取結(jié)束標(biāo)簽,單標(biāo)簽時(shí)返回空字符串append()
:追加當(dāng)前標(biāo)簽的子內(nèi)容,可以是字符串形式,也可以是SVG標(biāo)簽實(shí)例(會(huì)自動(dòng)調(diào)用to_string()
方法轉(zhuǎn)化為字符串)
# =============================================
# 名稱:MLtag
# 類型:類
# 描述:HTML、XML通用標(biāo)簽類,用于定義和生成HTML、XML標(biāo)簽字符串
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日17:48:01
# 最后修改時(shí)間:2024年7月16日22:27:53
# =============================================
class_name MLTag# ====================== 屬性 ======================
var tag_name = "" # 標(biāo)簽名稱
var attrs:Dictionary = {} # 屬性字典
var is_single = false # 是否單標(biāo)簽
var content = "" # 子內(nèi)容 # ====================== 方法 ======================
# 獲取結(jié)束標(biāo)簽
func get_end_tag() -> String:return "" if is_single else "</%s>" % tag_name# 追加子內(nèi)容
func append(new_content) -> void:if new_content is String:content += "\n" + new_contentelse:content += "\n" + new_content.to_string()# ====================== 虛函數(shù) ======================
# 轉(zhuǎn)化為字符串
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
測(cè)試:
@tool
extends EditorScriptfunc _run() -> void:var tag = MLTag.new() # 創(chuàng)建一個(gè)標(biāo)簽tag.name = "a" # 名稱tag.attrs["id"] = "a1" # 設(shè)定屬性tag.attrs["href"] = "https://www.runoob.com/"tag.content = "菜鳥(niǎo)教程"print(tag)
默認(rèn)是雙標(biāo)簽,也就是帶有起始標(biāo)簽和結(jié)束標(biāo)簽的標(biāo)簽對(duì)。
<a id="a1" href="https://www.runoob.com/" >菜鳥(niǎo)教程</a>
is_single
設(shè)為true
后,就被認(rèn)為是單標(biāo)簽:
@tool
extends EditorScriptfunc _run() -> void:var tag = MLTag.new() # 創(chuàng)建一個(gè)標(biāo)簽tag.name = "a" # 名稱tag.attrs["id"] = "a1" # 設(shè)定屬性tag.attrs["href"] = "1.com"tag.innerHTML = "hahah"tag.is_single = true # 設(shè)為標(biāo)簽print(tag)
打印輸出的結(jié)果也就變了:
<a id="a1" href="https://www.runoob.com/" />
可以看到?jīng)]有了結(jié)束標(biāo)簽,子內(nèi)容部分也自動(dòng)省略。
HTML標(biāo)簽基類
# =============================================
# 名稱:HTMLtag
# 類型:類
# 描述:HTML標(biāo)簽基類
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日19:05:46
# 最后修改時(shí)間:2024年7月16日19:29:34
# =============================================
class_name HTMLTag extends MLTag# ====================== 屬性 ======================
# ID
var id:String:set(val):attrs["id"] = valget:return attrs["id"]
# name
var name:String:set(val):attrs["name"] = valget:return attrs["name"]
# css類名
var className:String:set(val):attrs["class"] = valget:return attrs["class"]
# 行內(nèi)CSS樣式
var style:String:set(val):attrs["style"] = valget:return attrs["style"]
# ====================== 初始化 ======================
func _init() -> void:# HTML標(biāo)簽通用屬性attrs = {"id" = "", # ID"name" = "", # name屬性"class" = "", # css類名"style" = "", # 行內(nèi)樣式}
測(cè)試代碼:
@tool
extends EditorScriptfunc _run() -> void:var tag = HTMLTag.new() # 創(chuàng)建一個(gè)標(biāo)簽tag.tag_name = "a" # 名稱# 設(shè)定HTML標(biāo)簽通用屬性tag.id = "a2"tag.name = "a2"tag.className = "url"tag.style = "font-size:16px;"tag.innerHTML = "一個(gè)超鏈接"print(tag)
輸出:
<a id="a2" name="a2" class="url" style="font-size:16px;" >一個(gè)超鏈接</a>
HTML<a>標(biāo)簽
# =============================================
# 名稱:HTMLtagA
# 類型:類
# 描述:HTML的<a>標(biāo)簽類
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日19:32:47
# 最后修改時(shí)間:2024年7月16日22:30:57
# =============================================
class_name HTMLTagA extends HTMLTag# ====================== 屬性 ======================
# 鏈接地址
var href:String:set(val):attrs["href"] = valget:return attrs["href"]
# 指定鏈接如何在瀏覽器中打開(kāi)
var target:String:set(val):attrs["target"] = valget:return attrs["target"]
# 鼠標(biāo)提示文本
var title:String:set(val):attrs["title"] = valget:return attrs["title"]
# 指定與鏈接目標(biāo)的關(guān)系,如 nofollow、noopener 等
var rel:String:set(val):attrs["rel"] = valget:return attrs["rel"]# ====================== 初始化 ======================
func _init() -> void:super() # 初始化父類,否則無(wú)法繼承相關(guān)的默認(rèn)屬性# 確定標(biāo)簽名稱以及是否單標(biāo)簽tag_name = "a"is_single = false# <a>標(biāo)簽可用屬性attrs["href"] = "" # 鏈接地址attrs["target"] = "" # 指定鏈接如何在瀏覽器中打開(kāi)attrs["title"] = "" # 鼠標(biāo)提示文本attrs["rel"] = "" # 指定與鏈接目標(biāo)的關(guān)系,如 nofollow、noopener 等
測(cè)試代碼:
@tool
extends EditorScriptfunc _run() -> void:var link = HTMLTagA.new() # 創(chuàng)建一個(gè)標(biāo)簽# 設(shè)定<a>標(biāo)簽屬性link.href = "https://www.runoob.com/"link.innerHTML = "菜鳥(niǎo)教程"print(link)
輸出:
<a href="https://www.runoob.com/" >菜鳥(niǎo)教程</a>
SVG標(biāo)簽類
我發(fā)現(xiàn)專門做一個(gè)XML標(biāo)簽基類是沒(méi)有必要的,XML本身就沒(méi)有固定的標(biāo)簽,所以由MLTag定義完全可以解決XML標(biāo)簽定義和生成的功能。
而<svg>
本身既可以算HTML標(biāo)簽,也可以看做是XML標(biāo)簽。這里為了簡(jiǎn)化,我創(chuàng)建SVG類,代表<svg>
標(biāo)簽,并直接繼承自MLTag
類型。
# =============================================
# 名稱:SVG
# 類型:類
# 描述:SVG的<svg>標(biāo)簽類
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日21:37:24
# 最后修改時(shí)間:2024年7月16日21:44:04
# =============================================
class_name SVG extends MLTag# ====================== 屬性 ======================
# SVG畫布寬度
var width:String:set(val):attrs["width"] = valget:return attrs["width"]
# SVG畫布高度
var height:String:set(val):attrs["height"] = valget:return attrs["height"]# ====================== 初始化 ======================
func _init() -> void:tag_name = "svg"# HTML標(biāo)簽通用屬性attrs = {"version"="1.1","baseProfile"="full","width"="200","height"="200","xmlns"="http://www.w3.org/2000/svg",}
SVGShape
SVG的形狀和路徑有許多共同的屬性,所以抽象出一個(gè)SVGShape
類型,用來(lái)承載共同屬性。
# =============================================
# 名稱:SVGShape
# 類型:類
# 描述:SVG所有形狀和路徑標(biāo)簽類的基類,承載共同屬性
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日21:51:00
# 最后修改時(shí)間:2024年7月16日23:07:46
# =============================================
class_name SVGShape extends MLTag# ====================== 屬性 ======================
# 填充顏色
var fill:String:set(val):attrs["fill"] = valget:return attrs["fill"]# 描邊顏色
var stroke:String:set(val):attrs["stroke"] = valget: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形狀和路徑標(biāo)簽通用屬性attrs["fill"] = "#fff"attrs["stroke"] = "#000"attrs["stroke-width"] = "1"
矩形
基于SVGShape
類型,我們可以創(chuàng)建SVG具體的形狀和路徑類型。SVGRect
就是SVG矩形
# =============================================
# 名稱:SVGRect
# 類型:類
# 描述:SVG的<rect>標(biāo)簽類
# 作者:巽星石
# 創(chuàng)建時(shí)間:2024年7月16日21:47:43
# 最后修改時(shí)間:2024年7月16日22:16:54
# =============================================
class_name SVGRect extends SVGShape# ====================== 屬性 ======================# ---------------------- 位置 ----------------------
# 矩形左上角x坐標(biāo)
var x:String:set(val):attrs["x"] = valget:return attrs["x"]# 矩形左上角y坐標(biāo)
var y:String:set(val):attrs["y"] = valget:return attrs["y"]
# ---------------------- 尺寸 ----------------------
# 矩形寬度
var width:String:set(val):attrs["width"] = valget:return attrs["width"]# 矩形高度
var height:String:set(val):attrs["height"] = valget:return attrs["height"]
# ---------------------- 圓角 ----------------------
# 矩形圓角半徑(水平方向)
var rx:String:set(val):attrs["rx"] = valget:return attrs["rx"]# 矩形圓角半徑(垂直方向)
var ry:String:set(val):attrs["ry"] = valget:return attrs["ry"]# ====================== 初始化 ======================
func _init() -> void:super() # 初始化父類,否則無(wú)法繼承相關(guān)的默認(rèn)屬性tag_name = "rect"# HTML標(biāo)簽通用屬性attrs["x"] = "0"attrs["y"] = "0"attrs["width"] = "100"attrs["height"] = "100"attrs["rx"] = "0"attrs["ry"] = "0"
測(cè)試代碼:
@tool
extends EditorScriptfunc _run() -> void:var svg = SVG.new() # 創(chuàng)建SVG標(biāo)簽var rect = SVGRect.new() # 創(chuàng)建矩形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預(yù)覽如下:
@tool
extends EditorScriptfunc _run() -> void:var svg = SVG.new(100,200) # 創(chuàng)建SVG標(biāo)簽var rect = SVGRect.new(0,0,100,200,12,12) # 創(chuàng)建矩形# 設(shè)定矩形屬性rect.stroke = "red"rect.stroke_width = 2# 將矩形追加到svg內(nèi)容的末尾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>
預(yù)覽如下:
總結(jié)
- 純面向?qū)ο蟮脑O(shè)計(jì),尤其是基于繼承的多個(gè)類組成的體系在某些方面還是很有用的。比如HTML、XML、SVG這樣本身就很明顯的繼承設(shè)計(jì)。
- 基于繼承或許會(huì)寫出一堆類,但是輔以類圖和文檔,還是能讓別人比較輕松的理解和掌握的。
- 靜態(tài)函數(shù)庫(kù)則完全是一個(gè)很差的設(shè)計(jì)形式,很有可能會(huì)被一堆函數(shù)搞得特別臃腫。
- 適當(dāng)?shù)挠妙惡皖惖睦^承形式取代靜態(tài)函數(shù)庫(kù)形式是我正在做的嘗試