clip-path 相关的的动画资料汇总

SVG动画与CSS剪切技巧:探索视觉效果新边界
import cv2 import numpy as np import random from collections import deque import mediapipe as mp import json import os from datetime import datetime from PIL import Image, ImageDraw, ImageFont import platform # ------------------------------ # 检测系统并选择合适的中文字体路径 # ------------------------------ def get_chinese_font(): system = platform.system() font_path = None if system == "Windows": font_path = "C:/Windows/Fonts/simhei.ttf" # 黑体 elif system == "Darwin": # macOS font_path = "/System/Library/Fonts/PingFang.ttc" elif system == "Linux": for path in [ "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc" ]: if os.path.exists(path): font_path = path break try: return ImageFont.truetype(font_path, 32) if font_path else ImageFont.load_default() except Exception as e: print(f"⚠️ 加载中文字体失败: {e}") return ImageFont.load_default() CHINESE_FONT = get_chinese_font() # ------------------------------ # 在 OpenCV 图像上绘制中文(使用 PIL) # ------------------------------ def put_chinese_text(image, text, position, color=(255, 255, 255), font_size=30): """使用 Pillow 绘制中文文本""" try: if hasattr(CHINESE_FONT, 'path'): font = ImageFont.truetype(CHINESE_FONT.path, font_size) else: font = ImageFont.load_default() print("⚠️ 使用默认字体渲染中文") except: font = ImageFont.load_default() pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(pil_image) draw.text(position, text, fill=tuple(color), font=font) return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) # ------------------------------ # 排行榜管理 # ------------------------------ RANKING_FILE = "snake_ranking.json" MAX_RECORDS = 100 def load_ranking(): if not os.path.exists(RANKING_FILE): return [] try: with open(RANKING_FILE, 'r', encoding='utf-8') as f: data = json.load(f) seen = set() unique_data = [] for item in data: key = (item.get('score', 0), item.get('timestamp', '')) if key not in seen: seen.add(key) unique_data.append(item) return sorted(unique_data, key=lambda x: x['score'], reverse=True) except Exception as e: print("加载排行榜失败:", e) return [] def save_best_score(score): ranking = load_ranking() current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") new_record = {"score": score, "timestamp": current_time} ranking.append(new_record) seen = set() unique_ranking = [] for r in ranking: key = (r['score'], r['timestamp']) if key not in seen: seen.add(key) unique_ranking.append(r) unique_ranking = sorted(unique_ranking, key=lambda x: x['score'], reverse=True)[:MAX_RECORDS] try: with open(RANKING_FILE, 'w', encoding='utf-8') as f: json.dump(unique_ranking, f, indent=2, ensure_ascii=False) except Exception as e: print("保存排行榜失败:", e) def clear_ranking(): frame = np.zeros((720, 1280, 3), dtype=np.uint8) for y in range(720): color_val = 20 + y // 20 frame[y, :] = [color_val, color_val // 2, 60] h, w = frame.shape[:2] center_x = w // 2 frame = put_chinese_text(frame, "⚠️ 清空所有记录?", (center_x - 240, h // 2 - 60), color=(0, 0, 255), font_size=48) frame = put_chinese_text(frame, "确定要清空吗?(Y=是, N=否)", (center_x - 260, h // 2), color=(255, 255, 255), font_size=36) frame = put_chinese_text(frame, "此操作不可撤销!", (center_x - 180, h // 2 + 50), color=(150, 150, 150), font_size=32) cv2.imshow("Hand-Controlled Snake Game", frame) while True: key = cv2.waitKey(1) & 0xFF if key in (ord('y'), ord('Y')): try: with open(RANKING_FILE, 'w') as f: f.write("[]") return True except Exception as e: print("清空失败:", e) return False elif key in (ord('n'), ord('N'), 27): # ESC return False # ------------------------------ # 主菜单界面 # ------------------------------ def show_ranking_menu(): ranking = load_ranking() frame = np.zeros((720, 1280, 3), dtype=np.uint8) for y in range(720): color_val = 20 + y // 20 frame[y, :] = [color_val, color_val // 2, 60] h, w = frame.shape[:2] center_x = w // 2 frame = put_chinese_text(frame, "🏆 贪吃蛇游戏排行榜 🏆", (center_x - 280, 40), color=(255, 255, 100), font_size=50) frame = put_chinese_text(frame, "名次 得分 时间", (center_x - 240, 90), color=(200, 255, 255), font_size=30) start_y = 140 for i, item in enumerate(ranking[:10]): text = f"{i + 1:2d} {item['score']:4d} {item['timestamp']}" color = (0, 255, 255) if i == 0 else (200, 255, 200) frame = put_chinese_text(frame, text, (center_x - 240, start_y + i * 32), color=color, font_size=28) if len(ranking) == 0: frame = put_chinese_text(frame, "暂无记录...", (center_x - 100, start_y), color=(150, 150, 150), font_size=30) button_w = 200 btn_y1, btn_y2 = h - 140, h - 80 # 开始按钮 start_x1, start_x2 = center_x - button_w - 50, center_x - 50 cv2.rectangle(frame, (start_x1, btn_y1), (start_x2, btn_y2), (0, 180, 0), -1) cv2.rectangle(frame, (start_x1, btn_y1), (start_x2, btn_y2), (0, 255, 0), 3) frame = put_chinese_text(frame, "开始游戏", (center_x - button_w // 2 - 50, h - 100), color=(255, 255, 255), font_size=40) # 退出按钮 quit_x1, quit_x2 = center_x + 50, center_x + button_w + 50 cv2.rectangle(frame, (quit_x1, btn_y1), (quit_x2, btn_y2), (180, 0, 0), -1) cv2.rectangle(frame, (quit_x1, btn_y1), (quit_x2, btn_y2), (255, 0, 0), 3) frame = put_chinese_text(frame, "退出游戏", (center_x + button_w // 2 - 40, h - 100), color=(255, 255, 255), font_size=40) # 清空按钮 clear_x1, clear_x2 = center_x - 100, center_x + 100 cv2.rectangle(frame, (clear_x1, h - 70), (clear_x2, h - 10), (100, 100, 100), -1) cv2.rectangle(frame, (clear_x1, h - 70), (clear_x2, h - 10), (200, 200, 200), 2) frame = put_chinese_text(frame, "清空记录", (center_x - 45, h - 30), color=(255, 255, 255), font_size=32) frame = put_chinese_text(frame, "按'S'开始|'Q'退出|'C'清空", (center_x - 240, h - 160), color=(200, 200, 255), font_size=24) cv2.imshow("Hand-Controlled Snake Game", frame) while True: key = cv2.waitKey(1) & 0xFF if key in (ord('s'), ord('S')): return "start" elif key in (ord('q'), ord('Q'), 27): return "quit" elif key in (ord('c'), ord('C')): result = clear_ranking() return "refresh" # ------------------------------ # 初始化 MediaPipe Hands # ------------------------------ mp_hands = mp.solutions.hands mp_draw = mp.solutions.drawing_utils hands = mp_hands.Hands( static_image_mode=False, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) # ------------------------------ # 游戏参数设置 # ------------------------------ width, height = 1280, 720 snake_speed = 8 snake_length = 3 score = 0 game_over = False walls = [] cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) snake = deque([(width // 2, height // 2)]) direction = np.array([1.0, 0.0]) target_pos = None food_radius = 15 food_color = (0, 255, 0) food = [random.randint(50, width - 50), random.randint(50, height - 50)] # ------------------------------ # 工具函数 # ------------------------------ def is_point_in_wall(x, y, walls): return any(wx <= x <= wx + ww and wy <= y <= wy + wh for (wx, wy, ww, wh) in walls) def check_wall_collision(head, walls): hx, hy = head return any(wx <= hx <= wx + ww and wy <= hy <= wy + wh for (wx, wy, ww, wh) in walls) def generate_food(snake_body, walls): max_attempts = 100 min_dist = 30 for _ in range(max_attempts): x = random.randint(50, width - 50) y = random.randint(50, height - 50) pos = np.array([x, y]) if is_point_in_wall(x, y, walls): continue if any(np.linalg.norm(pos - np.array(seg)) < min_dist for seg in snake_body): continue return [x, y] return [width - 60, height - 60] # BFS 路径可达性检查(略去以保持简洁,实际项目建议保留) # 此处简化为仅距离判断(用于快速测试) def is_path_available(head_pos, food_pos, walls): # 简化版:只要不直接被墙堵死就算通路 return not is_point_in_wall(food_pos[0], food_pos[1], walls) def add_wall_safely(walls_list, snake_body, food_pos): if len(walls_list) >= 5: return walls_list for _ in range(30): ww = random.randint(40, 150) wh = random.randint(40, 150) wx = random.randint(50, width - ww - 50) wy = random.randint(50, height - wh - 50) new_wall = (wx, wy, ww, wh) temp_walls = walls_list + [new_wall] if not is_point_in_wall(snake_body[0][0], snake_body[0][1], temp_walls) and \ not is_point_in_wall(food_pos[0], food_pos[1], temp_walls): walls_list.append(new_wall) break return walls_list # ------------------------------ # 主游戏循环 # ------------------------------ while True: action = show_ranking_menu() if action == "quit": break elif action == "refresh": continue elif action == "start": # 重置游戏 snake.clear() snake.append((width // 2, height // 2)) direction = np.array([1.0, 0.0]) snake_length = 3 score = 0 game_over = False walls = [] target_pos = None food = generate_food(snake, walls) while cap.isOpened(): ret, frame = cap.read() if not ret: break frame = cv2.flip(frame, 1) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 👇 安全调用 MediaPipe 并检查结果 results = hands.process(rgb_frame) new_target = None # ✅ 关键修复:先检查是否检测到手 if not game_over and results is not None: # ✅ 使用 hasattr 和 None 判断避免 IDE 警告 if hasattr(results, 'multi_hand_landmarks') and results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS) idx_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP] x, y = int(idx_tip.x * width), int(idx_tip.y * height) # 更新目标点(平滑滤波) if target_pos is None: target_pos = (x, y) else: alpha = 0.3 target_pos = ( int(alpha * x + (1 - alpha) * target_pos[0]), int(alpha * y + (1 - alpha) * target_pos[1]) ) new_target = target_pos # 显示目标点(紫色圆圈) cv2.circle(frame, target_pos, 12, (255, 0, 255), -1) # 移动逻辑 if not game_over: head = np.array(snake[0]) if new_target is not None: to_target = np.array(new_target) - head dist = np.linalg.norm(to_target) if dist > 30: desired_dir = to_target / (dist + 1e-8) curr_dir_norm = direction / (np.linalg.norm(direction) + 1e-8) dot = np.clip(np.dot(curr_dir_norm, desired_dir), -1.0, 1.0) angle = np.arccos(dot) if angle > 0.25: # 最大转向弧度 w1 = np.sin(angle - 0.25) w2 = np.sin(0.25) sin_a = np.sin(angle) blended = (w1 * curr_dir_norm + w2 * desired_dir) / (sin_a + 1e-8) direction = blended / (np.linalg.norm(blended) + 1e-8) else: direction = desired_dir new_head = head + direction * snake_speed new_head = np.round(new_head).astype(int) snake.appendleft(tuple(new_head)) # 碰撞检测 if (check_wall_collision(new_head, walls) or new_head[0] <= 0 or new_head[0] >= width or new_head[1] <= 0 or new_head[1] >= height): game_over = True for i in range(4, len(snake)): seg = np.array(snake[i]) if np.linalg.norm(new_head - seg) < 15: game_over = True break # 吃食物 if np.linalg.norm(new_head - np.array(food)) < (food_radius + 10): old_score = score score += 1 food = generate_food(snake, walls) snake_length += 2 if score // 5 > old_score // 5: walls = add_wall_safely(walls, snake, food) while len(snake) > snake_length: snake.pop() # 绘图部分 for wall in walls: wx, wy, ww, wh = wall cv2.rectangle(frame, (wx, wy), (wx + ww, wy + wh), (255, 255, 0), -1) cv2.rectangle(frame, (wx, wy), (wx + ww, wy + wh), (0, 0, 0), 3) cv2.circle(frame, tuple(food), food_radius, food_color, -1) for i in range(1, len(snake)): alpha = i / len(snake) color = (0, int(255 * (1 - alpha)), int(100 * (1 - alpha))) cv2.line(frame, snake[i - 1], snake[i], color, 8) cv2.circle(frame, snake[0], 10, (255, 255, 255), -1) cv2.circle(frame, snake[0], 8, (0, 150, 0), -1) frame = put_chinese_text(frame, f"得分: {score}", (20, 15), color=(255, 255, 255), font_size=50) if game_over: overlay = frame.copy() cv2.rectangle(overlay, (width // 4, height // 4), (3 * width // 4, 3 * height // 4), (0, 0, 0), -1) cv2.addWeighted(overlay, 0.7, frame, 0.3, 0, frame) frame = put_chinese_text(frame, "游戏结束", (width // 2 - 120, height // 2 - 60), color=(0, 0, 255), font_size=60) frame = put_chinese_text(frame, "按任意键返回主菜单", (width // 2 - 160, height // 2), color=(255, 255, 255), font_size=36) frame = put_chinese_text(frame, f"最终得分: {score}", (width // 2 - 120, height // 2 + 50), color=(255, 255, 0), font_size=32) cv2.imshow("Hand-Controlled Snake Game", frame) cv2.waitKey(0) break cv2.imshow("Hand-Controlled Snake Game", frame) if cv2.waitKey(1) == 27: # ESC break # ------------------------------ # 释放资源 # ------------------------------ cap.release() cv2.destroyAllWindows() hands.close()
11-08
<template> <div class="home-container"> <el-tabs @tab-click="handleTabChange"> <el-tab-pane label="总览"> <div class="tab-content"> <div class="stats-row"> <el-col :span="6"> <el-card class="stat-card danger"> <div class="stat-title">当前通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #f56c6c">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">今日通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">历史通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">当前线路数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> </div> <div class="table-card"> <el-table :data="summaryTable" border> <el-table-column prop="label" label="指标"></el-table-column> <el-table-column prop="value" label="数值"></el-table-column> </el-table> </div> </div> </el-tab-pane> <el-tab-pane label="省份统计"> <div class="tab-content"> <el-table :data="provinceTable" border> <el-table-column prop="province" label="省份"></el-table-column> <el-table-column prop="currentCall" label="当前通话数" ></el-table-column> <el-table-column prop="todayCall" label="今日通话数" ></el-table-column> <el-table-column prop="historyCall" label="历史通话数" ></el-table-column> <el-table-column prop="currentLine" label="当前线路数" ></el-table-column> <el-table-column prop="circuit" label="电路线路数" ></el-table-column> <el-table-column prop="network" label="网络线路数" ></el-table-column> <el-table-column prop="todayLine" label="今日线路数" ></el-table-column> <el-table-column prop="todayCircuit" label="今日电路线路数" ></el-table-column> <el-table-column prop="todayNetwork" label="今日网络线路数" ></el-table-column> <el-table-column prop="historyLine" label="历史线路数" ></el-table-column> <el-table-column prop="historyCircuit" label="历史电路线路数" ></el-table-column> <el-table-column prop="historyNetwork" label="历史网络线路数" ></el-table-column> </el-table> </div> </el-tab-pane> <el-tab-pane label="趋势分析"> <div class="tab-content"> <div class="chart-placeholder"> <div class="mock-chart"> <div class="chart-line-container"> <div class="chart-line通话"></div> <div class="chart-line线路"></div> </div> <div class="chart-legend"> <span style="color: teal">通话数</span> | <span style="color: purple">线路数</span> </div> <div class="chart-buttons"> <el-button size="mini">近7天</el-button> <el-button size="mini">近30天</el-button> </div> </div> </div> </div> </el-tab-pane> </el-tabs> </div> </template> <script> import { userlist, getsuperes } from "@/utils/https.js"; export default { name: "HomeView", data() { return { summaryTable: [], provinceTable: [ { province: "江苏", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "上海", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "浙江", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "安徽", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, ], superEnterpriseList: [], // 新增的超级企业列表数据 }; }, mounted() { this.loadHomeData(); this.loadSuperEnterpriseList(); // 调用获取超级企业列表的方法 }, methods: { loadHomeData() { userlist() .then(data => { this.summaryTable = data.summary || []; this.provinceTable = data.provinces || this.provinceTable; }) .catch(error => { console.error("加载首页数据失败:", error); this.$message.error("加载数据失败"); }); }, loadSuperEnterpriseList() { getsuperes() .then(response => { this.superEnterpriseList = response.data || []; console.log('超级企业列表:', this.superEnterpriseList); }) .catch(error => { console.error('获取超级企业列表失败:', error); this.$message.error('获取超级企业列表失败'); }); }, handleTabChange(tab) { console.log("切换到:", tab.name); }, handleSizeChange(val) { this.pageSize = val; }, handleCurrentChange(val) { this.currentPage = val; }, }, }; </script> <style scoped> :root { --main-bg-color: #f5f7fa; --tab-bg-color: #ffffff; --stat-border-color: #f56c6c; } .home-container { padding: 20px; background: var(--main-bg-color); min-height: calc(100vh - 64px); } .tab-wrapper { background: var(--tab-bg-color); border: 1px solid #ebeef5; border-radius: 4px; } .tab-content { padding: 20px; border-top: none; } .stats-row { margin-top: 10px; } .stat-card { height: 160px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .stat-card.danger { border-left: 4px solid var(--stat-border-color); } .stat-title { font-size: 16px; font-weight: 500; margin-bottom: 10px; } .stat-value { font-size: 24px; color: #303133; margin-bottom: 10px; } .stat-sub { font-size: 14px; color: #909399; } .table-card { padding: 20px; } .chart-placeholder { text-align: center; padding: 40px 0; } .mock-chart { position: relative; height: 300px; width: 100%; } .chart-line-container { position: absolute; bottom: 40px; left: 10%; width: 80%; height: 200px; border-bottom: 1px solid #e0e0e0; border-left: 1px solid #e0e0e0; } .chart-line通话 { position: absolute; bottom: 0; width: 100%; height: 30%; background: linear-gradient(to top, rgba(0, 128, 128, 0.2) 0%, teal 100%); clip-path: polygon( 0% 100%, 5% 80%, 10% 60%, 15% 70%, 20% 50%, 25% 60%, 30% 40%, 35% 50%, 40% 30%, 45% 40%, 50% 20%, 55% 30%, 60% 10%, 65% 20%, 70% 0%, 75% 10%, 80% 30%, 85% 20%, 90% 40%, 95% 30%, 100% 50%, 100% 100% ); } .chart-line线路 { position: absolute; bottom: 0; width: 100%; height: 60%; background: linear-gradient(to top, rgba(128, 0, 128, 0.2) 0%, purple 100%); clip-path: polygon( 0% 100%, 5% 90%, 10% 70%, 15% 80%, 20% 60%, 25% 70%, 30% 50%, 35% 60%, 40% 40%, 45% 50%, 50% 30%, 55% 40%, 60% 20%, 65% 30%, 70% 10%, 75% 20%, 80% 40%, 85% 30%, 90% 50%, 95% 40%, 100% 60%, 100% 100% ); } .chart-legend { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); } .chart-buttons { position: absolute; bottom: -20px; left: 50%; transform: translateX(-50%); } .server-select, .province-select { width: 160px; margin-bottom: 20px; } </style>纠错
08-01
MATLAB主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性内容概要:本文主要介绍了一种在MATLAB环境下实现的主动噪声和振动控制算法,该算法针对较大的次级路径变化具有较强的鲁棒性。文中详细阐述了算法的设计原理与实现方法,重点解决了传统控制系统中因次级路径动态变化导致性能下降的问题。通过引入自适应机制和鲁棒控制策略,提升了系统在复杂环境下的稳定性和控制精度,适用于需要高精度噪声与振动抑制的实际工程场景。此外,文档还列举了多个MATLAB仿真实例及相关科研技术服务内容,涵盖信号处理、智能优化、机器学习等多个交叉领域。; 适合人群:具备一定MATLAB编程基础和控制系统理论知识的科研人员及工程技术人员,尤其适合从事噪声与振动控制、信号处理、自动化等相关领域的研究生和工程师。; 使用场景及目标:①应用于汽车、航空航天、精密仪器等对噪声和振动敏感的工业领域;②用于提升现有主动控制系统对参数变化的适应能力;③为相关科研项目提供算法验证与仿真平台支持; 阅读建议:建议读者结合提供的MATLAB代码进行仿真实验,深入理解算法在不同次级路径条件下的响应特性,并可通过调整控制参数进一步探究其鲁棒性边界。同时可参考文档中列出的相关技术案例拓展应用场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值