Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
Zag 和 PandaCSS 都是出自 chakra 團隊之手,Zag 聚焦于處理組件的邏輯,而 PandaCSS 聚焦于通過 ts 來維護樣式,將兩者進行搭配會有怎么樣的使用體驗呢?這篇文章將繼續以 vuesax 中 checkbox 組件的樣式作為參考,結合 Zag 和 PandaCSS 進行 vue3 版本的重構,實現一個超絲滑的勾選框組件。
Zag 中將 Checkbox 分為三個組成部分:
我們首先在 Zag Checkbox 文檔中復制 JSX 的實例代碼:
import * as checkbox from "@zag-js/checkbox"
import { normalizeProps, useMachine } from "@zag-js/vue"
import { defineComponent, h, Fragment, computed } from "vue"
export default defineComponent({
name: "Checkbox",
setup() {
const [state, send] = useMachine(checkbox.machine({ id: "checkbox" }))
const apiRef = computed(() =>
checkbox.connect(state.value, send, normalizeProps),
)
return () => {
const api = apiRef.value
return (
<label {...api.rootProps}>
<span {...api.labelProps}>
Input is {api.isChecked ? "checked" : "unchecked"}
</span>
<div {...api.controlProps} />
<input {...api.hiddenInputProps} />
</label>
)
}
},
})
這段代碼使用了 useMachine 函數創建了一個狀態機,并且寫了一個無樣式的基礎 checkbox 結構:
接下來我們為 checkbox 組件補充樣式.
想要實現絲滑的勾選框效果,最直觀的是打勾的動畫。這個效果可以通過 SVG 或者純 css 實現,這里我使用的是 css 來實現的。:
首先我們要想想如何實現一個勾勾的效果,??由一長一短兩個斜邊組成,那么我們只需要放置一個矩形,設置一定的旋轉角度,并設置其中的兩個邊框,就能實現一個??的形狀:
代碼實現如下:
import { defineComponent } from "vue";
import { css, cx } from "@/styled-system/css";
const IconCheck = defineComponent({
props: {
color: {
type: String,
default: css({ colorPalette: "gray" }),
},
size: {
type: String,
default: css({ colorPalette: "gray" }),
},
customCSS: {
type: String,
},
},
setup(props) {
return () => (
<i
class={cx(
css({
display: "flex",
alignItems: "center",
justifyContent: "center",
}),
props.customCSS,
)}
>
<div
class={css({
position: "relative",
width: "80%",
height: "40%",
transform: "rotate(-45deg)",
})}
>
<div
class={css({
position: "absolute",
left: "0",
width: "full",
height: "full",
borderLeft: "2px solid white",
animation: "checkShort 0.15s",
})}
/>
<div
class={css({
position: "absolute",
left: "0",
width: "full",
height: "full",
borderBottom: "2px solid white",
animation: "checkLong 0.5s",
})}
/>
</div>
</i>
);
},
});
export default IconCheck;
上面這段代碼中,定義了一個矩形,寬高分別為最外層容器的 80% 和 40%,transform: "rotate(-45deg)", 則設置了矩形的旋轉角度,內部放置兩個與矩形寬高一致的容器,分別設置 borderLeft 和 borderBottom ,這樣就組成了一長一短兩條線。
這里之所以需要在內部放兩個容器單獨設置邊框,而不是直接在矩形設置邊框,是為了更好的實現動畫效果,長短邊分別設置了兩個持續時間不同的動畫 checkShort 0.15s 和 checkLong 0.5s:
checkShort: {
"0%": {
height:0,
},
"100%":{
height: "full",
}
},
checkLong: {
"0%": {
width: 0,
},
"30%":{
width: 0,
},
"100%": {
width: "full",
}
}
短邊從最開始就執行動畫,持續時間為長邊動畫的 30%,長邊則在 0-30% 時不執行,30% 之后開始執行,這樣就能實現短邊動畫執行完成后,長邊動畫再執行的效果。
之所以不使用 animation-delay 去延遲執行長邊動畫,是因為這種方式會導致動畫延遲執行前,長邊會先展示出來,效果就不對了。如果要使用這種方式還得單獨做一些動畫延遲前的隱藏處理,會比較麻煩:
為了讓用戶更容易感知勾選框是可以交互的,我們為勾選框增加未勾選和關狀態的 hover 效果。
未勾選狀態的 hover 效果,默認只有灰色邊框,鼠標懸浮后變為灰色背景:
這里有個注意點,我們鼠標懸浮在勾選框的最外層,也可以觸發內層的 hover 樣式,如果直接使用 hover 效果是沒法做到的,這樣只能鼠標懸浮在邊框內才能觸發。
如果我們沒有使用任何樣式庫,實現這個效果可以通過維護一個 鼠標是否 hover 的狀態,并通過 onMouseEnter 和 onMouseLeave 來更新這個狀態,再在內層根據這個狀態動態渲染樣式。
但這里我們可以使用 pandaCSS 的 group 選擇器來實現。
首先在勾選框最外層元素增加 group 類名:
<label
{...api.rootProps}
class={[
css({
display: "flex",
alignItems: "center",
cursor: "pointer",
}),
+ "group",
]}
>
然后在內層的 control 元素增加基礎樣式:
<div
{...api.controlProps}
class={css({
width: "24px",
height: "24px",
borderRadius: "8px",
border: api.isChecked
? "none"
: "token(colors.gray.200) solid 2px",
transition: "all 0.3s",
marginRight: "4px",
flexShrink: "0",
_groupHover: {
background: "gray.200",
},
})}
>
// ...
</div>
這里的 _groupHover 即為 group 選擇器,當帶有 group 類名的元素觸發 hover 時,內部的元素都可以使用 _groupHover 設置特定樣式。這樣我們就實現了前文圖中的效果。
在勾選時,會有一個藍色色塊放大漸出的效果,我們先來實現這個樣式。
<Transition
enterFromClass={css({
transition: "all 0.2s",
transform: "scale(0.5)",
opacity: "0",
})}
enterToClass={css({
transition: "all 0.2s",
transform: "scale(1)",
opacity: "1",
})}
leaveToClass={css({
transition: "all 0.2s",
transform: "scale(0.5)",
opacity: "0",
})}
>
{api.isChecked && (
<div
class={cx(
props.color,
css({
width: "full",
height: "full",
background: "colorPalette.600",
borderRadius: "inherit",
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "all 0.3s",
}),
)}
>
<IconCheck
customCSS={css({
width: "18px",
height: "18px",
})}
/>
</div>
)}
</Transition>
這里我們使用 vue 中的 Transition 組件來實現動畫效果,通過改變scale 和 opacity 實現元素大小和透明度的過渡動畫,內部包裹著勾選的圖標。
實現了勾選的效果,繼續實現勾選后的 hover 樣式。勾選后在 hover 時,勾選框的外層有一個與主題色相同的外層陰影效果:
這里我們依然使用 group 選擇器來設置 hover 樣式:
<div
class={cx(
props.color,
css({
width: "full",
height: "full",
background: "colorPalette.600",
borderRadius: "inherit",
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "all 0.3s",
+ _groupHover: {
+ boxShadow:
+ "0px 3px 15px 0px color-mix(in srgb, token(colors.colorPalette.600) 40%, transparent)",
+ },
}),
)}
>
<IconCheck
customCSS={css({
width: "18px",
height: "18px",
})}
></IconCheck>
</div>
在陰影效果的代碼中 0px 3px 15px 0px color-mix(in srgb, token(colors.colorPalette.600) 40%, transparent) ,前面幾個設置陰影大小的參數很容易理解,但是后面陰影顏色的實現大家可能比較陌生,單獨解釋一下:
我這里用法的含義是在 srgb 的色彩模式下,將主題色(token(colors.colorPalette.600)) 與透明色(transparent),以 40% 的比例進行混合,最終合成的顏色就是 40% 透明度的主題色。 color-mix() 函數是 pandaCSS 中推薦用戶用于為內置顏色設置透明度的方法,除此以外并沒有發現其他更簡便的方式。
最后我們完善一下勾選框的雙向綁定邏輯邏輯,
實現的代碼如下:
const [state, send] = useMachine(
checkbox.machine({
id: useId("checkbox"),
onCheckedChange(detail) {
emit("update:modelValue", detail.checked);
},
}),
);
const apiRef = computed(() =>
checkbox.connect(state.value, send, normalizeProps),
);
watch(
() => props.modelValue,
() => {
apiRef.value.setChecked(props.modelValue);
},
);
? 使用 Vue+Zag+PandaCSS 實現一個超絲滑的勾選框組件
原文鏈接:https://juejin.cn/post/7295954109404463155
html表單:HTML表單用于收集用戶輸入的數據,并將數據發送到服務器進行處理,創建了一個包含多種表單元素的表單。其中,<label> 標簽用來描述表單元素,<input> 標簽用來創建表單輸入框,<textarea> 標簽用來創建多行文本輸入框,<button> 標簽用來創建提交按鈕等等。下面我們一起來學習了解吧
HTML提供了幾個用于創建表單的標簽,包括<form>、<input>、<label>、<select>、<option>、<textarea>和<button>。
<form>標記用于創建表單元素,該元素可以包含一個或多個表單控件,如文本輸入、復選框、單選按鈕等。
action屬性指定表單數據應提交到的URL,method屬性指定用于提交的HTTP方法(通常為“GET”或“POST”)。
下面是一個帶有文本輸入和提交按鈕的簡單表單示例:
<form action="submit-form.php" method="POST">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<button type="submit">Submit</button>
</form>
在本例中,<label>標記用于使用for屬性和id屬性將文本輸入與其標簽相關聯。輸入的name屬性指定將與表單數據一起提交的表單字段的名稱。
<select>標記用于創建選項的下拉列表,<option>標記用于定義每個選項。下面是一個例子:
<label for="color">Favorite color:</label>
<select id="color" name="color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
在本例中,每個選項的value屬性指定將與表單數據一起提交的值。
<textarea>標記用于創建多行文本輸入。下面是一個例子:
<label for="message">Message:</label>
<textarea id="message" name="message"></textarea>
<button>標記用于創建一個按鈕,該按鈕可用于提交表單或執行其他操作。 下面是一個例子:
<button type="submit">Submit</button>
HTML中,文本框、密碼框和多行文本框分別使用input元素的不同type屬性值來實現。
文本框、密碼框和多行文本框是用來接收用戶輸入的常見表單元素。它們分別使用不同的標簽和屬性來實現。
文本框(text box)是用于接受單行文本輸入的表單元素。可以通過設置<input>標簽的type屬性為"text"來創建文本框。例如:
<label for="username">用戶名:</label>
<input type="text" id="username" name="username">
上面的示例代碼中,id屬性定義了文本框的唯一標識符,name屬性定義了提交表單時該文本框的名稱。
密碼框(password field)是用于接受密碼等敏感信息的表單元素,并且會將用戶輸入的字符隱藏起來。可以通過設置<input>標簽的type屬性為"password"來創建密碼框。例如:
<label for="password">密碼:</label>
<input type="password" id="password" name="password">
多行文本框(text area)可用于接收包含多個行的文本輸入,例如評論或留言等。可以通過使用<textarea>標簽來創建多行文本框,然后使用它的rows和cols屬性來指定它的尺寸。例如:
<label for="message">留言:</label>
<textarea id="message" name="message" rows="5" cols="30"></textarea>
上面的示例代碼中,rows屬性定義了多行文本框的行數,cols屬性定義了多行文本框每一行的字符數。
HTML中,單選框和復選框是常見的表單元素,用于讓用戶選擇不同選項。它們分別使用<input>標簽的不同type屬性值來實現。
單選框(radio button)允許用戶在一組選項中選擇一個。可以使用相同的name屬性來將多個單選框關聯起來。當用戶勾選其中一個單選框時,其他單選框將自動取消選中狀態。可以通過設置<input>標簽的type屬性為"radio"來創建單選框。例如:
<form>
<p>請選擇性別:</p>
<label><input type="radio" name="gender" value="M">男士</label>
<label><input type="radio" name="gender" value="F">女士</label>
<label><input type="radio" name="gender" value="O">其他</label>
</form>
上面的示例代碼中,三個單選框使用相同的name屬性,以便將它們關聯起來。當用戶勾選其中一個單選框時,另外兩個單選框將自動取消選中狀態。
復選框(checkbox)允許用戶選擇多個選項。可以使用相同的name屬性來將多個復選框關聯起來。當用戶勾選其中一個復選框時,其他復選框保持不變。可以通過設置<input>標簽的type屬性為"checkbox"來創建復選框。例如:
<form>
<p>請選擇語言:</p>
<label><input type="checkbox" name="lang" value="js">JavaScript</label>
<label><input type="checkbox" name="lang" value="py">Python</label>
<label><input type="checkbox" name="lang" value="java">Java</label>
</form>
上面的示例代碼中,三個復選框使用相同的name屬性,以便將它們關聯起來。用戶可以勾選多個復選框。
單選框和復選框的值可以通過value屬性進行指定,當表單提交時,瀏覽器會將被選中的單選框或復選框的值作為表單數據提交到服務器并進行處理。
HTML中,下拉列表框和列表框是用來顯示多個選項的表單元素。它們分別使用不同的標簽和屬性來實現。
下拉列表框(dropdown list)可以讓用戶從多個選項中選擇一個選項。可以使用<select>標簽來創建下拉列表框,然后使用<option>標簽定義每一個選項。例如:
<form>
<p>請選擇城市:</p>
<select name="city">
<option value="bj">北京</option>
<option value="sh">上海</option>
<option value="gz">廣州</option>
<option value="sz">深圳</option>
</select>
</form>
上面的示例代碼中,四個<option>標簽定義了四個選項。其中"value"屬性指定每個選項的值,"text"節點指定每個選項的文本內容。當用戶點擊下拉框時,會出現一個下拉菜單列出所有可用選項,用戶可以從中選擇一個選項。
列表框(list box)是另一種顯示多個選項的表單元素,與下拉列表框不同的是,列表框可以同時顯示多個選項。可以使用<select>標簽來創建列表框,然后使用<option>標簽定義每一個選項并設置multiple屬性為"multiple"來啟用多選模式。例如:
<form>
<p>請選擇興趣愛好:</p>
<select name="interests" multiple>
<option value="reading">閱讀</option>
<option value="music">音樂</option>
<option value="painting">繪畫</option>
<option value="sports">運動</option>
</select>
</form>
上面的示例代碼中,multiple屬性指定該列表框啟用多選模式。當用戶選擇一個或多個選項時,這些選項將被高亮顯示。
總之,在HTML中可以使用下拉列表框和列表框來為用戶提供多個選項讓用戶選擇,并在表單提交時將選擇的結果作為表單數據提交到服務器。
HTML中,按鈕和圖像按鈕是用來觸發事件或提交表單的表單元素。它們分別使用<button>標簽和<input>標簽的不同type屬性值來實現。
普通按鈕(button)通常用于觸發一些事件,例如刷新頁面、清空表單等。可以使用<button>標簽來創建普通按鈕。例如:
<button>點擊我</button>
上面的示例代碼中,創建了一個簡單的按鈕,點擊按鈕會觸發一些事件。
提交按鈕(submit button)用于將表單數據提交到服務器進行處理。可以使用<input>標簽,并將其type屬性設置為"submit"來創建提交按鈕,例如:
<input type="submit" value="提交">
上面的示例代碼中,設置了一個提交按鈕,當用戶點擊該按鈕時,瀏覽器會將表單數據提交到服務器并進行處理。
圖像按鈕(image button)與普通按鈕類似,但它使用圖片而不是文本作為按鈕的標識。可以使用<input>標簽,并將其type屬性設置為"image"來創建圖像按鈕,例如:
<input type="image" src="submit.png" alt="提交">
上面的示例代碼中,創建了一個帶有圖片的圖像按鈕。當用戶單擊圖像按鈕時,瀏覽器會將表單數據提交到服務器并進行處理。
以上就是今天要講的內容,本文簡單介紹了HTML的表單的知識點,更多內容可以查看THTML官方文檔
如果覺得有用,歡迎明天再來,繼續合集的下一篇文章學習
遇到問題,私信我!!~~
次講Qt Style Sheet(QSS),QSS是一種與CSS類似的語言,實際上這兩者幾乎完全一樣。既然談到CSS我們就有必要說一下盒模型。
在樣式中,每一個UI控件都可以抽象成一個盒模型:
盒模型由4個同心矩形組成,從外到內分別是外邊距、邊界、內襯和內容,大部分UI視覺內容都包含在內容矩形中。默認情況下,前三個矩形的大小屬性都是0,因此這四個矩形都重疊成一個了。這里與前三個大小相關的屬性有:
QSS與CSS相似,因此這里只大概介紹QSS的特點:
這里我們通過一個示例程序來接觸QSS,因為實例程序涉及多個控件但我們篇幅有限,我們只介紹菜單相關的樣式設置。菜單分為兩部分:菜單欄(QMenuBar)、菜單(QMenu)。
我們把菜單欄寬度設置成大于等于菜單item的寬度60px(這里的width不指代整個菜單欄的寬度,比較奇怪),防止item的寬度被菜單欄的寬度限制,并且設置灰色點邊框。
QT開發交流+貲料君羊:714620761
QMenuBar {
width:60px;
background-color:white;
border:1px dotted gray;
}
item這里代指菜單欄上的每一項菜單,我們設置邊框位groove以使其看起來有凹凸效果;設置margin-right,這樣兩個item之間會有合適的間隔;我們還在不同的狀態下設置不同的背景顏色,這樣交互上比較友好。
QMenuBar::item {
height:15px;
width:60px;
background:transparent;
border:2px groove gray;
margin-right:1px;
}
QMenuBar::item:selected {
color:green;
background-color:rgb(236, 242, 245);
}
QMenuBar::item:pressed {
color:green;
background-color:rgb(233, 227, 227);
}
菜單我們設置成與菜單欄一樣;菜單的item指代每一個菜單選項,我們對其設置合適的margin和padding大小,border、item的selected和pressed狀態設置成菜單欄的樣式,使其看起來布局空間合理且與菜單欄一致:
QMenu {
background-color:white;
border:1px solid rgb(0, 171, 255);
padding:1px;
}
QMenu::item {
height:15px;
width:60px;
background-color:white;
margin:1px;
padding:2px 2px 2px 20px;
border:2px groove gray;
}
QMenu::item:selected {
color:green;
background-color:rgb(236, 242, 245);
}
QMenu::item:pressed {
color:green;
background-color:rgb(233, 227, 227);
}
我們重繪菜單之間的間隔條(separator),簡單的用淺藍色填充1像素高的背景:
QMenu::separator {
height:1px;
margin:1px;
background-color:lightblue;
}
菜單的選中指示框和子菜單我們用圖片來顯示,圖片選用png格式,保持透明通道,使其與背景一致:
QMenu::indicator:checked {
width:10px;
height:10px;
margin-left:3px;
border:0px solid blue;
image:url(:/checked-icon.png);
}
QMenu::right-arrow {
width:15px;
height:15px;
image:url(:/right-arrow.png);
}
程序的完整運行結果如下:
優點:
缺點:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。