BUG:#154863 (update)新增电池动态图标组件、更新电池2x1卡片组件

This commit is contained in:
wangchangqi 2023-01-10 13:39:50 +08:00
parent c3d095f9b4
commit 483be78ab6
11 changed files with 944 additions and 68 deletions

View File

@ -0,0 +1,43 @@
# 电池功能组件
## 描述
显示电池卡片 UI
## 接口
## 大小规格
提供 2x1, 1x2, 1x1 大小规格
## 示意图
```
┌───────────────────────────────┐
<star-battery-rect-card>
├───────────────────────────────┤
│ ┌───────bg──────┐ │
│ │ ┌─text───┐ │ ┌─icon────┐ │
│ │ │ 100 % │ │ │ thunder │ │
│ │ └────────┘ │ └─────────┘ │
│ └───────────────┘ │
└───────────────────────────────┘
┌───────────────────────────────┐
<star-battery-square-card>
├───────────────────────────────┤
│ ┌─────circle──────┐ │
│ │ ┌─icon────┐ │ │
│ │ │ thunder │ │ │
│ │ └─────────┘ │ │
│ │ ┌─text────┐ │ │
│ │ │ 100 % │ │ │
│ │ └─────────┘ │ │
│ └─────────────────┘ │
└───────────────────────────────┘
┌───────────────────────────┐
<star-battery-icon>
│ ┌─text───┐ ┌─icon────┐ │
│ │ 100 % │ │ thunder │ │
│ └────────┘ └─────────┘ │
└───────────────────────────┘
```

View File

@ -0,0 +1,35 @@
export type BatteryThemeType = 'dm' | 'lm'
export type BatteryMode = 'power-normal' | 'power-save'
export enum BatteryHealth {
'Good',
'Overheat',
'Cold',
'Warm',
'Cool',
'Unknown',
}
export type BatteryEventType =
| 'chargingchange'
| 'chargingtimechange'
| 'dischargingtimechange'
| 'levelchange'
| 'batteryhealthchange'
export interface BatteryManager extends EventTarget {
readonly charging: boolean
readonly chargingTime: number
readonly dischargingTime: number
readonly level: number
readonly temperature: number
readonly health: BatteryHealth
readonly present: boolean
onchargingchange: (ev: Event) => any
onchargingtimechange: (ev: Event) => any
ondischargingtimechange: (ev: Event) => any
onlevelchange: (ev: Event) => any
onbatteryhealthchange: (ev: Event) => any
}

View File

@ -0,0 +1,46 @@
# 电池图标
## 描述
可用于状态栏、指示器等地方
## 电池图标显示模式
1. 常规模式
1. `(常规)(充电图标)(绿色)`
2. `(常规)(百分比)(灰色)`
3. `(常规)(百分比)(红色)`
4. `(常规)(灰色)`
5. `(常规)(红色)`
2. 省电模式
1. `(省电)(充电图标)(黄色)`
2. `(省电)(百分比)(黄色)`
3. `(省电)(黄色)`
## 显示分支流程
1. 是否在充电
1. 是,是什么模式
1. 常规模式,`(常规)(充电图标)(绿色)`
2. 省电模式,`(省电)(充电图标)(黄色)`
2. 否,是否有百分比
1. 有,是什么模式
1. 常规模式,电量是否大于等于 20%
1. 是,`(常规)(百分比)(灰色)`
2. 否,`(常规)(百分比)(红色)`
2. 省电模式,`(省电)(百分比)(黄色)`
2. 否,是什么模式
1. 常规模式,电量是否大于等于 20%
1. 是,`(常规)(灰色)`
2. 否,`(常规)(红色)`
2. 省电模式,`(省电)(黄色)`
## 接口属性
| 字段 | 类型 | 值 | 优先级 | 备注 |
| ---------- | ------- | ----------------------- | ------ | --------------------------------------------------------- |
| charge | boolean | false/true | 1 | 指示充电 |
| theme | string | light/dark | 1 | 指示浅色/深色模式,控制电池边框、充电图标、百分比数字颜色 |
| percentage | boolean | false/true | 2 | 指示充电指示百分比 |
| percents | number | [0,100] | 2 | 指示充电指示百分比 |
| mode | string | power-normal/power-save | 3 | 指示模式,和图标颜色关联 |

View File

