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
選是由多個單選項組成的選擇控件,獲取用戶針對某個事情的唯一結果。
常用場景有“微信APP-我-個人信息-設置性別”、“iOS設置-通知-顯示預覽”等。
單選功能通常包含標題和多個單選項,每個單選項由選項名稱和單選按鈕。
(1)先畫標題。從默認元件庫拖動“文本標簽”到工作區,或者直接把“頁面名稱”作為標題。
(2)再畫選項名稱。從默認元件庫拖動“矩形1”到工作區,修改尺寸為375*40px,雙擊輸入文字“選項名稱”,設置左填充為15px這樣展示效果更妥當。
(3)再畫單選按鈕。從默認元件庫拖動“文本標簽”到“選項名稱”的右邊,雙擊輸入“√”,修改尺寸為40*40px,設置對齊方式為左右居中和垂直居中。
(4)復制單選名稱2份,依次排列。
(5)生成原型HTML并在瀏覽器中查看效果。
單選功能的常見交互效果:點擊任一單選按鈕自動變為選中狀態,同時其他單選按鈕變成未選中狀態。選中狀態和未選中狀態的樣式是不一樣的。
(6)繼承上面的“無交互”步驟,從第四步開始繼續畫“有交互”。設置按鈕的未選中狀態,設置文本顏色為白色。
(7)設置按鈕的選中狀態,點擊“交互樣式-選中”,選中字體顏色設置為#333333。
(8)設置按鈕為選項組。選擇按鈕設置選項組名稱為“單選”或者其他名稱,這樣代表該組的按鈕同時只能有一個選中狀態。
(9)選中標題和按鈕,然后右鍵點擊“組合”,然后命名為“單選項”。
(10)設置單選項的交互。點擊該組合,設置“鼠標單擊時”事件,添加動作“選中”,組織動作“當前元件”。
(11)復制單選項2份,依次排列。
(12)選中第一個按鈕,打勾選中,這樣生成原型之后默認選中它。
(13)生成原型HTML并在瀏覽器中查看效果。
不同場景下的單選功能,標題不一樣,樣式相對固定。
根據多年PM經驗,總結出3種常用的“單選”,添加到APP功能庫。
單選(打勾)
單選(主流)
單選(傳統)
單選功能同一時間只有一個選中狀態。
單選功能可以設計多種樣式,另外選擇器也可充當單選功能。
我們百度搜索我們想要的文章時,好不容易找到了我們想要的文章,點開復制,卻發現文章被鎖定,像下面這種情況,復制需要收費,面對這樣的情況,教你一招解決,免費復制自己想要的文章。
首先我們需要找到我們所要復制的文章,按電腦上的F12按鈕,打開如同所示的頁面
然后按F1按鈕
再往下翻,找到Debugger下面的禁用JavaScript,進行打勾
千萬不要將旁邊的框框刪去,這樣就可以免費復制了
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
*請認真填寫需求信息,我們會在24小時內與您取得聯系。