wxc-button使用

<wxc-button text="按钮"
           
type="white"
           
size="full"
           
:disabled="false"
           
:btnStyle="btnStyle"
           
:textStyle="textStyle"
           
@wxcButtonClicked="
openDialog()">
</
wxc-button>

上面就是一个<wxc-button>的全部设置。

其中:

①   text:设置显示的文本内容。

②   type:设置按钮的底色。默认有4个取值:white/yellow/red/blue。这4个值是预定义在一个内部对象STYLE_MAP中的,取值时会以STYLE_MAP[type]的形式来获取。所以type只能使用已定义的这4个值,无法人为扩展。要自定义按钮颜色,可使用btnStyle。

③   size:设置按钮的大小。默认有4个取值:full/big/medium/small。同type属性,size的这4个值也是预定义在一个内部对象BUTTON_STYLE_MAP中的:

export const BUTTON_STYLE_MAP = {
  full: {
    width: '702px',
    height: '88px'
  },
  big: {
    width: '339px',
    height: '70px'
  },
  medium: {
    width: '218px',
    height: '60px'
  },
  small: {
    width: '157px',
    height: '44px'
  }
}

然而,在源码中,按钮样式的定义:

const mrBtnStyle = {
  ...STYLE_MAP[type],
  ...btnStyle,
  ...BUTTON_STYLE_MAP[size]
};

可以看到STYLE_MAP是第一位的,然后是btnStyle,最后是BUTTON_STYLE_MAP。这导致了一个问题就是STYLE_MAP会被btnStyle覆盖,而btnStyle会被BUTTON_STYLE_MAP覆盖。

由于BUTTON_STYLE_MAP定义了按钮的width与height,所以btnStyle中自定义的各种属性,唯有width与height是不生效的。

总之,<wxc-button>的大小只能使用预定义的4个值,无法通过btnStyle来修改

④   disabled:是否启用禁用样式。注意仅仅是修改样式,并不会屏蔽掉点击事件。

⑤   btnStyle:自定义按钮样式。<wxc-button>的本质是一个<div>,btnStyle所定义的样式都会作用于该<div>。所以只要是<div>可用的样式即可,仅仅不能定义width和height。

⑥   textStyle:自定义按钮文本样式。<wxc-button>的文本显示是一个vue的<text>。所以只要是<text>可接受的样式即可。

⑦   wxcButtonClicked:响应按钮点击事件。

 

注意样式定义在data中时,需要将全小写+横线的形式转换为驼峰形式。

例如:

background-color     →   backgroundColor