@ -0,0 +1,167 @@
import {
css,
customElement,
html,
ifDefined,
property,
state,
LitElement,
} from '@star-web-components/base'
import {BatteryMode, BatteryThemeType} from '../base'
@customElement('battery-dynamic-icon')
export class BatteryDynamicIcon extends LitElement {
@property({type: Boolean}) charge!: boolean
@property({type: Boolean}) percentage!: boolean
@property({type: String}) theme!: BatteryThemeType
/**
* : [0, 100]
*/
@property({type: Number}) percents = 100
@property({type: String}) mode: BatteryMode = 'power-normal'
@state() lowpower = false
attributeChangedCallback(name: string, _old: string, value: string) {
super.attributeChangedCallback(name, _old, value)
if (name === 'percents') {
const _value = Number(value)
if (_value > 100 || _value < 0) {
throw new Error('Set wrong number on battery-icons percents')
} else {
this.lowpower = _value < 20
}
this.style.setProperty('--battery-percents', String(this.percents))
}
}
render() {
return html`
<svg
mode=${this.mode}
theme=${ifDefined(this.theme)}
?charge=${this.charge}
?percentage=${this.percentage}
?lowpower=${this.lowpower}
fill="none"
viewBox="0 0 36 36"
xmlns="http://www.w3.org/2000/svg"
shape-rendering="geometricPrecision"
>
<g>
<!-- , :[4, 24] -->
<rect
id="rect-width"
fill="var(--battery-background)"
x="4"
y="13"
width="24"
height="10"
rx="1.5"
/>
<!-- -->
<text
id="percents-text"
x="16"
y="19.7"
dominant-baseline="middle"
text-anchor="middle"
font-family="OPPOSans, sans-serif"
fill="var(--percents-color)"
>
${this.percents}
</text>
</g>
<g fill="var(--border-color)">
<!-- -->
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M27 11H5C3.34315 11 2 12.3431 2 14V22C2 23.6569 3.34315 25 5 25H27C28.6569 25 30 23.6569 30 22V14C30 12.3431 28.6569 11 27 11ZM5 9C2.23858 9 0 11.2386 0 14V22C0 24.7614 2.23858 27 5 27H27C29.7614 27 32 24.7614 32 22V14C32 11.2386 29.7614 9 27 9H5Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M33 14.1579C33 14.0707 33.0707 14 33.1579 14C34.7275 14 36 15.2725 36 16.8421V19.1579C36 20.7275 34.7275 22 33.1579 22C33.0707 22 33 21.9293 33 21.8421V14.1579Z"
/>
<!-- -->
<path
id="thunder-icon"
d="M17 16.6H21L14 25L15 19.4H11L18 11L17 16.6Z"
/>
</g>
<style></style>
</svg>
`
}
static styles = css`
svg {
width: 100%;
height: 100%;
font-size: 12px;
--green: #02b56d;
--yellow: #f5c125;
--red: #ec4949;
--brown: rgba(51, 51, 51, 0.3);
--border-color: #333333;
--percents-color: #262626;
--battery-background: var(--brown);
--rect-width: var(--battery-width, 24);
}
svg[theme='dm'] {
--border-color: #f4f4f4;
--percents-color: #f0f0f0;
--brown: rgba(244, 244, 244, 0.3);
}
svg[mode='power-normal'] {
--battery-background: var(--brown);
}
svg[mode='power-normal'][charge] {
--battery-background: var(--green);
}
svg[mode='power-normal'][lowpower]:not([charge]) {
--battery-background: var(--red);
}
svg[mode='power-save'] {
--battery-background: var(--yellow);
}
rect#rect-width {
width: calc(var(--battery-percents, 100) * 24px / 100);
}
path#thunder-icon,
text#percents-text {
display: none;
}
svg[charge] path#thunder-icon,
svg[percentage]:not([charge]) text#percents-text {
display: block;
}
@media (prefers-color-scheme: dark) {
svg {
--border-color: #f4f4f4;
--percents-color: #f0f0f0;
--brown: rgba(244, 244, 244, 0.3);
}
}
`
}
declare global {
interface HTMLElementTagNameMap {
'battery-dynamic-icon': BatteryDynamicIcon
}
}

View File

@ -0,0 +1,2 @@
export * from './rect-card/rect-card.js'
export * from './dynamic-icon/icon.js'

View File

@ -0,0 +1,28 @@
{
"name": "@star-web-components/battery",
"version": "0.0.1",
"description": "",
"type": "module",
"main": "./index.js",
"module": "./index.js",
"exports": {
".": {
"default": "./index.js"
},
"./index": {
"default": "./index.js"
},
"./package.json": "./package.json",
"./base": {
"default": "./base.js"
},
"./rect-card": {
"default": "./rect-card/rect-card.js"
},
"./dynamic-icon/icon.js": {
"default": "./dynamic-icon/icon.js"
}
},
"author": "",
"license": "ISC"
}

View File

