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
選是由多個(gè)單選項(xiàng)組成的選擇控件,獲取用戶針對(duì)某個(gè)事情的唯一結(jié)果。
常用場(chǎng)景有“微信APP-我-個(gè)人信息-設(shè)置性別”、“iOS設(shè)置-通知-顯示預(yù)覽”等。
單選功能通常包含標(biāo)題和多個(gè)單選項(xiàng),每個(gè)單選項(xiàng)由選項(xiàng)名稱和單選按鈕。
(1)先畫標(biāo)題。從默認(rèn)元件庫(kù)拖動(dòng)“文本標(biāo)簽”到工作區(qū),或者直接把“頁(yè)面名稱”作為標(biāo)題。
(2)再畫選項(xiàng)名稱。從默認(rèn)元件庫(kù)拖動(dòng)“矩形1”到工作區(qū),修改尺寸為375*40px,雙擊輸入文字“選項(xiàng)名稱”,設(shè)置左填充為15px這樣展示效果更妥當(dāng)。
(3)再畫單選按鈕。從默認(rèn)元件庫(kù)拖動(dòng)“文本標(biāo)簽”到“選項(xiàng)名稱”的右邊,雙擊輸入“√”,修改尺寸為40*40px,設(shè)置對(duì)齊方式為左右居中和垂直居中。
(4)復(fù)制單選名稱2份,依次排列。
(5)生成原型HTML并在瀏覽器中查看效果。
單選功能的常見交互效果:點(diǎn)擊任一單選按鈕自動(dòng)變?yōu)檫x中狀態(tài),同時(shí)其他單選按鈕變成未選中狀態(tài)。選中狀態(tài)和未選中狀態(tài)的樣式是不一樣的。
(6)繼承上面的“無(wú)交互”步驟,從第四步開始繼續(xù)畫“有交互”。設(shè)置按鈕的未選中狀態(tài),設(shè)置文本顏色為白色。
(7)設(shè)置按鈕的選中狀態(tài),點(diǎn)擊“交互樣式-選中”,選中字體顏色設(shè)置為#333333。
(8)設(shè)置按鈕為選項(xiàng)組。選擇按鈕設(shè)置選項(xiàng)組名稱為“單選”或者其他名稱,這樣代表該組的按鈕同時(shí)只能有一個(gè)選中狀態(tài)。
(9)選中標(biāo)題和按鈕,然后右鍵點(diǎn)擊“組合”,然后命名為“單選項(xiàng)”。
(10)設(shè)置單選項(xiàng)的交互。點(diǎn)擊該組合,設(shè)置“鼠標(biāo)單擊時(shí)”事件,添加動(dòng)作“選中”,組織動(dòng)作“當(dāng)前元件”。
(11)復(fù)制單選項(xiàng)2份,依次排列。
(12)選中第一個(gè)按鈕,打勾選中,這樣生成原型之后默認(rèn)選中它。
(13)生成原型HTML并在瀏覽器中查看效果。
不同場(chǎng)景下的單選功能,標(biāo)題不一樣,樣式相對(duì)固定。
根據(jù)多年P(guān)M經(jīng)驗(yàn),總結(jié)出3種常用的“單選”,添加到APP功能庫(kù)。
單選(打勾)
單選(主流)
單選(傳統(tǒng))
單選功能同一時(shí)間只有一個(gè)選中狀態(tài)。
單選功能可以設(shè)計(jì)多種樣式,另外選擇器也可充當(dāng)單選功能。
我們百度搜索我們想要的文章時(shí),好不容易找到了我們想要的文章,點(diǎn)開復(fù)制,卻發(fā)現(xiàn)文章被鎖定,像下面這種情況,復(fù)制需要收費(fèi),面對(duì)這樣的情況,教你一招解決,免費(fèi)復(fù)制自己想要的文章。
首先我們需要找到我們所要復(fù)制的文章,按電腦上的F12按鈕,打開如同所示的頁(yè)面
然后按F1按鈕
再往下翻,找到Debugger下面的禁用JavaScript,進(jìn)行打勾
千萬(wàn)不要將旁邊的框框刪去,這樣就可以免費(fèi)復(fù)制了
Zag 和 PandaCSS 都是出自 chakra 團(tuán)隊(duì)之手,Zag 聚焦于處理組件的邏輯,而 PandaCSS 聚焦于通過 ts 來(lái)維護(hù)樣式,將兩者進(jìn)行搭配會(huì)有怎么樣的使用體驗(yàn)?zāi)兀窟@篇文章將繼續(xù)以 vuesax 中 checkbox 組件的樣式作為參考,結(jié)合 Zag 和 PandaCSS 進(jìn)行 vue3 版本的重構(gòu),實(shí)現(xiàn)一個(gè)超絲滑的勾選框組件。
Zag 中將 Checkbox 分為三個(gè)組成部分:
我們首先在 Zag Checkbox 文檔中復(fù)制 JSX 的實(shí)例代碼:
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 函數(shù)創(chuàng)建了一個(gè)狀態(tài)機(jī),并且寫了一個(gè)無(wú)樣式的基礎(chǔ) checkbox 結(jié)構(gòu):
接下來(lái)我們?yōu)?checkbox 組件補(bǔ)充樣式.
想要實(shí)現(xiàn)絲滑的勾選框效果,最直觀的是打勾的動(dòng)畫。這個(gè)效果可以通過 SVG 或者純 css 實(shí)現(xiàn),這里我使用的是 css 來(lái)實(shí)現(xiàn)的。:
首先我們要想想如何實(shí)現(xiàn)一個(gè)勾勾的效果,??由一長(zhǎng)一短兩個(gè)斜邊組成,那么我們只需要放置一個(gè)矩形,設(shè)置一定的旋轉(zhuǎn)角度,并設(shè)置其中的兩個(gè)邊框,就能實(shí)現(xiàn)一個(gè)??的形狀:
代碼實(shí)現(xiàn)如下:
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;
上面這段代碼中,定義了一個(gè)矩形,寬高分別為最外層容器的 80% 和 40%,transform: "rotate(-45deg)", 則設(shè)置了矩形的旋轉(zhuǎn)角度,內(nèi)部放置兩個(gè)與矩形寬高一致的容器,分別設(shè)置 borderLeft 和 borderBottom ,這樣就組成了一長(zhǎng)一短兩條線。
這里之所以需要在內(nèi)部放兩個(gè)容器單獨(dú)設(shè)置邊框,而不是直接在矩形設(shè)置邊框,是為了更好的實(shí)現(xiàn)動(dòng)畫效果,長(zhǎng)短邊分別設(shè)置了兩個(gè)持續(xù)時(shí)間不同的動(dòng)畫 checkShort 0.15s 和 checkLong 0.5s:
checkShort: {
"0%": {
height:0,
},
"100%":{
height: "full",
}
},
checkLong: {
"0%": {
width: 0,
},
"30%":{
width: 0,
},
"100%": {
width: "full",
}
}
短邊從最開始就執(zhí)行動(dòng)畫,持續(xù)時(shí)間為長(zhǎng)邊動(dòng)畫的 30%,長(zhǎng)邊則在 0-30% 時(shí)不執(zhí)行,30% 之后開始執(zhí)行,這樣就能實(shí)現(xiàn)短邊動(dòng)畫執(zhí)行完成后,長(zhǎng)邊動(dòng)畫再執(zhí)行的效果。
之所以不使用 animation-delay 去延遲執(zhí)行長(zhǎng)邊動(dòng)畫,是因?yàn)檫@種方式會(huì)導(dǎo)致動(dòng)畫延遲執(zhí)行前,長(zhǎng)邊會(huì)先展示出來(lái),效果就不對(duì)了。如果要使用這種方式還得單獨(dú)做一些動(dòng)畫延遲前的隱藏處理,會(huì)比較麻煩:
為了讓用戶更容易感知勾選框是可以交互的,我們?yōu)楣催x框增加未勾選和關(guān)狀態(tài)的 hover 效果。
未勾選狀態(tài)的 hover 效果,默認(rèn)只有灰色邊框,鼠標(biāo)懸浮后變?yōu)榛疑尘埃?/p>
這里有個(gè)注意點(diǎn),我們鼠標(biāo)懸浮在勾選框的最外層,也可以觸發(fā)內(nèi)層的 hover 樣式,如果直接使用 hover 效果是沒法做到的,這樣只能鼠標(biāo)懸浮在邊框內(nèi)才能觸發(fā)。
如果我們沒有使用任何樣式庫(kù),實(shí)現(xiàn)這個(gè)效果可以通過維護(hù)一個(gè) 鼠標(biāo)是否 hover 的狀態(tài),并通過 onMouseEnter 和 onMouseLeave 來(lái)更新這個(gè)狀態(tài),再在內(nèi)層根據(jù)這個(gè)狀態(tài)動(dòng)態(tài)渲染樣式。
但這里我們可以使用 pandaCSS 的 group 選擇器來(lái)實(shí)現(xiàn)。
首先在勾選框最外層元素增加 group 類名:
<label
{...api.rootProps}
class={[
css({
display: "flex",
alignItems: "center",
cursor: "pointer",
}),
+ "group",
]}
>
然后在內(nèi)層的 control 元素增加基礎(chǔ)樣式:
<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 選擇器,當(dāng)帶有 group 類名的元素觸發(fā) hover 時(shí),內(nèi)部的元素都可以使用 _groupHover 設(shè)置特定樣式。這樣我們就實(shí)現(xiàn)了前文圖中的效果。
在勾選時(shí),會(huì)有一個(gè)藍(lán)色色塊放大漸出的效果,我們先來(lái)實(shí)現(xiàn)這個(gè)樣式。
<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 組件來(lái)實(shí)現(xiàn)動(dòng)畫效果,通過改變scale 和 opacity 實(shí)現(xiàn)元素大小和透明度的過渡動(dòng)畫,內(nèi)部包裹著勾選的圖標(biāo)。
實(shí)現(xiàn)了勾選的效果,繼續(xù)實(shí)現(xiàn)勾選后的 hover 樣式。勾選后在 hover 時(shí),勾選框的外層有一個(gè)與主題色相同的外層陰影效果:
這里我們依然使用 group 選擇器來(lái)設(shè)置 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) ,前面幾個(gè)設(shè)置陰影大小的參數(shù)很容易理解,但是后面陰影顏色的實(shí)現(xiàn)大家可能比較陌生,單獨(dú)解釋一下:
我這里用法的含義是在 srgb 的色彩模式下,將主題色(token(colors.colorPalette.600)) 與透明色(transparent),以 40% 的比例進(jìn)行混合,最終合成的顏色就是 40% 透明度的主題色。 color-mix() 函數(shù)是 pandaCSS 中推薦用戶用于為內(nèi)置顏色設(shè)置透明度的方法,除此以外并沒有發(fā)現(xiàn)其他更簡(jiǎn)便的方式。
最后我們完善一下勾選框的雙向綁定邏輯邏輯,
實(shí)現(xiàn)的代碼如下:
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 實(shí)現(xiàn)一個(gè)超絲滑的勾選框組件
原文鏈接:https://juejin.cn/post/7295954109404463155
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。