这篇文章要解决一个问题,就是给定 HTML 中任意一个点(起点)和另一个点(终点),绘制一条带箭头的曲线。
废话不多说,直奔主题。
我们只有两个点的相对偏移量(offset),思路就是以这两个点作为对角,创建一个绝对定位的 Canvas,然后在两点中绘制一条曲线(Curve),最后在终点处绘制箭头(Arrow)。
因此分为 3 步:
先确定 Canvas 的绝对定位偏移量,因为是任意两点,所以对角可能是左上加右下,也可能是左下加右上,不论是哪一种,它的左偏移量一定是两个点的左偏移量的最小值,同理,上偏移量也是两个点的上偏移量的最小值。
再确定 Canvas 的宽和高,宽等于两点左偏移量之差的模,长等于两点上偏移量之差的模。
// 随机的起始点和终点,这里不考虑边缘情况,实际生产环境下,相近的两点应该很少会有加指向性箭头的需求
const sp = {
left: Math.floor(window.innerWidth * Math.random()), top: Math.floor(window.innerHeight * Math.random()) };
const ep = {
left: Math.floor(window.innerWidth * Math.random()), top: Math.floor(window.innerHeight * Math.random()) };
const canvas = document.createElement('canvas');
canvas.style.position = 'absolute'; // 设置绝对定位
canvas.style.left = Math.min(sp.left, ep.left) + 'px'; // 设置左偏移量
canvas.style.top = Math.min(sp.top, ep.top) + 'px'; // 设置右偏移量
canvas.width = Math.abs(sp.left - ep.left); // 设置宽度
canvas.height = Math.abs(sp.top - ep.top); // 设置高度
// 顺便为 Canvas 加个红色的边框,方便 debug
canvas.style.border = '1px solid red';
// 把 Canvas 放到 body 中
document.body.appendChild(canvas);
Canvas 中绘制曲线很简单,API 中已经提供了贝塞尔曲线(Bezier Curve)的绘制方法。
而控制点的掌握…全靠经验
这里提供一个很简单,很好算的控制点,绘制出的曲线效果也非常好。
const ctx = canvas.getContext('2d'); // 获取 Canvas 上下文
// 下面求各点在 Canvas 中的坐标