import dash from dash import dcc, html from dash.dependencies import Input, Output, State import plotly.graph_objects as go import json import pandas as pd import os import numpy as np from shapely.geometry import Point, Polygon # 用于点是否在多边形内的判断 # ---------------------------------------------------------------------- # 1. 初始设置和数据结构 # ---------------------------------------------------------------------- # 小区拓扑数据 (四个顶点坐标) # 注意:坐标按顺序排列,用于绘制平行四边形 cell_coords = { "cell1": [(0, 200), (115.4701, 200), (57.73503, 100), (-57.73503, 100)], "cell2": [(-57.73503, 100), (57.73503, 100), (115.4701, 0), (0, 0)], } # 定义shapely多边形用于点过滤 CELL1_POLYGON = Polygon(cell_coords["cell1"]) CELL2_POLYGON = Polygon(cell_coords["cell2"]) # JSON 文件路径 JSON_FILE = "user_specific_parameter.json" # 初始化JSON文件结构(如果不存在或为空) def initialize_json_file(): if not os.path.exists(JSON_FILE) or os.stat(JSON_FILE).st_size == 0: initial_data = {"ue_trajectories": {"trajectory_list": []}} with open(JSON_FILE, 'w') as f: json.dump(initial_data, f, indent=4) print(f"Initialized {JSON_FILE}") # 初始化JSON文件 initialize_json_file() # ---------------------------------------------------------------------- # 2. 背景点生成函数 (用于捕获点击) # ---------------------------------------------------------------------- def generate_background_points(cell_polygons, density=5): """在指定多边形区域内生成均匀分布的背景点.""" # 确定边界范围 min_x = min(min(c[0] for c in p.exterior.coords) for p in cell_polygons) - 10 max_x = max(max(c[0] for c in p.exterior.coords) for p in cell_polygons) + 10 min_y = min(min(c[1] for c in p.exterior.coords) for p in cell_polygons) - 10 max_y = max(max(c[1] for c in p.exterior.coords) for p in cell_polygons) + 10 # 创建网格点 x_coords = np.linspace(min_x, max_x, int((max_x - min_x) * density)) y_coords = np.linspace(min_y, max_y, int((max_y - min_y) * density)) points_x = [] points_y = [] # 过滤点,只保留在任意小区内的点 for x in x_coords: for y in y_coords: p = Point(x, y) if any(polygon.contains(p) or polygon.boundary.contains(p) for polygon in cell_polygons): points_x.append(x) points_y.append(y) return points_x, points_y # 生成背景点数据 BG_POINTS_X, BG_POINTS_Y = generate_background_points([CELL1_POLYGON, CELL2_POLYGON], density=2) # 降低密度以提高性能 # ---------------------------------------------------------------------- # 3. 小区拓扑图绘制函数 # ---------------------------------------------------------------------- def create_initial_figure(all_trajectories_data=[]): """绘制初始的小区拓扑图(平行四边形).""" fig = go.Figure() # --- 绘制小区1 和 小区2 (拓扑) --- for i, (name, coords) in enumerate(cell_coords.items()): x, y = zip(*coords) fig.add_trace(go.Scatter( x=list(x) + [x[0]], y=list(y) + [y[0]], mode='lines', line=dict(color='green', width=2), name=f'{name} Topology', hoverinfo='skip', showlegend=True )) # --- 绘制透明背景点 (用于点击捕获) --- fig.add_trace(go.Scatter( x=BG_POINTS_X, y=BG_POINTS_Y, mode='markers', marker=dict( size=5, color='rgba(0,0,0,0)', # 完全透明 opacity=0, line=dict(width=0) ), name='Click Area', hoverinfo='none', # crucial: enable selection on this invisible trace customdata=[[x, y] for x, y in zip(BG_POINTS_X, BG_POINTS_Y)], unselected=dict(marker={'opacity': 0}), # 未选择时透明 selected=dict(marker={'color': 'rgba(255, 0, 0, 0.5)', 'opacity': 0.5, 'size': 8}), # 选择时半透明红色 showlegend=False )) # 设置图表布局 fig.update_layout( title=f'小区拓扑图与UE轨迹绘制工具 - 正在绘制第 {len(all_trajectories_data) + 1} 个UE轨迹', xaxis_title='X 坐标', yaxis_title='Y 坐标', # 移除比例约束,允许图表拉伸 xaxis=dict(range=[-80, 140]), yaxis=dict(range=[-20, 220]), # 关键: 设置拖拽模式为 lasso 或 rectangular 选择 dragmode='select', selectdirection='any', template='plotly_white', clickmode='event+select', # 确保图形占满整个容器 autosize=True, ) return fig # ---------------------------------------------------------------------- # 4. Dash 应用和布局 # ---------------------------------------------------------------------- app = dash.Dash(__name__) app.layout = html.Div([ html.H1("UE 轨迹绘制工具"), # 图表区域: 设置 style 确保图表高度较大,占满页面 dcc.Graph( id='topology-graph', figure=create_initial_figure(), config={'displayModeBar': True, 'editable': True}, style={'height': '80vh', 'width': '100%'} # 确保图形占满大部分页面高度 ), # 坐标显示区域 html.Div(id='selected-data-output', style={'margin-top': '10px', 'font-size': '16px', 'font-weight': 'bold'}), # UE 轨迹操作按钮 html.Div([ html.Button('保存当前UE轨迹并开始下一个', id='save-clear-button', n_clicks=0, style={'margin-right': '10px', 'padding': '10px', 'background-color': '#4CAF50', 'color': 'white', 'border': 'none', 'border-radius': '5px'}), html.Button('导出所有轨迹到JSON文件', id='export-json-button', n_clicks=0, style={'padding': '10px', 'background-color': '#008CBA', 'color': 'white', 'border': 'none', 'border-radius': '5px'}), ], style={'margin-top': '20px'}), # 隐藏的存储组件 dcc.Store(id='current-ue-store', data=[]), dcc.Store(id='all-trajectories-store', data=json.load(open(JSON_FILE))["ue_trajectories"]["trajectory_list"]), dcc.Store(id='last-point-coords', data={'x': None, 'y': None}) ]) # ---------------------------------------------------------------------- # 5. Dash 回调函数 # ---------------------------------------------------------------------- # 回调1: 处理鼠标选择事件,更新当前UE轨迹 @app.callback( [Output('current-ue-store', 'data', allow_duplicate=True), Output('last-point-coords', 'data', allow_duplicate=True)], [Input('topology-graph', 'selectedData')], [State('current-ue-store', 'data')], prevent_initial_call=True ) def handle_graph_select(selectedData, current_ue_data): """选择背景点时,记录新的轨迹点.""" if selectedData is None or 'points' not in selectedData or not selectedData['points']: # 没有有效的选择数据 return dash.no_update, dash.no_update # 获取最后一个被选择的点 # 注意: Plotly selection 可以选择多个点。我们只取最后一个点作为轨迹点。 last_point = selectedData['points'][-1] # 确认选择的是我们用于捕获的 'Click Area' 轨迹 if last_point.get('curveNumber') != 2: # 假设 'Click Area' 是第三个轨迹 (索引2) return dash.no_update, dash.no_update x = last_point['x'] y = last_point['y'] z = 1.5 # 固定z坐标 # 构造新的轨迹点: [x, y, z] new_point = [round(x, 4), round(y, 4), z] # 检查是否重复添加了同一个点 (防止多次点击同一区域导致的重复) if current_ue_data and new_point == current_ue_data[-1]: return dash.no_update, dash.no_update # 更新当前轨迹列表 updated_trajectory = current_ue_data + [new_point] # 返回更新后的数据和最新的点击坐标 return updated_trajectory, {'x': round(x, 4), 'y': round(y, 4)} # 回调2: 绘制当前UE轨迹和更新坐标显示 @app.callback( [Output('topology-graph', 'figure', allow_duplicate=True), Output('selected-data-output', 'children')], [Input('current-ue-store', 'data'), Input('last-point-coords', 'data')], [State('all-trajectories-store', 'data')], prevent_initial_call=True ) def update_graph_and_display(current_ue_data, last_point_coords, all_trajectories_data): """根据当前轨迹数据,在图上绘制轨迹点和连线,并更新坐标显示.""" # 重新创建初始的小区图 fig = create_initial_figure(all_trajectories_data) # 如果当前有轨迹点,则进行绘制 if current_ue_data: # 提取 x 和 y 坐标 df = pd.DataFrame(current_ue_data, columns=['x', 'y', 'z']) # 绘制连线和点 fig.add_trace(go.Scatter( x=df['x'], y=df['y'], mode='lines+markers', marker=dict(size=8, color='red', symbol='circle'), # 使用圆点更清晰 line=dict(color='red', width=2), name='UE Trajectory', hoverinfo='text', text=[f'({x}, {y})' for x, y in zip(df['x'], df['y'])], showlegend=True )) # 强制更新标题 (在 create_initial_figure 中已更新) # 更新坐标显示 if last_point_coords['x'] is not None: display_text = f"上一次轨迹点坐标: X={last_point_coords['x']}, Y={last_point_coords['y']}, Z=1.5" else: display_text = "请使用鼠标拖拽/点击图表上的区域来绘制UE轨迹..." return fig, display_text # 回调3: 保存当前UE轨迹并开始下一个 @app.callback( [Output('current-ue-store', 'data', allow_duplicate=True), Output('all-trajectories-store', 'data', allow_duplicate=True)], [Input('save-clear-button', 'n_clicks')], [State('current-ue-store', 'data'), State('all-trajectories-store', 'data')], prevent_initial_call=True ) def save_and_clear_trajectory(n_clicks, current_ue_data, all_trajectories_data): """点击按钮时,保存当前UE轨迹,并清空当前轨迹列表.""" changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0] if 'save-clear-button' in changed_id and n_clicks > 0: if not current_ue_data: print("当前UE轨迹为空,未保存任何数据。") return [], all_trajectories_data # 1. 保存当前轨迹 updated_all_trajectories = all_trajectories_data + [current_ue_data] print(f"UE轨迹已保存。当前总计 {len(updated_all_trajectories)} 条轨迹。") # 2. 清空当前轨迹数据,准备绘制下一个 new_current_ue_data = [] # 返回更新后的数据 return new_current_ue_data, updated_all_trajectories return dash.no_update, dash.no_update # 回调4: 导出所有轨迹到JSON文件 # ... (与前一版本保持一致,功能无变化) @app.callback( Output('export-json-button', 'children'), [Input('export-json-button', 'n_clicks')], [State('all-trajectories-store', 'data')], prevent_initial_call=True ) def export_to_json(n_clicks, all_trajectories_data): """将所有已保存的轨迹数据导出到JSON文件.""" changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0] if 'export-json-button' in changed_id and n_clicks > 0: try: with open(JSON_FILE, 'r') as f: data = json.load(f) data["ue_trajectories"]["trajectory_list"] = all_trajectories_data with open(JSON_FILE, 'w') as f: json.dump(data, f, indent=4) num_trajectories = len(all_trajectories_data) return f"成功导出 ({num_trajectories} 条)!" except Exception as e: return "导出失败!" return '导出所有轨迹到JSON文件' if __name__ == '__main__': # 运行应用 print(f"请安装 shapely (pip install shapely) 并打开浏览器访问 http://127.0.0.1:8050/") app.run(debug=True) 将上面代码中所有中文部分均改为英文,同时添加一个功能,运行前先检查是否存在user_specific_parameter.json文件,若不存在进行创建,user_specific_parameter.json文件格式如下 { "ue_trajectories": { "trajectory_interval_second": 1, "interpolation_interval_second": 0.01, "trajectory_list": []
最新发布
10-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值