# 样式处理
PE引擎使用Less作为CSS预处理器,提供了强大而灵活的样式管理方案。每个场景可以有对应的样式文件,确保样式的作用域隔离和可维护性。
## Less预处理器
Less是一种向后兼容CSS的语言扩展,为CSS添加了变量、嵌套、混合等功能,让样式编写更加高效和可维护。
### 变量
使用变量来存储常用的值:
```less
// 定义变量
@primary-color: #3498db;
@secondary-color: #2ecc71;
@font-size-large: 18px;
@border-radius: 4px;
// 使用变量
.header {
background-color: @primary-color;
font-size: @font-size-large;
border-radius: @border-radius;
}
```
### 嵌套
Less支持嵌套语法,让样式结构更清晰:
```less
.navbar {
background-color: #34495e;
// 嵌套选择器
.nav-item {
color: white;
padding: 10px 15px;
// 伪类嵌套
&:hover {
background-color: #2c3e50;
}
// 子元素嵌套
.icon {
margin-right: 5px;
}
}
}
```
### 混合(Mixins)
混合允许你定义可复用的样式块:
```less
// 定义混合
.border-radius(@radius: 4px) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
.box-shadow(@x: 0, @y: 0, @blur: 10px, @color: rgba(0,0,0,0.1)) {
box-shadow: @arguments;
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
}
// 使用混合
.button {
.border-radius(8px);
.box-shadow(0, 2px, 5px, rgba(0,0,0,0.2));
}
```
### 函数
Less提供了丰富的内置函数:
```less
// 颜色函数
.button {
background-color: #3498db;
// 变暗10%
&:hover {
background-color: darken(#3498db, 10%);
}
// 变亮10%
&:active {
background-color: lighten(#3498db, 10%);
}
}
// 数学函数
.progress-bar {
width: percentage(0.5); // 50%
height: unit(20, px); // 20px
}
```
## 场景样式隔离
PE引擎确保每个场景的样式只作用于该场景内的元素,避免样式冲突。
### 样式作用域
每个场景的样式文件会自动包装在特定的选择器中:
```less
/* scenes/home/index.less */
// 原始样式
.welcome-box {
background-color: #3498db;
}
// 实际生成的样式
[data-scene-id="pe-scene-1634567890-abc123"] .welcome-box {
background-color: #3498db;
}
```
### 全局样式
你可以在项目根目录创建全局样式文件:
```less
/* styles/base.less */
// 全局变量
@primary-color: #3498db;
@secondary-color: #2ecc71;
@text-color: #2c3e50;
@bg-color: #ecf0f1;
// 全局重置样式
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
color: @text-color;
background-color: @bg-color;
}
// 全局工具类
.text-center {
text-align: center;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
```
在主文件中引入全局样式:
```javascript
// main.js
import './styles/base.less'
import PE from 'pe-engine'
```
## 样式组织最佳实践
### 按功能组织样式
```less
/* styles/components.less */
// 按钮组件
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
&.btn-primary {
background-color: @primary-color;
color: white;
&:hover {
background-color: darken(@primary-color, 10%);
}
}
&.btn-secondary {
background-color: @secondary-color;
color: white;
&:hover {
background-color: darken(@secondary-color, 10%);
}
}
}
// 卡片组件
.card {
background-color: white;
border-radius: 8px;
padding: 20px;
.box-shadow();
.card-header {
font-size: 18px;
font-weight: bold;
margin-bottom: 15px;
}
.card-body {
font-size: 14px;
line-height: 1.5;
}
}
```
### 响应式样式
使用媒体查询创建响应式设计:
```less
/* styles/responsive.less */
// 响应式断点变量
@screen-sm: 576px;
@screen-md: 768px;
@screen-lg: 992px;
@screen-xl: 1200px;
// 媒体查询混合
.responsive(@rules) {
@media (max-width: @screen-sm) {
@rules();
}
}
.responsive-md(@rules) {
@media (min-width: @screen-md) {
@rules();
}
}
// 响应式网格系统
.container {
width: 100%;
padding: 0 15px;
margin: 0 auto;
.responsive({
max-width: 100%;
});
.responsive-md({
max-width: 750px;
});
@media (min-width: @screen-lg) {
max-width: 970px;
}
@media (min-width: @screen-xl) {
max-width: 1170px;
}
}
```
## 动态样式
PE支持在运行时动态修改样式:
### 通过JavaScript修改样式
```javascript
// 获取场景元素
const element = game.getSceneElement('my-element')
// 修改单个样式属性
element.setStyle('backgroundColor', '#e74c3c')
// 修改多个样式属性
element.setStyles({
backgroundColor: '#3498db',
color: 'white',
fontSize: '18px'
})
// 添加/移除CSS类
element.addClass('active')
element.removeClass('inactive')
```
### 条件样式
在场景脚本中根据条件动态应用样式:
```html
状态: {{ isOnline ? '在线' : '离线' }}
```
## CSS自定义属性(CSS变量)
PE也支持使用CSS自定义属性:
```less
/* styles/theme.less */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--text-color: #2c3e50;
--bg-color: #ecf0f1;
}
.themed-element {
background-color: var(--primary-color);
color: var(--text-color);
&:hover {
background-color: var(--secondary-color);
}
}
```
## 样式调试
### 开发者工具
在浏览器开发者工具中,你可以看到PE为每个场景生成的特定选择器:
```css
/* 实际生成的样式 */
[data-scene-id="pe-scene-1634567890-abc123"] .welcome-box {
background-color: #3498db;
}
```
### 样式覆盖
如果需要覆盖场景样式,可以使用更具体的选择器:
```less
/* 覆盖特定场景的样式 */
[data-scene-id="pe-scene-1634567890-abc123"] .welcome-box {
background-color: #e74c3c !important;
}
```
## 完整示例
以下是一个完整的样式处理示例:
### styles/variables.less
```less
// 颜色变量
@colors: {
primary: #3498db;
secondary: #2ecc71;
success: #27ae60;
warning: #f39c12;
danger: #e74c3c;
info: #3498db;
light: #f8f9fa;
dark: #343a40;
}
// 尺寸变量
@sizes: {
xs: 0.25rem;
sm: 0.5rem;
md: 1rem;
lg: 1.5rem;
xl: 3rem;
}
// 字体变量
@fonts: {
family: 'Helvetica Neue', Arial, sans-serif;
size-base: 16px;
size-sm: 0.875rem;
size-lg: 1.25rem;
weight-normal: 400;
weight-bold: 700;
}
```
### styles/mixins.less
```less
// 清除浮动
.clearfix() {
&::after {
display: block;
content: "";
clear: both;
}
}
// 文本省略
.text-ellipsis() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 三角形
.triangle(@direction: down, @size: 5px, @color: #000) {
width: 0;
height: 0;
border-style: solid;
when (@direction = up) {
border-width: 0 @size @size @size;
border-color: transparent transparent @color transparent;
}
when (@direction = down) {
border-width: @size @size 0 @size;
border-color: @color transparent transparent transparent;
}
when (@direction = left) {
border-width: @size @size @size 0;
border-color: transparent @color transparent transparent;
}
when (@direction = right) {
border-width: @size 0 @size @size;
border-color: transparent transparent transparent @color;
}
}
```
### scenes/dashboard/index.less
```less
@import '../../styles/variables.less';
@import '../../styles/mixins.less';
.dashboard {
padding: @sizes[md];
.clearfix();
.header {
margin-bottom: @sizes[lg];
.title {
font-size: @fonts[size-lg];
font-weight: @fonts[weight-bold];
color: @colors[dark];
.text-ellipsis();
}
.subtitle {
font-size: @fonts[size-sm];
color: lighten(@colors[dark], 30%);
}
}
.stats-container {
display: flex;
flex-wrap: wrap;
gap: @sizes[md];
margin-bottom: @sizes[lg];
.stat-card {
flex: 1;
min-width: 200px;
background-color: white;
border-radius: @sizes[sm];
padding: @sizes[md];
.box-shadow(0, 2px, 8px, rgba(0,0,0,0.1));
.stat-value {
font-size: 2rem;
font-weight: @fonts[weight-bold];
color: @colors[primary];
margin-bottom: @sizes[sm];
}
.stat-label {
font-size: @fonts[size-sm];
color: lighten(@colors[dark], 40%);
}
}
}
.chart-container {
background-color: white;
border-radius: @sizes[sm];
padding: @sizes[md];
.box-shadow(0, 2px, 8px, rgba(0,0,0,0.1));
.chart-title {
font-size: @fonts[size-base];
font-weight: @fonts[weight-bold];
margin-bottom: @sizes[md];
}
}
@media (max-width: 768px) {
.stats-container {
flex-direction: column;
.stat-card {
min-width: 100%;
}
}
}
}
```
通过以上内容,你已经了解了PE引擎的样式处理机制。在下一章节中,我们将探讨事件处理的相关内容。