二次贝塞尔曲线在线绘制
本帖最后由 马黑黑 于 2024-9-10 13:23 编辑代码:<style>
#pa { margin: 20px auto; padding: 0; width: 400px; height: 400px; min-width: 100px; min-height: 100px; border: 1px solid gray; resize: both; overflow: hidden; position: relative; }
#stage > circle { cursor: pointer; }
#sizeMsg { transform: translateY(20px); }
#pathMsg:active { user-select: all; }
.msgbox { margin: 0 auto; width: 400px; font: normal 18px/24px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; }
</style>
<div id="sizeMsg" class="msgbox">400*400</div>
<div id="pa" data-size="400*400">
<svg id="stage" width="400" height="400">
<path id="cPath" d="M10 200, C10 10, 390 10, 390 200" fill="none" stroke="steelblue"></path>
<circle id="start" cx="10" cy="200" r="5" fill="teal"></circle>
<circle id="c1" cx="200" cy="10" r="5" fill="red"></circle>
<circle id="end" cx="390" cy="200" r="5" fill="teal"></circle>
</svg>
</div>
<div id="pathMsg" class="msgbox"></div>
<script>
var balls = ;
var currentball = null;
var ro = new ResizeObserver(elms => {
var rect = elms.contentRect;
var data = {
stage: { w: stage.getAttribute('width'), h: stage.getAttribute('height') },
start: { x : start.getAttribute('cx'), y: start.getAttribute('cy') },
c1: { x : c1.getAttribute('cx'), y: c1.getAttribute('cy') },
end: { x : end.getAttribute('cx'), y: end.getAttribute('cy') },
};
setPos(stage, 'width', rect.width);
setPos(stage, 'height', rect.height);
setPos(start, 'cx', (data.start.x * rect.width / data.stage.w).toFixed(2));
setPos(start, 'cy', (data.start.y * rect.height / data.stage.h).toFixed(2));
setPos(c1,'cx', (data.c1.x * rect.width / data.stage.w).toFixed(2));
setPos(c1, 'cy', (data.c1.y * rect.height / data.stage.h).toFixed(2));
setPos(end, 'cx', (data.end.x * rect.width / data.stage.w).toFixed(2));
setPos(end, 'cy', (data.end.y * rect.height / data.stage.h).toFixed(2));
cPath.setAttribute('d', setPath(start,c1,end));
pathMsg.innerText = `d='${cPath.getAttribute('d')}'`;
pathMsg.style.setProperty('width', rect.width + 'px');
sizeMsg.style.setProperty('width', rect.width + 'px');
sizeMsg.innerText = rect.width + '*'+ rect.height;
});
ro.observe(pa);
setPath = (e1,e2,e3) => `M${e1.getAttribute('cx')} ${e1.getAttribute('cy')},Q${e2.getAttribute('cx')} ${e2.getAttribute('cy')},${e3.getAttribute('cx')} ${e3.getAttribute('cy')}`;
setPos = (elm,name, val) => elm.setAttribute(name, val);
balls.forEach(ball => {
ball.onmousedown = () => currentball = ball;
ball.onmouseup = () => currentball = null;
});
document.onmouseup = () => currentball = null;
stage.onmousemove = (e) => {
if(!currentball) return;
setPos(currentball, 'cx', e.offsetX);
setPos(currentball, 'cy', e.offsetY);
cPath.setAttribute('d', setPath(start,c1,end));
pathMsg.innerText = `d='${cPath.getAttribute('d')}'`;
};
</script>链接:二次贝塞尔曲线在线绘制 (52qingyin.cn)
两端的线头、控制点都可以拖曳。控制点被限制在svg场景中,实际上它可以脱离svg元素,但这样一来会看不到也控制不了控制点,所以简化了;如果需要更陡峭的控制点数值,可以在拿到路径后修改控制点的值。
盒子可以改变大小,操作入口在右下角,向右下或左上拖曳,盒子会变大变小,盒子的尺寸信息实时呈现在盒子的左上方。
三次贝塞尔曲线在线绘制正在测试中,最迟明天发布。 谢谢老师教材! 谢谢老师辛苦! 这个厉害了,拖曳盒子的时候,三个点还能自动保持和盒子的相对关系呢{:4_187:} 而且盒子也一直自动居中,把盒子拉大了,在上面任意调着3个点,感受着曲线的变化。
当头尾两个点在不同高度上,也可以调整中间的点得到一段比较规整的圆弧,貌似要得到一个斜向的正圆弧,计算出来的值比这样调出来的更准确些{:4_173:} 马黑黑 发表于 2024-9-10 12:03
两端的线头、控制点都可以拖曳。控制点被限制在svg场景中,实际上它可以脱离svg元素,但这样一来会看不到也 ...
三次贝塞尔曲线多了一个控制点,更复杂了。
黑黑厉害,让计算机去处理计算公式,我们只要用鼠标去拉动一下,就能看到它的样子和得到路径{:4_187:} 所有的点都可以画面内的任意位置,比之前想象的更灵活。。可以实现各种形状的需要。。太厉害了。。 看了说明才发现,页面中画面大小可更改,以适合各种大小的贴子。。真是只要能想到的老师都能做到。。帅。 花飞飞 发表于 2024-9-10 20:10
看了说明才发现,页面中画面大小可更改,以适合各种大小的贴子。。真是只要能想到的老师都能做到。。帅。
{:4_172:} 彩云归 发表于 2024-9-10 12:53
谢谢老师教材!
{:4_190:} 梦江南 发表于 2024-9-10 17:46
谢谢老师辛苦!
{:4_190:} 红影 发表于 2024-9-10 19:28
这个厉害了,拖曳盒子的时候,三个点还能自动保持和盒子的相对关系呢
这是做了计算的,看源码应该可以看得出来 花飞飞 发表于 2024-9-10 20:06
所有的点都可以画面内的任意位置,比之前想象的更灵活。。可以实现各种形状的需要。。太厉害了。。
难点就在这里,所有的点都要计算,不过万变不离其宗,曲线的原理就在那里。实现这个,函数的作用就很明显了。 红影 发表于 2024-9-10 19:44
三次贝塞尔曲线多了一个控制点,更复杂了。
黑黑厉害,让计算机去处理计算公式,我们只要用鼠标去拉动一 ...
实际上是先做了三次再做二次。过去有过演示三次的,但没有演示二次的,且起点和终点不可变,现在曲线上所有的点都可变。 马黑黑 发表于 2024-9-10 20:52
这是做了计算的,看源码应该可以看得出来
嗯嗯,这些是被设定好的{:4_187:} 马黑黑 发表于 2024-9-10 20:55
实际上是先做了三次再做二次。过去有过演示三次的,但没有演示二次的,且起点和终点不可变,现在曲线上所 ...
所有点都能变,需要考虑和设计的更多了{:4_187:} 红影 发表于 2024-9-10 23:45
嗯嗯,这些是被设定好的
这就是所谓的编程了:很多情况都是处理数学问题。 红影 发表于 2024-9-10 23:46
所有点都能变,需要考虑和设计的更多了
其实倒也不是酱紫,就是要操作的点多了,比较繁琐而已。 马黑黑 发表于 2024-9-10 23:47
这就是所谓的编程了:很多情况都是处理数学问题。
处理好了以后,就可以交给计算机去运作了。编程也是指挥计算机工作的指挥行为{:4_204:}