我正在为我的游戏制作 map编辑器。我有一个svg,其中将包含许多<polyline>
。每当用户单击的任何行时<polyline>
。我把两件事当作信息。单击鼠标的坐标以及该折线的所有点的顺序。
我想检查单击线之间的那两个点是什么。
为此,我使用了距离公式。如果AB
是一条线,我们要检查该点是否C
在该线上。我们将检查的距离AB
是否等于BC + AC
。
下面是我的代码。
const poly = document.getElementById("poly");
poly.onclick = function(e){
const mousePos = [e.clientX,e.clientY];
//console.log(mousePos)
const points = poly.getAttribute('points').split(' ').map(x => x.split(',').map(Number));
const res= points.find((p, i) => {
let prevPoint = points[i-1];
if(i === 0){
prevPoint = points[points.length - 1];
}
return arePointsCollinear(prevPoint, p, mousePos)
});
if(res){
console.log(res);
}
}
const getDistance = (pointA, pointB) => {
const dx = Math.pow(pointA[0] - pointB[0], 2);
const dy = Math.pow(pointA[1] - pointB[1], 2);
return Math.sqrt(dx + dy);
};
const arePointsCollinear = (
pointA,
pointB,
pointC
) => {
const totalDistance = getDistance(pointA, pointB);
const deltaAC = getDistance(pointA, pointC);
const deltaBC = getDistance(pointB, pointC);
return totalDistance === deltaAC + deltaBC;
};
svg polyline{
fill:none;
stroke:black;
stroke-width: 10
}
svg{
height:500px;
width:500px;
}
body{
padding: 0;
margin: 0;
}
<svg xmlns="http://www.w3.org/2000/svg">
<polyline id="poly" points="100,100 150,200 250,150 100,100"/>
</svg>
上面代码中的问题是它没有考虑线的宽度。意味着我们恰好在行的中心单击以获取答案。我希望每当我单击线时都应该告诉该线的两点。
我有工作
https://codepen.io/Alexander9111/pen/rNaERKa
HTML:
<svg id="svg" height="500" width="500" xmlns="http://www.w3.org/2000/svg">
<polyline id="poly" points="100,100 150,200 250,150 100,100"/>
</svg>
JS:
const svg = document.getElementById("svg");
const poly = document.getElementById("poly");
const poly_width = getComputedStyle(poly)['stroke-width'];
console.log(parseInt(poly_width));
const half_width = parseInt(poly_width) / 2;
poly.onclick = function(e){
const mousePos = [e.clientX,e.clientY];
console.log(mousePos)
const points = poly.getAttribute('points').split(' ').map(x => x.split(',').map(Number));
const res= points.find((p, i) => {
let prevPoint = points[i-1];
if(i === 0){
prevPoint = points[points.length - 1];
}
return arePointsCollinear(prevPoint, p, mousePos)
});
if(res){
console.log(res);
const NS = 'http://www.w3.org/2000/svg';
const circle = document.createElementNS(NS,'circle');
circle.setAttribute('r', '5');
circle.setAttribute('cx', res[0]);
circle.setAttribute('cy', res[1]);
svg.appendChild(circle);
console.log('circle');
}
}
const getDistance = (pointA, pointB) => {
const dx = Math.pow(pointA[0] - pointB[0], 2);
const dy = Math.pow(pointA[1] - pointB[1], 2);
return Math.sqrt(dx + dy);
};
const arePointsCollinear = (
pointA,
pointB,
pointC
) => {
const totalDistance = getDistance(pointA, pointB);
const deltaAC = getDistance(pointA, pointC);
const deltaBC = getDistance(pointB, pointC);
return deltaAC + deltaBC <= Math.sqrt(totalDistance**2 + half_width**2);
};
最重要的是return deltaAC + deltaBC <= Math.sqrt(totalDistance**2 + half_width**2);
-我画了一张图来说明这是从哪里来的:
基本上,您需要考虑仍在笔划宽度内的最长路径。我相信这是(lengthAB ^ 2加half_stroke-width ^ 2)的平方根
更新
如果要添加线,则需要更改points.find()
为,points.findIndex()
则可以使用索引和prevIndex在点之间画一条线:
JS:
const svg = document.getElementById("svg");
const poly = document.getElementById("poly");
const poly_width = getComputedStyle(poly)['stroke-width'];
console.log(parseInt(poly_width));
const half_width = parseInt(poly_width) / 2;
poly.onclick = function(e){
const mousePos = [e.clientX,e.clientY];
console.log(mousePos)
const points = poly.getAttribute('points').split(' ').map(x => x.split(',').map(Number));
const res= points.findIndex((p, i) => {
let prevPoint = points[i-1];
if(i === 0){
prevPoint = points[points.length - 1];
}
return arePointsCollinear(prevPoint, p, mousePos)
});
if(res != -1){
console.log(res);
const NS = 'http://www.w3.org/2000/svg';
const line = document.createElementNS(NS,'line')
// const circle = document.createElementNS(NS,'circle');
// circle.setAttribute('r', '5');
// circle.setAttribute('cx', points[res][0]);
// circle.setAttribute('cy', points[res][1]);
// svg.appendChild(circle);
// console.log('circle');
line.setAttribute('x1', points[res][0]);
line.setAttribute('y1', points[res][1]);
let prevIndex = (res === 0) ? (points.length - 1) : res - 1;
line.setAttribute('x2', points[prevIndex][0]);
line.setAttribute('y2', points[prevIndex][1]);
svg.appendChild(line);
console.log('line');
}
}
const getDistance = (pointA, pointB) => {
const dx = Math.pow(pointA[0] - pointB[0], 2);
const dy = Math.pow(pointA[1] - pointB[1], 2);
return Math.sqrt(dx + dy);
};
const arePointsCollinear = (
pointA,
pointB,
pointC
) => {
const totalDistance = getDistance(pointA, pointB);
const deltaAC = getDistance(pointA, pointC);
const deltaBC = getDistance(pointB, pointC);
return deltaAC + deltaBC <= Math.sqrt(totalDistance**2 + (2*half_width)**2);
};