我正在制作一个vue.js应用程序,它使用大量不同的图标,所以我决定在node.js中制作一个小型图标构建器来标准化它们的使用,它还"裁剪"每个svg,使其适合其父(使用viewbox属性).

尽管我偶然发现了一个问题,但将图标zoom 以适应正方形会让更多的"方形"看起来比圆形的要大,所以我想将它们zoom 成圆圈:

* {
  box-sizing: border-box;
}

.container {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 2rem;
}

.title {
  font-family: sans-serif;
  font-weight: 600;
  font-size: 24px;
  margin: 0;
}

.grid {
  display: flex;
  gap: 1.5rem;
}

.group {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  text-align: center;
}

.bg {
  width: 80px;
  height: 80px;
  background-color: lightgray;
}

.zone {
  border: 2px solid red;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.zone--wanted {
    border-radius: 50%;
  }

.icon {
  width: 100%;
  height: 100%;
  background-color: coral;
}

.icon--rounded {
  border-radius: 20%;
}
  
.icon--circle {
  border-radius: 50%;
}
  
.icon-scaled--rounded {
  width: 80%;
  height: 80%;
}

.icon-scaled--square {
  width: 70.71068%;
  height: 70.71068%;
}
<div class="container">
  <p class="title">What I have :</p>
  <div class="grid">
    <div class="bg">
      <div class="zone">
        <div class="icon"></div>
      </div>
    </div>
    <div class="bg">
      <div class="zone">
        <div class="icon icon--rounded"></div>
      </div>
    </div>
    <div class="bg">
      <div class="zone">
        <div class="icon icon--circle"></div>
      </div>
    </div>
  </div>
  <p class="title">What I want :</p>
  <div class="grid">
    <div class="bg">
      <div class="zone zone--wanted">
        <div class="icon icon-scaled--square"></div>
      </div>
    </div>
    <div class="bg">
      <div class="zone zone--wanted">
        <div class="icon icon--rounded icon-scaled--rounded"></div>
      </div>
    </div>
    <div class="bg">
      <div class="zone zone--wanted">
        <div class="icon icon--circle"></div>
      </div>
    </div>
  </div>
</div>

你们知道如何做到这一点吗?

推荐答案

这是一个非常原始的 idea :由于很容易获得元素的高度和垂直范围,因此如果我们旋转它并在每次旋转时采样宽度和高度,我们就可以得到对最大直径d的不错的估计.按r/dzoom (其中r是您想要放入的圆的直径)应该效果相当好.这对您的示例特别有效,因为我们知道最大直径是在45度旋转时,所以我们不需要太多样本;一个就足够了.如果您的形状奇怪,直径为10度,则需要更多样本来接近最大值.如果您采样不足,则JPEG元素将从圆圈中向外看一点.

function unitCircleScale(element, angles=4) {
  if (typeof angles == "number") {
    angles = Array.from({length: angles}, (_, i) => i * 90 / angles)
  }
  const initTransform = element.style.transform
  const transform = initTransform.replace(/rotate\([^)]*\)\s*;?/, '')
  const sizes = []
  for (const angle of angles) {
    element.style.transform = `rotate(${angle}deg) ${transform}`
    const bbox = element.parentNode.getBBox()
    sizes.push(bbox.width, bbox.height)
  }
  element.style.transform = initTransform
  return 2 / Math.max(...sizes)
}

const [rect, square, circle] = document.querySelectorAll("rect, circle")
// to fit into a 100-diameter (50-radius) circle, scale by:
// rough idea, at just 0deg and 45deg
console.log("rect at 2 samples:", 50 * unitCircleScale(rect, 2))
// better idea, with more samples
console.log("rect at 16 samples:", 50 * unitCircleScale(rect, 16))
// 45deg is ideal for a square, test just that
console.log("square at 45deg:", 50 * unitCircleScale(square, [45]))
// circle is same however you turn it, just do a single sample (i.e. 0deg)
console.log("circle at 1 sample:", 50 * unitCircleScale(circle, 1))
<svg width="400" height="120" xmlns="http://www.w3.org/2000/svg">
  <g>
    <rect width="150" height="50" x="10" y="10" style="fill:none; stroke:red" />
  </g>
  <g>
    <rect width="100" height="100" x="170" y="10" style="fill:none; stroke:blue" />
  </g>
  <g>
    <circle cx="330" cy="60" r="50" style="fill:none; stroke:green" />
  </g>
  Sorry, your browser does not support inline SVG.  
</svg>

请注意,这不会很快,因为它会交替更改属性,然后读取边界框,这意味着它将强制每次迭代重新布局.理想情况下,您需要计算一次理想的扩展并缓存它.

Javascript相关问答推荐

如何在不分配整个数组的情况下修改包含数组的行为主体?

使用useup时,React-Redux无法找到Redux上下文值

过滤对象数组并动态将属性放入新数组

格式值未保存在redux持久切片中

防止用户在selectizeInput中取消 Select 选项

如何在Connect 4游戏中 for each 玩家使用位板寻找7形状?

Snowflake JavaScript存储过程返回成功,尽管预期失败

点击按钮一次有文本出现和褪色,而不是点击两次?(html,CSS,JavaScript)

手机上的渲染错误文本必须在文本组件中渲染,但在浏览器上没有问题<><>

如何使用子字符串在数组中搜索重复项

如何在ASP.NET项目中使用Google Chart API JavaScript将二次轴线值格式化为百分比

NG/Express API路由处理程序停止工作

为什么客户端没有收到来自服务器的响应消息?

如何 for each 输入动态设置输入变更值

Docent.cloneNode(TRUE)不克隆用户输入

如何在一个对象Java脚本中获取不同键的重复值?

顶点图使用组标签更新列之间的条宽

按特定顺序将4个数组组合在一起,按ID分组

JQuery使用选项填充HTMLSELECT并设置默认结果,默认结果显示为空

使用Java脚本替换字符串中的小文本格式hashtag