小圆点踢足球

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

<title>上帝视角 · AI足球冠军杯 | 左右球门+得分</title>

<style>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

user-select: none;

}

body {

background: linear-gradient(145deg, #0a3b1f, #05250e);

min-height: 100vh;

display: flex;

justify-content: center;

align-items: center;

font-family: 'Segoe UI', 'Poppins', monospace;

padding: 20px;

}

.game-wrapper {

background: #1e5a1e;

border-radius: 56px;

padding: 20px 24px 24px 24px;

box-shadow: 0 20px 35px rgba(0,0,0,0.6), inset 0 1px 4px rgba(255,255,200,0.3);

}

canvas {

display: block;

margin: 0 auto;

border-radius: 32px;

box-shadow: 0 12px 28px black;

cursor: pointer;

background-color: #2c9e2c;

}

.info-board {

margin-top: 20px;

display: flex;

justify-content: space-between;

align-items: center;

gap: 20px;

flex-wrap: wrap;

background: rgba(0, 0, 0, 0.7);

backdrop-filter: blur(8px);

border-radius: 60px;

padding: 8px 28px;

color: #FFF3C9;

}

.score-panel {

display: flex;

gap: 40px;

background: #000000aa;

padding: 6px 28px;

border-radius: 48px;

font-weight: bold;

}

.team-score {

font-size: 1.6rem;

display: flex;

align-items: center;

gap: 12px;

}

.team-score span:first-child {

font-size: 1.9rem;

}

.red-text { color: #ff7b6b; }

.blue-text { color: #6ba5ff; }

.score-number {

font-size: 2.4rem;

font-weight: 800;

color: #FFD966;

margin-left: 8px;

}

.status-area {

background: #1d2f1ad9;

padding: 5px 24px;

border-radius: 32px;

font-weight: bold;

font-size: 0.95rem;

}

button {

background: #ffb347;

border: none;

font-weight: bold;

font-size: 0.9rem;

padding: 6px 20px;

border-radius: 40px;

cursor: pointer;

transition: 0.05s linear;

box-shadow: 0 3px 0 #a1622a;

font-family: inherit;

}

button:active {

transform: translateY(2px);

box-shadow: 0 1px 0 #a1622a;

}

.legend {

display: flex;

gap: 18px;

font-size: 0.7rem;

background: #00000066;

padding: 5px 16px;

border-radius: 32px;

}

.dot {

display: inline-block;

width: 12px;

height: 12px;

border-radius: 12px;

margin-right: 5px;

}

footer {

font-size: 0.7rem;

text-align: center;

margin-top: 12px;

color: #cfefcf;

}

</style>

</head>

<body>

<div>

<div class="game-wrapper">

<canvas id="soccerCanvas" width="1100" height="620"></canvas>

<div class="info-board">

<div class="score-panel">

<div class="team-score"><span class="red-text">🔴 红队</span><span class="score-number" id="redScoreDisplay">0</span></div>

<div class="team-score"><span class="blue-text">🔵 蓝队</span><span class="score-number" id="blueScoreDisplay">0</span></div>

</div>

<div class="status-area" id="gameStatusMsg">⚽ AI 激战中 · 进球自动中圈开球</div>

<button id="resetMatchBtn">🔄 重赛</button>

<div class="legend">

<span><i class="dot" style="background:#e34234;"></i> 红队(攻右门)</span>

<span><i class="dot" style="background:#3b83ff;"></i> 蓝队(攻左门)</span>

<span><i class="dot" style="background:#f5f2b0;"></i> 足球</span>

</div>

</div>

<footer>🎯 AI智能跑位+身体对抗 | 足球碰到球员会踢飞 | 球门区得分自动累计</footer>

</div>

</div>

<script>

(function(){

// ----- CANVAS ------

const canvas = document.getElementById('soccerCanvas');

const ctx = canvas.getContext('2d');

const W = 1100, H = 620;

canvas.width = W; canvas.height = H;

// 球场边界(球员不可逾越,足球也不可出界,但碰到边界会反弹)

const BOUNDS = { left: 28, right: W-28, top: 35, bottom: H-35 };

// ========= 球门定义(左右两侧明显区域)==========

// 左侧球门 (蓝队防守,但红队射此门得分)

const LEFT_GOAL = {

x: 5, y: H/2 - 55, w: 22, h: 110,

teamOwner: 'blue' // 防守方是蓝队,但红队进球

};

// 右侧球门 (红队防守,蓝队射此门得分)

const RIGHT_GOAL = {

x: W-27, y: H/2 - 55, w: 22, h: 110,

teamOwner: 'red'

};

// 物理半径

const BALL_RADIUS = 7;

const PLAYER_RADIUS = 12;

// 运动参数

const MAX_SPEED = 4.6;

const ACC = 0.32;

const AIR_FRICTION = 0.99;

const BALL_FRICTION = 0.993;

// 队伍配置

const PLAYERS_COUNT = 6;

let redTeam = \[\]; // 红队 (左侧半场起始,进攻右侧球门)

let blueTeam = \[\]; // 蓝队 (右侧半场起始,进攻左侧球门)

let ball = { x: W/2, y: H/2, vx: 0, vy: 0 };

// 比分

let redScore = 0, blueScore = 0;

let goalCooldown = false; // 进球后短暂冻结,重置足球位置

let goalTimer = null;

// UI 元素

const redScoreSpan = document.getElementById('redScoreDisplay');

const blueScoreSpan = document.getElementById('blueScoreDisplay');

const statusMsgDiv = document.getElementById('gameStatusMsg');

function updateUI() {

redScoreSpan.innerText = redScore;

blueScoreSpan.innerText = blueScore;

}

function setStatusMsg(msg, isTemp = false) {

statusMsgDiv.innerHTML = msg;

if(isTemp) {

setTimeout(() => {

if(!goalCooldown) statusMsgDiv.innerHTML = "⚽ AI 激战中 · 进球自动中圈开球";

}, 1800);

}

}

// ---------- 重置所有球员到阵型(不重置比分)----------

function resetPositions(centerBall = true) {

// 红队阵型 (左半场 150~400区域)

for(let i=0; i<redTeam.length; i++) {

let angle = (i / redTeam.length) * Math.PI * 2;

let baseX = 160 + Math.sin(angle) * 70;

let baseY = H/2 + Math.cos(angle * 1.2) * 85;

baseX = Math.min(Math.max(baseX, BOUNDS.left + PLAYER_RADIUS), BOUNDS.right - 280);

baseY = Math.min(Math.max(baseY, BOUNDS.top + PLAYER_RADIUS), BOUNDS.bottom - PLAYER_RADIUS);

redTeami.x = baseX;

redTeami.y = baseY;

redTeami.vx = 0;

redTeami.vy = 0;

}

// 蓝队阵型 (右半场 700~1000)

for(let i=0; i<blueTeam.length; i++) {

let angle = (i / blueTeam.length) * Math.PI * 2;

let baseX = W - 180 + Math.sin(angle) * 70;

let baseY = H/2 + Math.cos(angle * 1.1) * 80;

baseX = Math.min(Math.max(baseX, BOUNDS.left + 250), BOUNDS.right - PLAYER_RADIUS);

baseY = Math.min(Math.max(baseY, BOUNDS.top + PLAYER_RADIUS), BOUNDS.bottom - PLAYER_RADIUS);

blueTeami.x = baseX;

blueTeami.y = baseY;

blueTeami.vx = 0;

blueTeami.vy = 0;

}

if(centerBall) {

ball.x = W/2;

ball.y = H/2;

ball.vx = (Math.random() - 0.5) * 1.4;

ball.vy = (Math.random() - 0.5) * 1.2;

}

}

// 完全重置比赛(比分归零,重开)

function fullMatchReset() {

if(goalCooldown) return;

redScore = 0;

blueScore = 0;

updateUI();

resetPositions(true);

for(let p of redTeam) { p.vx = 0; p.vy = 0; }

for(let p of blueTeam) { p.vx = 0; p.vy = 0; }

ball.vx = 0; ball.vy = 0;

goalCooldown = false;

if(goalTimer) clearTimeout(goalTimer);

setStatusMsg("⚡ 比赛已重置,开球!");

}

// 进球处理

function handleGoal(scoringTeam) { // 'red' 或 'blue'

if(goalCooldown) return;

goalCooldown = true;

if(scoringTeam === 'red') {

redScore++;

setStatusMsg("🎉 红队进球! +1分 🎉", true);

} else {

blueScore++;

setStatusMsg("🎉 蓝队进球! +1分 🎉", true);

}

updateUI();

// 进球特效冻结,然后将球放回中圈

if(goalTimer) clearTimeout(goalTimer);

goalTimer = setTimeout(() => {

resetPositions(true);

goalCooldown = false;

setStatusMsg("⚽ 继续比赛!");

goalTimer = null;

}, 1300);

}

// 检测球是否进入球门区域

function checkGoalScored() {

// 左侧球门区域 (红队得分)

if(ball.x + BALL_RADIUS > LEFT_GOAL.x && ball.x - BALL_RADIUS < LEFT_GOAL.x + LEFT_GOAL.w &&

ball.y + BALL_RADIUS > LEFT_GOAL.y && ball.y - BALL_RADIUS < LEFT_GOAL.y + LEFT_GOAL.h) {

if(!goalCooldown) handleGoal('red');

return true;

}

// 右侧球门区域 (蓝队得分)

if(ball.x + BALL_RADIUS > RIGHT_GOAL.x && ball.x - BALL_RADIUS < RIGHT_GOAL.x + RIGHT_GOAL.w &&

ball.y + BALL_RADIUS > RIGHT_GOAL.y && ball.y - BALL_RADIUS < RIGHT_GOAL.y + RIGHT_GOAL.h) {

if(!goalCooldown) handleGoal('blue');

return true;

}

return false;

}

// ========= AI 决策: 球员追逐足球,但带有进攻方向偏移 ==========

function getPlayerTarget(player, teamColor) { // teamColor: 'red' / 'blue'

let dxToBall = ball.x - player.x;

let dyToBall = ball.y - player.y;

let dist = Math.hypot(dxToBall, dyToBall);

let aggression = Math.min(1.0, 170 / (dist + 35));

let targetX = ball.x;

let targetY = ball.y;

if(teamColor === 'red') {

// 红队倾向向右半场进攻 (射右侧球门)

let offensiveShift = 45 * (1 - aggression);

targetX = ball.x + offensiveShift;

// 若球靠近左后场,稍微回防但依然积极

if(ball.x < W/2 - 100 && dist > 130) targetX = Math.min(targetX, W/2 - 40);

targetY = ball.y + (player.y - ball.y) * 0.12;

} else {

// 蓝队倾向向左半场进攻 (射左侧球门)

let offensiveShift = -45 * (1 - aggression);

targetX = ball.x + offensiveShift;

if(ball.x > W/2 + 100 && dist > 130) targetX = Math.max(targetX, W/2 + 40);

targetY = ball.y + (player.y - ball.y) * 0.12;

}

// 边界钳位

targetX = Math.min(Math.max(targetX, BOUNDS.left + 15), BOUNDS.right - 15);

targetY = Math.min(Math.max(targetY, BOUNDS.top + 15), BOUNDS.bottom - 15);

return { x: targetX, y: targetY };

}

function updatePlayersMovement() {

// 红队移动

for(let p of redTeam) {

let target = getPlayerTarget(p, 'red');

let dx = target.x - p.x;

let dy = target.y - p.y;

let len = Math.hypot(dx, dy);

if(len > 0.3) {

let dirX = dx/len, dirY = dy/len;

p.vx += dirX * ACC;

p.vy += dirY * ACC;

let spd = Math.hypot(p.vx, p.vy);

if(spd > MAX_SPEED) { p.vx = (p.vx/spd)*MAX_SPEED; p.vy = (p.vy/spd)*MAX_SPEED; }

}

p.vx *= AIR_FRICTION;

p.vy *= AIR_FRICTION;

p.x += p.vx;

p.y += p.vy;

p.x = Math.min(Math.max(p.x, BOUNDS.left + PLAYER_RADIUS), BOUNDS.right - PLAYER_RADIUS);

p.y = Math.min(Math.max(p.y, BOUNDS.top + PLAYER_RADIUS), BOUNDS.bottom - PLAYER_RADIUS);

}

// 蓝队移动

for(let p of blueTeam) {

let target = getPlayerTarget(p, 'blue');

let dx = target.x - p.x;

let dy = target.y - p.y;

let len = Math.hypot(dx, dy);

if(len > 0.3) {

let dirX = dx/len, dirY = dy/len;

p.vx += dirX * ACC;

p.vy += dirY * ACC;

let spd = Math.hypot(p.vx, p.vy);

if(spd > MAX_SPEED) { p.vx = (p.vx/spd)*MAX_SPEED; p.vy = (p.vy/spd)*MAX_SPEED; }

}

p.vx *= AIR_FRICTION;

p.vy *= AIR_FRICTION;

p.x += p.vx;

p.y += p.vy;

p.x = Math.min(Math.max(p.x, BOUNDS.left + PLAYER_RADIUS), BOUNDS.right - PLAYER_RADIUS);

p.y = Math.min(Math.max(p.y, BOUNDS.top + PLAYER_RADIUS), BOUNDS.bottom - PLAYER_RADIUS);

}

}

// 球员互相推开防粘连

function resolveCollisionPlayers() {

let all = ...redTeam, ...blueTeam;

for(let i=0;i<all.length;i++) {

for(let j=i+1;j<all.length;j++) {

let p1=alli, p2=allj;

let dx = p1.x-p2.x, dy = p1.y-p2.y;

let dist = Math.hypot(dx,dy);

let minDist = PLAYER_RADIUS*2;

if(dist < minDist) {

let angle = Math.atan2(dy,dx);

let overlap = minDist - dist;

let move = overlap * 0.5;

let mx = Math.cos(angle)*move;

let my = Math.sin(angle)*move;

p1.x += mx; p1.y += my;

p2.x -= mx; p2.y -= my;

// 边界校正

p1.x = Math.min(Math.max(p1.x, BOUNDS.left+PLAYER_RADIUS), BOUNDS.right-PLAYER_RADIUS);

p1.y = Math.min(Math.max(p1.y, BOUNDS.top+PLAYER_RADIUS), BOUNDS.bottom-PLAYER_RADIUS);

p2.x = Math.min(Math.max(p2.x, BOUNDS.left+PLAYER_RADIUS), BOUNDS.right-PLAYER_RADIUS);

p2.y = Math.min(Math.max(p2.y, BOUNDS.top+PLAYER_RADIUS), BOUNDS.bottom-PLAYER_RADIUS);

}

}

}

}

// 足球与球员碰撞(踢球力度+射门倾向)

function handleBallPlayerCollision() {

let allPlayers = ...redTeam, ...blueTeam;

for(let player of allPlayers) {

let dx = ball.x - player.x;

let dy = ball.y - player.y;

let dist = Math.hypot(dx, dy);

let minDist = BALL_RADIUS + PLAYER_RADIUS;

if(dist < minDist) {

let angle = Math.atan2(dy, dx);

let overlap = minDist - dist;

// 把球员轻微推开

let push = overlap * 0.35;

player.x -= Math.cos(angle) * push;

player.y -= Math.sin(angle) * push;

player.x = Math.min(Math.max(player.x, BOUNDS.left+PLAYER_RADIUS), BOUNDS.right-PLAYER_RADIUS);

player.y = Math.min(Math.max(player.y, BOUNDS.top+PLAYER_RADIUS), BOUNDS.bottom-PLAYER_RADIUS);

// 重新计算方向

let dx2 = ball.x - player.x;

let dy2 = ball.y - player.y;

let norm = Math.hypot(dx2, dy2);

if(norm < 0.01) norm = 1;

let dirX = dx2/norm, dirY = dy2/norm;

let playerSpd = Math.hypot(player.vx, player.vy);

let basePower = 4.8 + playerSpd * 0.8;

basePower = Math.min(basePower, 9.8);

let team = redTeam.includes(player) ? 'red' : 'blue';

let kickAngle = angle;

if(team === 'red') {

// 倾向右球门方向 (进攻右侧)

let goalAngle = Math.atan2(H/2 - player.y, (W-45) - player.x);

let mix = 0.62;

kickAngle = angle * (1-mix) + goalAngle * mix + (Math.random()-0.5)*0.35;

} else {

// 倾向左球门方向

let goalAngle = Math.atan2(H/2 - player.y, (45) - player.x);

let mix = 0.62;

kickAngle = angle * (1-mix) + goalAngle * mix + (Math.random()-0.5)*0.35;

}

let force = basePower;

ball.vx = Math.cos(kickAngle) * force + player.vx * 0.55;

ball.vy = Math.sin(kickAngle) * force + player.vy * 0.55;

let ballSpeed = Math.hypot(ball.vx, ball.vy);

let maxBall = 11.5;

if(ballSpeed > maxBall) {

ball.vx = ball.vx/ballSpeed * maxBall;

ball.vy = ball.vy/ballSpeed * maxBall;

}

// 推出重叠区

let sep = (minDist + 1.5) / norm;

ball.x = player.x + dirX * sep;

ball.y = player.y + dirY * sep;

break; // 一次帧只处理一次碰撞防止连环瞬移

}

}

}

// 足球物理 + 边界碰撞 (反弹)

function updateBall() {

if(goalCooldown) return;

ball.x += ball.vx;

ball.y += ball.vy;

ball.vx *= BALL_FRICTION;

ball.vy *= BALL_FRICTION;

// 边界碰撞 (保证球不飞出界)

if(ball.x - BALL_RADIUS < BOUNDS.left) {

ball.x = BOUNDS.left + BALL_RADIUS;

ball.vx = -ball.vx * 0.65;

}

if(ball.x + BALL_RADIUS > BOUNDS.right) {

ball.x = BOUNDS.right - BALL_RADIUS;

ball.vx = -ball.vx * 0.65;

}

if(ball.y - BALL_RADIUS < BOUNDS.top) {

ball.y = BOUNDS.top + BALL_RADIUS;

ball.vy = -ball.vy * 0.65;

}

if(ball.y + BALL_RADIUS > BOUNDS.bottom) {

ball.y = BOUNDS.bottom - BALL_RADIUS;

ball.vy = -ball.vy * 0.65;

}

// 进球判定

checkGoalScored();

}

// ---------- 华丽绘图 ----------

function drawField() {

// 草地

ctx.fillStyle = "#2e9e3b";

ctx.fillRect(0,0,W,H);

ctx.strokeStyle = "#e9f5cf";

ctx.lineWidth = 2.5;

ctx.setLineDash(12,16);

ctx.beginPath();

ctx.moveTo(W/2, 10);

ctx.lineTo(W/2, H-10);

ctx.stroke();

ctx.setLineDash(\[\]);

ctx.beginPath();

ctx.arc(W/2, H/2, 50, 0, Math.PI*2);

ctx.stroke();

// 禁区线装饰

ctx.beginPath();

ctx.rect(LEFT_GOAL.x+8, LEFT_GOAL.y-5, 12, LEFT_GOAL.h+10);

ctx.fillStyle = "#488a4877";

ctx.fill();

ctx.beginPath();

ctx.rect(RIGHT_GOAL.x-5, RIGHT_GOAL.y-5, 12, RIGHT_GOAL.h+10);

ctx.fill();

}

function drawGoals() {

// 左侧球门 (带网纹)

ctx.fillStyle = "#D9B382";

ctx.shadowBlur = 0;

ctx.fillRect(LEFT_GOAL.x-2, LEFT_GOAL.y-4, LEFT_GOAL.w+4, LEFT_GOAL.h+8);

ctx.fillStyle = "#B87C3A";

ctx.fillRect(LEFT_GOAL.x, LEFT_GOAL.y, LEFT_GOAL.w, LEFT_GOAL.h);

ctx.fillStyle = "#FFE1A0aa";

for(let i=0;i<6;i++) {

ctx.fillRect(LEFT_GOAL.x+4, LEFT_GOAL.y+8 + i*17, 12, 6);

}

// 右侧球门

ctx.fillStyle = "#D9B382";

ctx.fillRect(RIGHT_GOAL.x-2, RIGHT_GOAL.y-4, RIGHT_GOAL.w+4, RIGHT_GOAL.h+8);

ctx.fillStyle = "#B87C3A";

ctx.fillRect(RIGHT_GOAL.x, RIGHT_GOAL.y, RIGHT_GOAL.w, RIGHT_GOAL.h);

ctx.fillStyle = "#FFE1A0aa";

for(let i=0;i<6;i++) {

ctx.fillRect(RIGHT_GOAL.x+4, RIGHT_GOAL.y+8 + i*17, 12, 6);

}

ctx.fillStyle = "#FFF5CF";

ctx.font = "bold 20px monospace";

ctx.fillText("🚪", LEFT_GOAL.x-5, LEFT_GOAL.y+LEFT_GOAL.h/2+8);

ctx.fillText("🚪", RIGHT_GOAL.x+RIGHT_GOAL.w-9, RIGHT_GOAL.y+RIGHT_GOAL.h/2+8);

}

function drawPlayers() {

for(let p of redTeam) {

ctx.beginPath();

ctx.arc(p.x, p.y, PLAYER_RADIUS-1, 0, Math.PI*2);

ctx.fillStyle = "#E63E2E";

ctx.fill();

ctx.strokeStyle = "#FFA07A";

ctx.lineWidth = 2;

ctx.stroke();

ctx.fillStyle = "white";

ctx.font = "bold 16px 'Segoe UI'";

ctx.fillText("⚡", p.x-7, p.y+6);

}

for(let p of blueTeam) {

ctx.beginPath();

ctx.arc(p.x, p.y, PLAYER_RADIUS-1, 0, Math.PI*2);

ctx.fillStyle = "#3B7BFF";

ctx.fill();

ctx.strokeStyle = "#B8D4FF";

ctx.stroke();

ctx.fillStyle = "white";

ctx.fillText("✦", p.x-6, p.y+6);

}

}

function drawBall() {

ctx.beginPath();

ctx.arc(ball.x, ball.y, BALL_RADIUS, 0, Math.PI*2);

ctx.fillStyle = "#FDF5C9";

ctx.fill();

ctx.strokeStyle = "#4a3b1c";

ctx.lineWidth = 1.8;

ctx.stroke();

ctx.beginPath();

ctx.moveTo(ball.x-4, ball.y-3);

ctx.lineTo(ball.x+4, ball.y+3);

ctx.moveTo(ball.x+4, ball.y-3);

ctx.lineTo(ball.x-4, ball.y+3);

ctx.stroke();

ctx.fillStyle = "#332211";

ctx.beginPath();

ctx.arc(ball.x-2, ball.y-2, 1.6, 0, Math.PI*2);

ctx.fill();

ctx.fillStyle = "white";

ctx.beginPath();

ctx.arc(ball.x-3, ball.y-3, 1, 0, Math.PI*2);

ctx.fill();

}

function drawStatusText() {

if(goalCooldown) {

ctx.font = "bold 28px 'Segoe UI'";

ctx.fillStyle = "#FFEDB5";

ctx.shadowBlur = 8;

ctx.fillText("⚽ 进球! ⚽", W/2-100, 55);

ctx.shadowBlur = 0;

}

}

// 主循环

function updateAndRender() {

if(!goalCooldown) {

updatePlayersMovement();

resolveCollisionPlayers();

updateBall();

handleBallPlayerCollision(); // 踢球核心

// 二次确保边界不溢出

ball.x = Math.min(Math.max(ball.x, BOUNDS.left+BALL_RADIUS), BOUNDS.right-BALL_RADIUS);

ball.y = Math.min(Math.max(ball.y, BOUNDS.top+BALL_RADIUS), BOUNDS.bottom-BALL_RADIUS);

}

drawField();

drawGoals();

drawPlayers();

drawBall();

drawStatusText();

requestAnimationFrame(updateAndRender);

}

// ---------- 初始化队伍 & 启动 ----------

function initTeams() {

redTeam = \[\];

blueTeam = \[\];

for(let i=0; i<PLAYERS_COUNT; i++) {

redTeam.push({ x: 180, y: H/2, vx: 0, vy: 0 });

blueTeam.push({ x: W-180, y: H/2, vx: 0, vy: 0 });

}

resetPositions(true);

}

// 重置按钮监听

document.getElementById('resetMatchBtn').addEventListener('click', () => {

if(goalCooldown) return;

fullMatchReset();

});

initTeams();

updateUI();

updateAndRender();

})();

</script>

</body>

</html>

相关推荐
YHL8 小时前
🧊 CSS 3D 硬核解析:四个属性手写旋转立方体
前端·css·html
Odoo老杨9 小时前
如何直接在线定制修改 Odoo UI界面?
css·python·crm·odoo·erp·中小企业数字化
LaughingZhu10 小时前
Product Hunt 每日热榜 | 2026-06-16
前端·人工智能·经验分享·chatgpt·html
m0_547486661 天前
《HTML+CSS+JavaScript+Vue前端开发技术教程》全套PPT课件
javascript·css·html
gCode Teacher 格码致知1 天前
Javascript技术:CSS 中rem、vh 和 px各有其最佳适用场景-由Deepseek产生
开发语言·javascript·css
fastjson_1 天前
Edge浏览器开启IE兼容模式
javascript·edge·html
qq_419854051 天前
css filter
前端·javascript·css
艾伦野鸽ggg1 天前
web 组大一下第二次考核
前端·css·html
川石课堂软件测试1 天前
APP自动化测试|高级手势操作&toast操作
css·功能测试·测试工具·microsoft·fiddler·单元测试·harmonyos
用户059540174461 天前
Playwright 网络拦截踩坑实录:我花了 3 小时才搞懂数据持久化验证的正确姿势
前端·css