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

SVG转Canvas实现蓝点随人体模型边缘动态缩放的简易方案问询

可行!实现SVG转Canvas并同步缩放蓝色圆点

核心思路

  • 利用SVG的viewBox获取原始尺寸,计算统一缩放比例,保证人体模型不变形
  • 单独提取蓝色圆点的坐标与半径,应用相同缩放因子,确保圆点始终贴合人体边缘
  • 将SVG转为DataURL加载到Canvas,叠加绘制缩放后的圆点实现精准控制

完整实现代码

HTML结构

<div>
  <label>输入目标高度(px):</label>
  <input type="number" id="heightInput" value="842" min="100" max="2000">
  <button onclick="updateCanvas()">更新尺寸</button>
</div>
<canvas id="humanCanvas"></canvas>

JavaScript逻辑

// 你的原始SVG字符串
const svgString = `
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 595.3 841.9" style="enable-background:new 0 0 595.3 841.9;" xml:space="preserve">
  <style type="text/css">
    .st0 {
      fill: #040305;
    }
    .st1 {
      fill: #5E459C;
    }
  </style>
  <g>
    <path class="st0" d="M322.2,837h143.3c19.6,0,37.1-15.6,39.1-34.7c7.8-77.7-7.9-175.3-22.6-211.1c-4.6-11.1-10.8-21.3-17.4-32.2
        c-18-29.5-38.3-63-36.2-129.5c2-62,37.1-104.1,57.9-123.7c10.5-9.9,22-28.1,22.6-44.9c1.7-48.9-12.9-83.6-25.4-104.1
        c-9.2-15.2-29.6-24.1-44.6-25.8c-17.8-2.1-50.7-7.6-71.1-20.7c-14.8-9.4-19-28.3-19.8-43c4.7-6,7.7-12.7,7.7-20.2
        c0-23.1-26-41.1-59.2-41.1c-33.2,0-59.2,18.1-59.2,41.1c0,7.6,3.1,14.5,8,20.6c-0.9,14.6-5.1,33.2-19.9,42.5
        c-20.4,13-53.3,18.6-71.1,20.7c-15.4,1.8-35.7,11.3-44.6,25.9c-12.5,20.5-27,55.2-25.4,104c0.6,16.8,12.1,35.1,22.6,44.9
        c20.8,19.6,56,61.7,57.9,123.7c2.1,66.5-18.3,100-36.3,129.6c-6.6,10.8-12.8,21.1-17.4,32.1c-14.7,35.8-30.5,133.4-22.6,211.1
        c1.9,19.1,19.5,34.7,39.1,34.7h103.8 M296.5,32.3c19.8,0,32.9,8.9,32.9,14.8s-13.1,14.8-32.9,14.8c-19.8,0-32.9-8.9-32.9-14.8
        S276.7,32.3,296.5,32.3z M253.3,836.9h47 M473.6,799.1c-0.4,3.3-4.4,6.6-8.1,6.6H127.7c-3.7,0-7.7-3.3-8.1-6.6
        c-7.2-71.8,7.3-164.1,20.5-196.1c3.6-8.8,9-17.6,15.2-27.9c19.2-31.6,43.1-70.9,40.7-146.7c-2.3-73.2-43.4-122.6-67.8-145.4
        c-6.5-6.1-12.6-17.1-12.7-23.2c-1.4-41.1,10.6-69.9,20.8-86.8c2.5-4.1,13-10.1,21.6-11.1c24.9-3,59.8-9.8,84.2-25.3
        c19.7-12.6,28.4-32.8,32.1-51.3c6.8,1.9,14.3,3,22.2,3c8.1,0,15.6-1.1,22.6-3c3.6,18.5,12.3,38.7,32.1,51.4
        c24.4,15.6,59.3,22.4,84.2,25.3c8.9,1.1,19.1,6.9,21.6,11.1c10.3,16.9,22.2,45.7,20.8,86.8c-0.2,6-6.3,17.1-12.8,23.2
        c-24.3,22.9-65.4,72.2-67.7,145.4c-2.4,75.9,21.5,115.1,40.7,146.7c6.2,10.2,11.6,19.1,15.2,27.9
        C466.3,635.1,480.8,727.4,473.6,799.1z" />
  </g>
  <circle class="st1" cx="100.1" cy="253.2" r="15.4" />
  <circle class="st1" cx="494.1" cy="253.2" r="15.4" />
  <circle class="st1" cx="144.1" cy="149.2" r="15.4" />
  <circle class="st1" cx="455.1" cy="149.2" r="15.4" />
  <circle class="st1" cx="147.1" cy="329.2" r="15.4" />
  <circle class="st1" cx="180.1" cy="450.2" r="15.4" />
  <circle class="st1" cx="161.1" cy="532.2" r="15.4" />
  <circle class="st1" cx="433.1" cy="532.2" r="15.4" />
  <circle class="st1" cx="413.1" cy="450.2" r="15.4" />
  <circle class="st1" cx="446.1" cy="329.2" r="15.4" />
  <circle class="st1" cx="110.1" cy="659.2" r="15.4" />
  <circle class="st1" cx="103.1" cy="797.2" r="15.4" />
  <circle class="st1" cx="489.1" cy="797.2" r="15.4" />
  <circle class="st1" cx="483.1" cy="659.2" r="15.4" />
</svg>
`;

// 解析SVG提取关键数据
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
const viewBox = svgDoc.querySelector("svg").getAttribute("viewBox").split(" ").map(Number);
const originalWidth = viewBox[2];
const originalHeight = viewBox[3];
const circles = Array.from(svgDoc.querySelectorAll("circle")).map(c => ({
  cx: parseFloat(c.getAttribute("cx")),
  cy: parseFloat(c.getAttribute("cy")),
  r: parseFloat(c.getAttribute("r"))
}));

// 获取Canvas上下文
const canvas = document.getElementById("humanCanvas");
const ctx = canvas.getContext("2d");

// 初始化渲染
updateCanvas();

function updateCanvas() {
  const targetHeight = parseInt(document.getElementById("heightInput").value);
  const scale = targetHeight / originalHeight;
  const targetWidth = originalWidth * scale;

  // 设置Canvas尺寸
  canvas.width = targetWidth;
  canvas.height = targetHeight;
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 加载并绘制缩放后的人体模型
  const img = new Image();
  img.onload = () => {
    ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
    // 绘制同步缩放的蓝色圆点
    ctx.fillStyle = "#5E459C";
    circles.forEach(c => {
      ctx.beginPath();
      ctx.arc(c.cx * scale, c.cy * scale, c.r * scale, 0, Math.PI * 2);
      ctx.fill();
    });
  };
  img.src = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgString)))}`;
}

关键细节说明

  • 宽高比保持:以输入的高度为基准,按SVG原始宽高比计算目标宽度,避免人体模型拉伸变形
  • 圆点精准缩放:提前提取所有圆点的坐标和半径,应用与人体模型相同的缩放因子,确保位置和大小完全同步
  • SVG转Canvas:通过DataURL将SVG转为图片资源加载,再叠加绘制圆点,既保留SVG的矢量清晰度,又实现对圆点的独立控制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:25:55