@ -0,0 +1,287 @@
import {
css,
customElement,
html,
ifDefined,
property,
state,
LitElement,
} from '@star-web-components/base'
import {BatteryThemeType} from '../base'
@customElement('battery-rect-card')
export class BatteryRectCard extends LitElement {
/**
* charge时,
*/
@property({type: Boolean, reflect: true}) charge!: boolean
@property({type: String}) theme!: BatteryThemeType
/**
* : [0, 100]
*/
@property({type: Number}) percents = 100
@state() lowpower = false
/**
* , 20,(436-20),
*
* : 'M0,20 a20 20, 0, 0, 1, 20,-20 h396 a20 20, 0, 0, 1, 20,20 v120 a20 20, 0, 0, 1, -20,20 h-396 a20 20, 0, 0, 1, -20,-20Z'
*/
private computeBatteryPath = (batteryPercents: number) => {
const [low, high] = [
Math.floor((20 * 100) / 436),
Math.ceil((416 * 100) / 436),
]
console.log(batteryPercents, typeof batteryPercents)
if (batteryPercents >= high) {
const dx = (436 * batteryPercents) / 100 - 20 - 396
const dy = Math.sqrt(400 - dx * dx)
const verticalHeight = 160 - (20 - dy) * 2
return `M0,20 a20 20, 0, 0, 1, 20,-20 h396 a20 20, 0, 0, 1, ${dx},${
20 - dy
} v${verticalHeight} a20 20, 0, 0, 1, -${dx},${
20 - dy
} h-396 a20 20, 0, 0, 1, -20,-20Z`
} else if (batteryPercents <= low) {
const dx = (436 * batteryPercents) / 100
const dy = Math.sqrt(400 - (20 - dx) * (20 - dx))
const verticalHeight = 160 - (20 - dy) * 2
return `M0,20 a20 20, 0, 0, 1, ${dx},-${dy} h0 a20 20, 0, 0, 1, 0,-0 v${verticalHeight} a20 20, 0, 0, 1, -${dx},-${dy} h-0 a20 20, 0, 0, 1, -20,-20Z`
} else {
const horizontalWidth = (436 * batteryPercents) / 100 - 20
return `M0,20 a20 20, 0, 0, 1, 20,-20 h${horizontalWidth} a20 20, 0, 0, 1, 0,0 v160 a20 20, 0, 0, 1, 0,0 h-${horizontalWidth} a20 20, 0, 0, 1, -20,-20Z`
}
}
attributeChangedCallback(name: string, _old: string, value: string) {
super.attributeChangedCallback(name, _old, value)
if (name === 'percents') {
const _value = Number(value)
if (_value > 100 || _value < 0) {
throw new Error('Set wrong number on battery-icons percents')
} else {
this.lowpower = _value < 20
}
}
}
render() {
return html`
<svg
theme=${ifDefined(this.theme)}
?lowpower=${this.lowpower}
?charge=${this.charge}
viewBox="0 0 436 160"
fill="none"
xmlns="http://www.w3.org/2000/svg"
shape-rendering="geometricPrecision"
>
<!-- -->
<rect width="436" height="160" rx="20" fill="var(--card-bg)" />
<!-- -->
<path
d="${this.computeBatteryPath(this.percents)}"
fill="var(--battery-bg)"
/>
<!-- -->
<rect
x="1"
y="1"
width="434"
height="158"
rx="19"
stroke="white"
stroke-opacity="0.15"
stroke-width="2"
/>
<!-- -->
<path
id="thunder-icon"
fill-rule="evenodd"
clip-rule="evenodd"
d="M389.832 51.2237C389.252 50.8637 388.502 50.9437 388.012 51.4237L365.612 72.9837C365.072 73.5037 364.872 74.2737 365.082 74.9837C365.292 75.6937 365.872 76.2337 366.602 76.3837L378.132 78.7237L373.252 94.9737C373.052 95.6237 373.322 96.3337 373.912 96.6837C374.492 97.0437 375.242 96.9637 375.732 96.4837L398.132 74.9237C398.672 74.4037 398.872 73.6337 398.662 72.9237C398.452 72.2137 397.872 71.6737 397.142 71.5237L385.612 69.1837L390.492 52.9337C390.692 52.2837 390.422 51.5737 389.832 51.2237Z"
fill="#EBC883"
/>
<!-- -->
<g id="charge-bubble">
<circle
cx="249.697"
cy="42.6969"
r="12"
transform="rotate(75 249.697 42.6969)"
fill="url(#linear_white_bubble1)"
fill-opacity="0.5"
></circle>
<circle
cx="185.023"
cy="126.023"
r="9"
transform="rotate(75 185.023 126.023)"
fill="url(#linear_white_bubble2)"
fill-opacity="0.3"
></circle>
<circle
cx="55.1236"
cy="28.0519"
r="5"
transform="rotate(75 55.1236 28.0519)"
fill="url(#linear_white_bubble3)"
fill-opacity="0.3"
></circle>
</g>
<!-- -->
<!-- svg字-UI稿 -->
<g fill="var(--text-color)">
<!-- <path d="M64.75 59.55V64.5L50.8 101H42.85L57.6 65.7H37.1V59.55H64.75ZM99.3867 88.75C99.3867 91.2833 98.7867 93.5333 97.5867 95.5C96.3867 97.4667 94.6867 98.9833 92.4867 100.05C90.2867 101.15 87.7367 101.7 84.8367 101.7C81.9367 101.7 79.3867 101.15 77.1867 100.05C74.9867 98.9833 73.2701 97.4667 72.0367 95.5C70.8367 93.5333 70.2367 91.2833 70.2367 88.75C70.2367 86.45 70.8034 84.4167 71.9367 82.65C73.0701 80.8833 74.6534 79.4833 76.6867 78.45C75.1867 77.5167 74.0201 76.35 73.1867 74.95C72.3867 73.55 71.9867 72 71.9867 70.3C71.9867 68.1 72.5034 66.1333 73.5367 64.4C74.6034 62.6667 76.1034 61.3167 78.0367 60.35C79.9701 59.3833 82.2367 58.9 84.8367 58.9C87.4367 58.9 89.7034 59.3833 91.6367 60.35C93.5701 61.3167 95.0534 62.6667 96.0867 64.4C97.1201 66.1333 97.6367 68.1 97.6367 70.3C97.6367 72 97.2367 73.55 96.4367 74.95C95.6367 76.35 94.4867 77.5167 92.9867 78.45C94.9867 79.4833 96.5534 80.8833 97.6867 82.65C98.8201 84.4167 99.3867 86.45 99.3867 88.75ZM78.7367 70.15C78.7367 71.8833 79.2867 73.2833 80.3867 74.35C81.5201 75.3833 83.0034 75.9 84.8367 75.9C86.6701 75.9 88.1367 75.3833 89.2367 74.35C90.3701 73.2833 90.9367 71.8833 90.9367 70.15C90.9367 68.3833 90.3701 66.9833 89.2367 65.95C88.1367 64.8833 86.6701 64.35 84.8367 64.35C83.0034 64.35 81.5201 64.8833 80.3867 65.95C79.2867 66.9833 78.7367 68.3833 78.7367 70.15ZM92.4367 88.55C92.4367 86.3167 91.7534 84.55 90.3867 83.25C89.0201 81.9167 87.1701 81.25 84.8367 81.25C82.5034 81.25 80.6534 81.9167 79.2867 83.25C77.9201 84.55 77.2367 86.3167 77.2367 88.55C77.2367 90.75 77.9201 92.5167 79.2867 93.85C80.6534 95.15 82.5034 95.8 84.8367 95.8C87.1701 95.8 89.0201 95.15 90.3867 93.85C91.7534 92.5167 92.4367 90.75 92.4367 88.55Z" /> -->
<text
id="percents-text"
x="15%"
y="52.7%"
dominant-baseline="middle"
text-anchor="middle"
font-family="OPPOSans, sans-serif"
font-weight="bold"
font-size="50px"
>
${this.percents}
</text>
<path
d="M115.616 87.654C114.108 87.654 112.921 87.1427 112.054 86.12C111.187 85.0973 110.754 83.6933 110.754 81.908C110.754 80.1227 111.187 78.7273 112.054 77.722C112.921 76.6993 114.108 76.188 115.616 76.188C117.107 76.188 118.285 76.6993 119.152 77.722C120.019 78.7273 120.452 80.1227 120.452 81.908C120.452 83.6933 120.019 85.0973 119.152 86.12C118.285 87.1427 117.107 87.654 115.616 87.654ZM117.462 98.08H114.264L126.9 76.526H130.098L117.462 98.08ZM115.616 78.736C114.957 78.736 114.455 79.0047 114.108 79.542C113.779 80.0793 113.614 80.868 113.614 81.908C113.614 82.948 113.779 83.7453 114.108 84.3C114.455 84.8373 114.957 85.106 115.616 85.106C116.257 85.106 116.743 84.8373 117.072 84.3C117.419 83.7453 117.592 82.948 117.592 81.908C117.592 80.868 117.419 80.0793 117.072 79.542C116.743 79.0047 116.257 78.736 115.616 78.736ZM128.746 86.978C130.254 86.978 131.433 87.4893 132.282 88.512C133.149 89.5347 133.582 90.9387 133.582 92.724C133.582 94.5093 133.149 95.9047 132.282 96.91C131.433 97.9327 130.254 98.444 128.746 98.444C127.255 98.444 126.077 97.9327 125.21 96.91C124.343 95.9047 123.91 94.5093 123.91 92.724C123.91 90.9387 124.343 89.5347 125.21 88.512C126.077 87.4893 127.255 86.978 128.746 86.978ZM128.746 95.896C129.405 95.896 129.899 95.6273 130.228 95.09C130.575 94.5527 130.748 93.764 130.748 92.724C130.748 91.6667 130.575 90.8693 130.228 90.332C129.899 89.7947 129.405 89.526 128.746 89.526C128.087 89.526 127.593 89.7947 127.264 90.332C126.935 90.8693 126.77 91.6667 126.77 92.724C126.77 93.764 126.935 94.5527 127.264 95.09C127.611 95.6273 128.105 95.896 128.746 95.896Z"
/>
</g>
<defs>
<linearGradient
id="linear_white"
x1="11"
y1="7"
x2="94.2619"
y2="255.817"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#F5F0F5" />
<stop offset="0.2262" stop-color="#FAFAFA" />
<stop offset="1" stop-color="#D5DAF2" />
</linearGradient>
<linearGradient
id="linear_green"
x1="68.5438"
y1="11.0167"
x2="117.935"
y2="175.493"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#6BE4D0" />
<stop offset="1" stop-color="#10A775" />
</linearGradient>
<radialGradient
id="linear_black"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(84.475 29.0909) rotate(22.7272) scale(236.352 122.564)"
>
<stop stop-color="#4B4E52" />
<stop offset="1" stop-color="#302F33" />
</radialGradient>
<linearGradient
id="linear_red"
x1="27.5"
y1="11.0167"
x2="117.059"
y2="96.5322"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#EF8B76" />
<stop offset="1" stop-color="#EB5A5A" />
</linearGradient>
<linearGradient
id="linear_white_bubble1"
x1="249.697"
y1="30.6969"
x2="249.697"
y2="54.6969"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient
id="linear_white_bubble2"
x1="185.023"
y1="117.023"
x2="185.023"
y2="135.023"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient
id="linear_white_bubble3"
x1="55.1236"
y1="23.0519"
x2="55.1236"
y2="33.0519"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
</defs>
</svg>
`
}
static styles = css`
:host {
width: 100%;
height: 100%;
}
svg {
--text-color: white;
--battery-bg: url(#linear_green);
--card-bg: url(#linear_white);
}
svg[theme='dm'] {
--card-bg: url(#linear_black);
}
svg[lowpower] {
--text-color: #ebc883;
--battery-bg: url(#linear_red);
}
svg:not([charge]) #charge-bubble {
display: none;
}
@media (prefers-color-scheme: dark) {
svg {
--card-bg: url(#linear_black);
}
}
`
}
declare global {
interface HTMLElementTagNameMap {
'battery-rect-card': BatteryRectCard
}
}

