我正在编写最多 4 个电荷的磁场模拟器,但我不明白角度计算有什么问题。
函数generarCargas是创建箭头的函数,抱歉,如果我没有发表评论,如果您对代码有任何疑问,我会立即回答。
JS:
//Funcion angle
function angle(cx, cy, ex, ey) {
const dy = ey - cy;
const dx = ex - cx;
const rad = Math.atan2(dy, dx);
const deg = (rad * 180) / Math.PI;
return deg;
}
//Funcion getPositionAtCenter
function getPositionAtCenter(element) {
const { top, left, width, height } = element.getBoundingClientRect();
return {
x: left + width / 2,
y: top + height / 2,
};
}
//Funcion getDistanceBetweenElements
function getDistanceBetweenElements(a, b) {
const aPosition = getPositionAtCenter(a);
const bPosition = getPositionAtCenter(b);
return Math.hypot(aPosition.x - bPosition.x, aPosition.y - bPosition.y);
}
function generarCargas(selectValues) {
const arrows = document.querySelectorAll(".arrow");
selectValues.forEach((carga) => {
const cargaDiv = document.createElement("div");
cargaDiv.className = "carga";
const div = document.createElement("div");
cargaDiv.appendChild(div);
div.textContent = carga;
allCampo.appendChild(cargaDiv);
valoresCarga = carga;
});
let dragItem = null;
let offsetX = 0;
let offsetY = 0;
allCampo.addEventListener("mousedown", (e) => {
const cargaDiv = e.target.closest(".carga");
if (cargaDiv) {
dragItem = cargaDiv;
offsetX = e.clientX - cargaDiv.getBoundingClientRect().left;
offsetY = e.clientY - cargaDiv.getBoundingClientRect().top;
document.addEventListener("mousemove", handleDrag);
document.addEventListener("mouseup", () => {
document.removeEventListener("mousemove", handleDrag);
dragItem = null;
});
function handleDrag(e) {
if (dragItem) {
const posX = e.clientX - offsetX;
const posY = e.clientY - offsetY;
dragItem.style.left = posX + "px";
dragItem.style.top = posY + "px";
}
const cargas = document.querySelectorAll(".carga");
arrows.forEach((arrow) => {
let angles = [];
let eRx = 0;
let eRy = 0;
let resultantAngle;
cargas.forEach((carga, index) => {
let qx = getPositionAtCenter(carga).x;
let qy = getPositionAtCenter(carga).y;
let distancia = getDistanceBetweenElements(arrow, carga) / 100;
let e;
const rekt = arrow.getBoundingClientRect();
const anchorX = rekt.left + rekt.width / 2;
const anchorY = rekt.top + rekt.height / 2;
let angleDeg = angle(qx, qy, anchorX, anchorY);
let cargaValue = parseInt(carga.textContent);
if (cargaValue < 0) {
angleDeg = angleDeg - 180;
cargaValue = -cargaValue;
}
e = (k * cargaValue) / Math.pow(distancia, 2);
let ex = e * Math.cos((angleDeg * Math.PI) / 180);
let ey = e * Math.sin((angleDeg * Math.PI) / 180);
eRx += ex;
eRy += ey;
angles.push(angleDeg);
});
let resultant = Math.sqrt(Math.pow(eRx, 2) + Math.pow(eRy, 2));
let tanAlpha = eRy / eRx;
let alpha = (Math.atan(tanAlpha) * 180) / Math.PI;
arrow.style.transform = "rotate(" + alpha + "deg)";
});
}
}
});
}
您的代码似乎大部分设置正确,可以计算模拟磁场的角度。但是,如何处理角度计算可能存在问题,尤其是在考虑多个费用及其累积效应时。以下是一些可能解决该问题的建议和代码片段:
tanAlpha
和alpha
的计算正确。使用 Math.atan2(eRy, eRx)
可能会更稳健,因为它可以处理所有象限以及零分母的可能性。这是对代码部分计算每个箭头角度的修改尝试:
// Inside handleDrag function
arrows.forEach((arrow) => {
let eRx = 0;
let eRy = 0;
cargas.forEach((carga) => {
const { x: qx, y: qy } = getPositionAtCenter(carga);
const distancia = getDistanceBetweenElements(arrow, carga) / 100;
const cargaValue = parseInt(carga.textContent);
const rekt = arrow.getBoundingClientRect();
const anchorX = rekt.left + rekt.width / 2;
const anchorY = rekt.top + rekt.height / 2;
let angleDeg = angle(qx, qy, anchorX, anchorY);
let e = (k * Math.abs(cargaValue)) / Math.pow(distancia, 2);
// Adjust direction for negative charges
if (cargaValue < 0) {
angleDeg += 180;
}
let ex = e * Math.cos((angleDeg * Math.PI) / 180);
let ey = e * Math.sin((angleDeg * Math.PI) / 180);
eRx += ex;
eRy += ey;
});
let alpha = Math.atan2(eRy, eRx) * (180 / Math.PI);
arrow.style.transform = `rotate(${alpha}deg)`;
});
本次修订使用
Math.atan2
来更准确地计算角度,并确保只需将角度调整180度即可处理负电荷。这应该更准确地代表具有多个电荷的磁场的物理原理。