svg - 如何使用 svg 路径创建时髦的圆圈?
问题描述
我正在尝试复制 Patrick Heng (patrickheng.com) 在他的网站上所做的事情。当您将鼠标悬停在固定圆圈上时,我想创建这种时髦的效果。我最接近的方法是使用路径创建圆然后更改路径值,但这会产生非常糟糕的结果并且不受控制。
<path
d="
M 25, 50
a 25,25 0 1,1 50,0
a 25,25 0 1,1 -50,0
" />
我们可以改变 和 的M
值a
。
解决方案
这是与二次贝塞尔路径类似的东西:
const angleFromCenter = (cx, cy, mx, my) => {
const mAngle = Math.atan2(mx - cx, - my + cy);
return mAngle > 0 ? mAngle : (Math.PI * 2 + mAngle);
};
const circlePath = (cx, cy, r, mx, my) => {
const dist = Math.hypot(mx - cx, my - cy);
let path = '';
if (dist > r) {
const angle = angleFromCenter(cx, cy, mx, my);
const delta = Math.acos(r / dist);
const p0x = cx + r * Math.sin(angle - delta);
const p0y = cy - r * Math.cos(angle - delta);
const p2x = cx + r * Math.sin(angle + delta);
const p2y = cy - r * Math.cos(angle + delta);
const anchorR = dist > r * 2 ? r * 4 - dist : dist;
const p1x = cx + anchorR * Math.sin(angle);
const p1y = cy - anchorR * Math.cos(angle);
path = `M ${p0x},${p0y} Q ${p1x},${p1y} ${p2x},${p2y}`;
}
return path + `M ${cx},${cy - r} A ${r},${r} 1 1 1 ${cx},${cy + r} A ${r},${r} 1 1 1 ${cx},${cy - r} Z`;
}
const svg = d3.select('svg')
const path = circlePath(100, 100, 50, 100, 100);
const circle = svg.append('path')
.attr('d', path)
.style('fill', 'blue');
svg.on('mousemove', (e) => {
const d = circlePath(100, 100, 50, e.offsetX, e.offsetY);
circle.attr('d', d);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="200" height="200">
</svg>
推荐阅读
- ant-media-server - Hash based Publish/Play in Ant Media Cluster
- flutter - 在 Inkwell 中使用导航在构建期间调用 setState() 或 markNeedsBuild()
- html - 为什么我的行不居中且每行包含 3 张图片?
- python - 在 pytorch kmeans 中使用 pytorch Dataloader
- python - 关于虚拟环境、PATH 变量和命令行的问题
- css - 如何让具有 flex 的父母让孩子溢出父母
- c++ - cfapi CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS 反复回调
- mysql - 加入具有不同列的两个表
- javascript - function.prototype.constructor.name 和 function.name 之间的 Javascript 区别
- database - 在 reddit 数据库上使用 Google Bigquery 来获取帖子以及所有评论