View File

@ -0,0 +1,104 @@
<svg theme="dm" low-power="" viewBox="0 0 436 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 卡片底色 -->
<rect width="436" height="160" rx="20" fill="var(--card-bg)" />
<!-- 电量底色 -->
<!-- <path
d="M0,20 a20 20, 0, 0, 1, 5.86,-14.14 v148.28 a20 20, 0, 0, 1, -5.86,-14.14Z"
fill="var(--battery-bg)" /> -->
<!-- <path
d="M0,20 a20 20, 0, 0, 1, 20,-20 h350 a20 20, 0, 0, 1, 0,0 v160 a20 20, 0, 0, 1, 0,0 h-350 a20 20, 0, 0, 1, -20,-20Z"
fill="var(--battery-bg)" /> -->
<!-- <path
d="M0,20 a20 20, 0, 0, 1, 20,-20 h396 a20 20, 0, 0, 1, 14.14,5.86 v148.28 a20 20, 0, 0, 1, -14.14,5.86 h-396 a20 20, 0, 0, 1, -20,-20Z"
fill="var(--battery-bg)" /> -->
<path
d="M0,20 a20 20, 0, 0, 1, 20,-20 h396 a20 20, 0, 0, 1, 20,20 v120 a20 20, 0, 0, 1, -20,20 h-396 a20 20, 0, 0, 1, -20,-20Z"
fill="var(--battery-bg)" />
<!-- 边框 -->
<rect x="1" y="1" width="434" height="158" rx="19" stroke="white" stroke-opacity="0.15" stroke-width="2" />
<!-- 雷电图标 -->
<path id="thunder-icon" fill-rule="evenodd" clip-rule="evenodd"
d="M389.832 51.2237C389.252 50.8637 388.502 50.9437 388.012 51.4237L365.612 72.9837C365.072 73.5037 364.872 74.2737 365.082 74.9837C365.292 75.6937 365.872 76.2337 366.602 76.3837L378.132 78.7237L373.252 94.9737C373.052 95.6237 373.322 96.3337 373.912 96.6837C374.492 97.0437 375.242 96.9637 375.732 96.4837L398.132 74.9237C398.672 74.4037 398.872 73.6337 398.662 72.9237C398.452 72.2137 397.872 71.6737 397.142 71.5237L385.612 69.1837L390.492 52.9337C390.692 52.2837 390.422 51.5737 389.832 51.2237Z"
fill="#EBC883" />
<!-- 充电气泡 -->
<circle cx="249.697" cy="42.6969" r="12" transform="rotate(75 249.697 42.6969)" fill="url(#linear_white_bubble1)"
fill-opacity="0.5" />
<circle cx="185.023" cy="126.023" r="9" transform="rotate(75 185.023 126.023)" fill="url(#linear_white_bubble2)"
fill-opacity="0.3" />
<circle cx="55.1236" cy="28.0519" r="5" transform="rotate(75 55.1236 28.0519)" fill="url(#linear_white_bubble3)"
fill-opacity="0.3" />
<!---->
<!-- svg字-用于测试比对UI稿 -->
<g fill="var(--text-color)">
<!-- <path d="M64.75 59.55V64.5L50.8 101H42.85L57.6 65.7H37.1V59.55H64.75ZM99.3867 88.75C99.3867 91.2833 98.7867 93.5333 97.5867 95.5C96.3867 97.4667 94.6867 98.9833 92.4867 100.05C90.2867 101.15 87.7367 101.7 84.8367 101.7C81.9367 101.7 79.3867 101.15 77.1867 100.05C74.9867 98.9833 73.2701 97.4667 72.0367 95.5C70.8367 93.5333 70.2367 91.2833 70.2367 88.75C70.2367 86.45 70.8034 84.4167 71.9367 82.65C73.0701 80.8833 74.6534 79.4833 76.6867 78.45C75.1867 77.5167 74.0201 76.35 73.1867 74.95C72.3867 73.55 71.9867 72 71.9867 70.3C71.9867 68.1 72.5034 66.1333 73.5367 64.4C74.6034 62.6667 76.1034 61.3167 78.0367 60.35C79.9701 59.3833 82.2367 58.9 84.8367 58.9C87.4367 58.9 89.7034 59.3833 91.6367 60.35C93.5701 61.3167 95.0534 62.6667 96.0867 64.4C97.1201 66.1333 97.6367 68.1 97.6367 70.3C97.6367 72 97.2367 73.55 96.4367 74.95C95.6367 76.35 94.4867 77.5167 92.9867 78.45C94.9867 79.4833 96.5534 80.8833 97.6867 82.65C98.8201 84.4167 99.3867 86.45 99.3867 88.75ZM78.7367 70.15C78.7367 71.8833 79.2867 73.2833 80.3867 74.35C81.5201 75.3833 83.0034 75.9 84.8367 75.9C86.6701 75.9 88.1367 75.3833 89.2367 74.35C90.3701 73.2833 90.9367 71.8833 90.9367 70.15C90.9367 68.3833 90.3701 66.9833 89.2367 65.95C88.1367 64.8833 86.6701 64.35 84.8367 64.35C83.0034 64.35 81.5201 64.8833 80.3867 65.95C79.2867 66.9833 78.7367 68.3833 78.7367 70.15ZM92.4367 88.55C92.4367 86.3167 91.7534 84.55 90.3867 83.25C89.0201 81.9167 87.1701 81.25 84.8367 81.25C82.5034 81.25 80.6534 81.9167 79.2867 83.25C77.9201 84.55 77.2367 86.3167 77.2367 88.55C77.2367 90.75 77.9201 92.5167 79.2867 93.85C80.6534 95.15 82.5034 95.8 84.8367 95.8C87.1701 95.8 89.0201 95.15 90.3867 93.85C91.7534 92.5167 92.4367 90.75 92.4367 88.55Z" /> -->
<text id="percents-text" x="16%" y="52.5%" dominant-baseline="middle" text-anchor="middle"
font-family="OPPOSans, sans-serif" font-weight="bold" font-siZe="50px">
20
</text>
<path
d="M115.616 87.654C114.108 87.654 112.921 87.1427 112.054 86.12C111.187 85.0973 110.754 83.6933 110.754 81.908C110.754 80.1227 111.187 78.7273 112.054 77.722C112.921 76.6993 114.108 76.188 115.616 76.188C117.107 76.188 118.285 76.6993 119.152 77.722C120.019 78.7273 120.452 80.1227 120.452 81.908C120.452 83.6933 120.019 85.0973 119.152 86.12C118.285 87.1427 117.107 87.654 115.616 87.654ZM117.462 98.08H114.264L126.9 76.526H130.098L117.462 98.08ZM115.616 78.736C114.957 78.736 114.455 79.0047 114.108 79.542C113.779 80.0793 113.614 80.868 113.614 81.908C113.614 82.948 113.779 83.7453 114.108 84.3C114.455 84.8373 114.957 85.106 115.616 85.106C116.257 85.106 116.743 84.8373 117.072 84.3C117.419 83.7453 117.592 82.948 117.592 81.908C117.592 80.868 117.419 80.0793 117.072 79.542C116.743 79.0047 116.257 78.736 115.616 78.736ZM128.746 86.978C130.254 86.978 131.433 87.4893 132.282 88.512C133.149 89.5347 133.582 90.9387 133.582 92.724C133.582 94.5093 133.149 95.9047 132.282 96.91C131.433 97.9327 130.254 98.444 128.746 98.444C127.255 98.444 126.077 97.9327 125.21 96.91C124.343 95.9047 123.91 94.5093 123.91 92.724C123.91 90.9387 124.343 89.5347 125.21 88.512C126.077 87.4893 127.255 86.978 128.746 86.978ZM128.746 95.896C129.405 95.896 129.899 95.6273 130.228 95.09C130.575 94.5527 130.748 93.764 130.748 92.724C130.748 91.6667 130.575 90.8693 130.228 90.332C129.899 89.7947 129.405 89.526 128.746 89.526C128.087 89.526 127.593 89.7947 127.264 90.332C126.935 90.8693 126.77 91.6667 126.77 92.724C126.77 93.764 126.935 94.5527 127.264 95.09C127.611 95.6273 128.105 95.896 128.746 95.896Z" />
</g>
<defs>
<linearGradient id="linear_white" x1="11" y1="7" x2="94.2619" y2="255.817" gradientUnits="userSpaceOnUse">
<stop stop-color="#F5F0F5" />
<stop offset="0.2262" stop-color="#FAFAFA" />
<stop offset="1" stop-color="#D5DAF2" />
</linearGradient>
<linearGradient id="linear_green" x1="68.5438" y1="11.0167" x2="117.935" y2="175.493"
gradientUnits="userSpaceOnUse">
<stop stop-color="#6BE4D0" />
<stop offset="1" stop-color="#10A775" />
</linearGradient>
<radialGradient id="linear_black" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="translate(84.475 29.0909) rotate(22.7272) scale(236.352 122.564)">
<stop stop-color="#4B4E52" />
<stop offset="1" stop-color="#302F33" />
</radialGradient>
<linearGradient id="linear_red" x1="27.5" y1="11.0167" x2="117.059" y2="96.5322" gradientUnits="userSpaceOnUse">
<stop stop-color="#EF8B76" />
<stop offset="1" stop-color="#EB5A5A" />
</linearGradient>
<linearGradient id="linear_white_bubble1" x1="249.697" y1="30.6969" x2="249.697" y2="54.6969"
gradientUnits="userSpaceOnUse">
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient id="linear_white_bubble2" x1="185.023" y1="117.023" x2="185.023" y2="135.023"
gradientUnits="userSpaceOnUse">
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient id="linear_white_bubble3" x1="55.1236" y1="23.0519" x2="55.1236" y2="33.0519"
gradientUnits="userSpaceOnUse">
<stop stop-color="white" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
</defs>
<style>
svg {
--text-color: white;
--battery-bg: url(#linear_green);
--card-bg: url(#linear_white);
}
svg[theme='dm'] {
--card-bg: url(#linear_black);
}
svg[low-power] {
--text-color: #EBC883;
--battery-bg: url(#linear_red);
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,78 @@
<svg theme="dm" low-power="" charge="" viewBox="0 0 436 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 卡片底色 -->
<rect width="436" height="160" rx="20" fill="var(--card-bg)" />
<!-- 电量底色 -->
<path
d="M0,20 a20 20, 0, 0, 1, 5.86,-14.14 h0 a20 20, 0, 0, 1, 0, 0 v148.28 a20 20, 0, 0, 1, 0,0 h-0 a20 20, 0, 0, 1, -5.86,-14.14Z"
fill="var(--battery-bg)" />
<!-- <path
d="M0,20 a20 20, 0, 0, 1, 20,-20 h396 a20 20, 0, 0, 1, 14.14,5.86 v148.28 a20 20, 0, 0, 1, -14.14,5.86 h-396 a20 20, 0, 0, 1, -20,-20Z"
fill="var(--battery-bg)" /> -->
<!-- 边框 -->
<rect x="1" y="1" width="434" height="158" rx="19" stroke="white" stroke-opacity="0.15" stroke-width="2" />
<!-- 雷电图标 -->
<path id="thunder-icon" fill-rule="evenodd" clip-rule="evenodd"
d="M389.832 51.2237C389.252 50.8637 388.502 50.9437 388.012 51.4237L365.612 72.9837C365.072 73.5037 364.872 74.2737 365.082 74.9837C365.292 75.6937 365.872 76.2337 366.602 76.3837L378.132 78.7237L373.252 94.9737C373.052 95.6237 373.322 96.3337 373.912 96.6837C374.492 97.0437 375.242 96.9637 375.732 96.4837L398.132 74.9237C398.672 74.4037 398.872 73.6337 398.662 72.9237C398.452 72.2137 397.872 71.6737 397.142 71.5237L385.612 69.1837L390.492 52.9337C390.692 52.2837 390.422 51.5737 389.832 51.2237Z"
fill="#EBC883" />
<!---->
<!-- svg字-用于测试比对UI稿 -->
<g fill="var(--text-color)">
<!-- <path d="M64.75 59.55V64.5L50.8 101H42.85L57.6 65.7H37.1V59.55H64.75ZM99.3867 88.75C99.3867 91.2833 98.7867 93.5333 97.5867 95.5C96.3867 97.4667 94.6867 98.9833 92.4867 100.05C90.2867 101.15 87.7367 101.7 84.8367 101.7C81.9367 101.7 79.3867 101.15 77.1867 100.05C74.9867 98.9833 73.2701 97.4667 72.0367 95.5C70.8367 93.5333 70.2367 91.2833 70.2367 88.75C70.2367 86.45 70.8034 84.4167 71.9367 82.65C73.0701 80.8833 74.6534 79.4833 76.6867 78.45C75.1867 77.5167 74.0201 76.35 73.1867 74.95C72.3867 73.55 71.9867 72 71.9867 70.3C71.9867 68.1 72.5034 66.1333 73.5367 64.4C74.6034 62.6667 76.1034 61.3167 78.0367 60.35C79.9701 59.3833 82.2367 58.9 84.8367 58.9C87.4367 58.9 89.7034 59.3833 91.6367 60.35C93.5701 61.3167 95.0534 62.6667 96.0867 64.4C97.1201 66.1333 97.6367 68.1 97.6367 70.3C97.6367 72 97.2367 73.55 96.4367 74.95C95.6367 76.35 94.4867 77.5167 92.9867 78.45C94.9867 79.4833 96.5534 80.8833 97.6867 82.65C98.8201 84.4167 99.3867 86.45 99.3867 88.75ZM78.7367 70.15C78.7367 71.8833 79.2867 73.2833 80.3867 74.35C81.5201 75.3833 83.0034 75.9 84.8367 75.9C86.6701 75.9 88.1367 75.3833 89.2367 74.35C90.3701 73.2833 90.9367 71.8833 90.9367 70.15C90.9367 68.3833 90.3701 66.9833 89.2367 65.95C88.1367 64.8833 86.6701 64.35 84.8367 64.35C83.0034 64.35 81.5201 64.8833 80.3867 65.95C79.2867 66.9833 78.7367 68.3833 78.7367 70.15ZM92.4367 88.55C92.4367 86.3167 91.7534 84.55 90.3867 83.25C89.0201 81.9167 87.1701 81.25 84.8367 81.25C82.5034 81.25 80.6534 81.9167 79.2867 83.25C77.9201 84.55 77.2367 86.3167 77.2367 88.55C77.2367 90.75 77.9201 92.5167 79.2867 93.85C80.6534 95.15 82.5034 95.8 84.8367 95.8C87.1701 95.8 89.0201 95.15 90.3867 93.85C91.7534 92.5167 92.4367 90.75 92.4367 88.55Z" /> -->
<text id="percents-text" x="16%" y="52.5%" dominant-baseline="middle" text-anchor="middle"
font-family="OPPOSans, sans-serif" font-weight="bold" font-siZe="50px">
20
</text>
<path
d="M115.616 87.654C114.108 87.654 112.921 87.1427 112.054 86.12C111.187 85.0973 110.754 83.6933 110.754 81.908C110.754 80.1227 111.187 78.7273 112.054 77.722C112.921 76.6993 114.108 76.188 115.616 76.188C117.107 76.188 118.285 76.6993 119.152 77.722C120.019 78.7273 120.452 80.1227 120.452 81.908C120.452 83.6933 120.019 85.0973 119.152 86.12C118.285 87.1427 117.107 87.654 115.616 87.654ZM117.462 98.08H114.264L126.9 76.526H130.098L117.462 98.08ZM115.616 78.736C114.957 78.736 114.455 79.0047 114.108 79.542C113.779 80.0793 113.614 80.868 113.614 81.908C113.614 82.948 113.779 83.7453 114.108 84.3C114.455 84.8373 114.957 85.106 115.616 85.106C116.257 85.106 116.743 84.8373 117.072 84.3C117.419 83.7453 117.592 82.948 117.592 81.908C117.592 80.868 117.419 80.0793 117.072 79.542C116.743 79.0047 116.257 78.736 115.616 78.736ZM128.746 86.978C130.254 86.978 131.433 87.4893 132.282 88.512C133.149 89.5347 133.582 90.9387 133.582 92.724C133.582 94.5093 133.149 95.9047 132.282 96.91C131.433 97.9327 130.254 98.444 128.746 98.444C127.255 98.444 126.077 97.9327 125.21 96.91C124.343 95.9047 123.91 94.5093 123.91 92.724C123.91 90.9387 124.343 89.5347 125.21 88.512C126.077 87.4893 127.255 86.978 128.746 86.978ZM128.746 95.896C129.405 95.896 129.899 95.6273 130.228 95.09C130.575 94.5527 130.748 93.764 130.748 92.724C130.748 91.6667 130.575 90.8693 130.228 90.332C129.899 89.7947 129.405 89.526 128.746 89.526C128.087 89.526 127.593 89.7947 127.264 90.332C126.935 90.8693 126.77 91.6667 126.77 92.724C126.77 93.764 126.935 94.5527 127.264 95.09C127.611 95.6273 128.105 95.896 128.746 95.896Z" />
</g>
<defs>
<linearGradient id="linear_white" x1="11" y1="7" x2="94.2619" y2="255.817" gradientUnits="userSpaceOnUse">
<stop stop-color="#F5F0F5" />
<stop offset="0.2262" stop-color="#FAFAFA" />
<stop offset="1" stop-color="#D5DAF2" />
</linearGradient>
<linearGradient id="linear_green" x1="68.5438" y1="11.0167" x2="117.935" y2="175.493"
gradientUnits="userSpaceOnUse">
<stop stop-color="#6BE4D0" />
<stop offset="1" stop-color="#10A775" />
</linearGradient>
<radialGradient id="linear_black" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="translate(84.475 29.0909) rotate(22.7272) scale(236.352 122.564)">
<stop stop-color="#4B4E52" />
<stop offset="1" stop-color="#302F33" />
</radialGradient>
<linearGradient id="linear_red" x1="27.5" y1="11.0167" x2="117.059" y2="96.5322" gradientUnits="userSpaceOnUse">
<stop stop-color="#EF8B76" />
<stop offset="1" stop-color="#EB5A5A" />
</linearGradient>
</defs>
<style>
svg {
--text-color: white;
--battery-bg: url(#linear_green);
--card-bg: url(#linear_white);
}
svg[theme='dm'] {
--card-bg: url(#linear_black);
}
svg[low-power] {
--text-color: #EBC883;
--battery-bg: url(#linear_red);
}
svg:not([charge]) path#thunder-icon {
display: none;
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -1,40 +1,132 @@
import {html, LitElement, CSSResultArray, css, PropertyValueMap} from 'lit'
import {customElement, query} from 'lit/decorators.js'
import {sharedStyles} from '../../../components/battery/battery-styles'
import {html, LitElement, css} from 'lit'
import {customElement, query, state} from 'lit/decorators.js'
import '../../../components/battery/rect-card/rect-card'
import '../../../components/battery/dynamic-icon/icon'
import {BatteryDynamicIcon} from '../../../components/battery/dynamic-icon/icon'
import {BatteryMode, BatteryThemeType} from '../../../components/battery/base'
@customElement('panel-battery')
export class PanelBattery extends LitElement {
@query('#container') container!: HTMLElement
@query('star-battery') battery!: HTMLElement
@query('battery-dynamic-icon') batteryDynamicIcon!: BatteryDynamicIcon
constructor() {
super()
const _addEventListener = Element.prototype.addEventListener
Element.prototype.addEventListener = function (
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
) {
console.log(this, type)
_addEventListener.call(this, type, listener, options)
}
}
@state() percents = 100
@state() theme!: BatteryThemeType
@state() percentage!: Boolean
@state() mode!: BatteryMode
@state() charge!: Boolean
render() {
return html`
<div id="container">
<star-battery charge></star-battery>
<div id="控制项">
<star-li
type="embed-switch"
label="电池图标显示模式"
description="常规模式"
split
>
<star-switch
slot="switch"
@change=${(e: any) => {
const bool = e.target.checked
const parent = e.target.parentElement
parent.description = bool ? '省电模式' : '常规模式'
this.mode = bool ? 'power-save' : 'power-normal'
}}
></star-switch>
</star-li>
<star-li
type="embed-switch"
label="打开充电"
description="未充电"
split
>
<star-switch
slot="switch"
@change=${(e: any) => {
const bool = e.target.checked
const parent = e.target.parentElement
parent.description = bool ? '充电' : '未充电'
this.charge = bool
}}
></star-switch>
</star-li>
<star-li
type="switch"
label="百分比显示"
@enabled=${() => (this.percentage = true)}
@disabled=${() => (this.percentage = false)}
></star-li>
<star-li
type="switch"
label="深色模式"
@enabled=${() => (this.theme = 'dm')}
@disabled=${() => (this.theme = 'lm')}
></star-li>
<star-li type="embed-slider" label="电量大小">
<star-slider
slot="slider"
endValue="100"
@star-slider-change=${(e: any) => (this.percents = e.detail.value)}
></star-slider>
</star-li>
</div>
<div style="display:flex;flex-direction: column;">
<battery-dynamic-icon
percents=${this.percents}
theme=${this.theme}
mode=${this.mode}
?percentage=${this.percentage}
?charge=${this.charge}
></battery-dynamic-icon>
<battery-rect-card
percents="${this.percents}"
theme=${this.theme}
?charge=${this.charge}
></battery-rect-card>
</div>
`
}
protected firstUpdated(
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
;(window as any).battery = this.battery
}
public static override get styles(): CSSResultArray {
return [
sharedStyles,
css`
static styles = css`
:host {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
#container {
height: 60vh;
width: 50vw;
battery-dynamic-icon,
battery-rect-card {
margin: auto;
}
`,
]
battery-rect-card {
width: 500px;
}
battery-dynamic-icon {
width: 250px;
}
`
}
declare global {

View File

@ -1,11 +1,26 @@
import GaiaWidget from '../gaia-widget'
import '../../components/battery/battery'
import {StarBattery} from '../../components/battery/battery'
import {customElement, query} from 'lit/decorators.js'
import {css, html} from 'lit'
import {customElement, query, state} from 'lit/decorators.js'
import GaiaWidget from '../gaia-widget'
import '../../components/battery/rect-card/rect-card'
import {BatteryRectCard} from '../../components/battery/rect-card/rect-card'
import {BatteryManager} from '../../components/battery/base'
declare global {
interface Navigator {
getBattery: () => Promise<BatteryManager>
}
}
@customElement('gaia-battery')
class BatteryWidget extends GaiaWidget {
@query('battery-rect-card') batteryRectCard!: BatteryRectCard
@state() charge = false
@state() percents = 100
batteryManager!: BatteryManager
constructor({
url,
appName,
@ -27,25 +42,22 @@ class BatteryWidget extends GaiaWidget {
url: url || 'js/widgets/battery.js',
appName: appName || 'homescreen',
origin: origin || 'http://homescreen.localhost/manifest.webmanifest',
size: size || [2, 2],
size: size || [1, 2],
widgetType: widgetType || 'battery',
widgetName,
params,
})
}
@query('star-battery') battery!: StarBattery
_battery: any
init = async () => {
// @ts-ignore
this._battery = await navigator.getBattery()
this.percent = this._battery.level * 100
this.battery.charge = this._battery.charging
this._battery.addEventListener('levelchange', this)
this._battery.addEventListener('chargingchange', this)
this.batteryManager = await navigator.getBattery()
this.percents = this.batteryManager.level * 100
this.charge = this.batteryManager.charging
this.lifeCycle = 'initialized'
this.percent = this._battery.level * 100
this.battery.charge = this._battery.charging
this.batteryManager.addEventListener('levelchange', this)
this.batteryManager.addEventListener('chargingchange', this)
}
firstUpdated = async () => {
@ -55,41 +67,23 @@ class BatteryWidget extends GaiaWidget {
handleEvent(event: Event): void {
switch (event.type) {
case 'levelchange':
this.percent = this._battery.level * 100
this.percents = this.batteryManager.level * 100
break
case 'chargingchange':
this.battery.charge = this._battery.charging
this.charge = this.batteryManager.charging
break
}
}
get percent() {
return this.battery.percent
}
set percent(value) {
this.battery.percent = value
}
get charge() {
return this.battery.charge
}
set charge(value) {
// this.battery.charge = !!value
if (value) {
setTimeout(() => {
this.battery.charge = false
})
}
this.battery.charge = value
}
render() {
return html`
<star-battery></star-battery>
<battery-rect-card
percents="${this.percents}"
?charge=${this.charge}
></battery-rect-card>
`
}
static override get styles() {
return [
css`