You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网格单元格选区圆角边框实现遇边缘问题求解决方案

SVG替代方案解决游戏瓦片分组边框绘制问题

核心思路

用SVG矢量图形替代CSS边框,精确控制瓦片的边缘和拐角绘制,既解决原生CSS无法处理的对角相邻(如F8与G9)场景,又避免Canvas放大像素化的问题。每个瓦片内嵌一个SVG,根据up/down/left/right的相邻状态动态生成边框路径。

Vue实现示例

<template>
  <div class="game-tile" :style="{ background: bg }">
    <!-- SVG作为边框层,不干扰瓦片交互 -->
    <svg class="tile-border" viewBox="0 0 100 100" preserveAspectRatio="none">
      <path 
        :d="borderPath" 
        :stroke="field.color" 
        stroke-width="10" 
        fill="none" 
        stroke-linejoin="round"
        stroke-linecap="round"
      />
    </svg>
  </div>
</template>

<script setup>
import { computed } from 'vue';

const props = defineProps({
  field: {
    type: Object,
    required: true,
    // 结构示例:{ border: { up: boolean, down: boolean, left: boolean, right: boolean }, color: string }
  },
  bg: {
    type: String,
    required: true
  }
});

// 动态生成SVG边框路径
const borderPath = computed(() => {
  const { up, down, left, right } = props.field.border;
  const offset = 5; // 对应stroke-width的一半,避免边框超出SVG容器
  const radius = 12; // 圆角半径,和原CSS一致
  const pathSegments = [];

  // 确定起点:根据上下左相邻状态调整,避免绘制多余的起始段
  let startX = left ? 50 : offset;
  let startY = up ? 50 : offset;
  pathSegments.push(`M ${startX} ${startY}`);

  // 绘制顶部边框(无上方相邻时)
  if (!up) {
    const topRightX = right ? 50 : 100 - offset;
    pathSegments.push(`L ${topRightX} ${offset}`);
    // 右上角圆角(无上方+无右方相邻时)
    if (!right) {
      pathSegments.push(`A ${radius} ${radius} 0 0 1 ${100 - offset} ${offset + radius}`);
    }
  }

  // 绘制右侧边框(无右方相邻时)
  if (!right) {
    const bottomRightY = down ? 50 : 100 - offset;
    pathSegments.push(`L ${100 - offset} ${bottomRightY}`);
    // 右下角圆角(无右方+无下方相邻时)
    if (!down) {
      pathSegments.push(`A ${radius} ${radius} 0 0 1 ${100 - offset - radius} ${100 - offset}`);
    }
  }

  // 绘制底部边框(无下方相邻时)
  if (!down) {
    const bottomLeftX = left ? 50 : offset;
    pathSegments.push(`L ${bottomLeftX} ${100 - offset}`);
    // 左下角圆角(无下方+无左方相邻时)
    if (!left) {
      pathSegments.push(`A ${radius} ${radius} 0 0 1 ${offset} ${100 - offset - radius}`);
    }
  }

  // 绘制左侧边框(无左方相邻时)
  if (!left) {
    const topLeftY = up ? 50 : offset;
    pathSegments.push(`L ${offset} ${topLeftY}`);
    // 左上角圆角(无左方+无上方相邻时)
    if (!up) {
      pathSegments.push(`A ${radius} ${radius} 0 0 1 ${offset + radius} ${offset}`);
    }
  }

  // 闭合路径
  pathSegments.push('Z');

  return pathSegments.join(' ');
});
</script>

<style scoped>
.game-tile {
  position: relative;
  width: 80px; /* 可根据需求调整瓦片大小 */
  height: 80px;
  box-sizing: border-box;
}

.tile-border {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none; /* 让SVG不拦截鼠标事件,保证瓦片可交互 */
}
</style>

针对对角相邻场景的扩展

如果需要处理F8与G9这类对角同组的情况,只需在props.field.border中添加对角状态(如topRight、bottomLeft等),然后在路径生成时调整对应拐角的逻辑:

  • 比如当topRight为true(右上角对角有同组瓦片),则跳过右上角的圆角或绘制斜向连接线段,避免出现多余的直角边框。

方案优势

  1. 矢量无像素化:SVG放大后依然清晰,完美解决Canvas的像素化问题;
  2. 精确控制边缘:通过路径指令可以自定义任意形状的边框,覆盖CSS无法处理的特殊场景;
  3. 灵活扩展:可轻松添加对角、多方向相邻的判断逻辑,适配复杂游戏地图需求;
  4. 性能友好:SVG作为DOM元素,渲染性能优于大量Canvas绘制,且可复用路径逻辑。

内容的提问来源于stack exchange,提问作者Alice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:01:04