Треугольники JavaScript неправильно масштабируютсяCSS

Разбираемся в CSS
Ответить
Anonymous
 Треугольники JavaScript неправильно масштабируются

Сообщение Anonymous »

Я работаю над эффектом, который создает множество точек и триангулирует их для создания простой фоновой анимации. Однако когда я пытаюсь их уменьшить, не все строки масштабируются соответствующим образом и часто не совпадают.
Вот код, который создает все

Код: Выделить всё

const numNodes = 40;

let ac = [];
let moveAC = [];

const gradient = {
len: 6,
gradients: [
[225, 238, 88],
[0, 188, 212],
[229, 115, 115],
[74, 20, 140],
[129, 199, 132],
[255, 255, 255]
]
}

let grad1 = Math.round(Math.random() * (gradient.len - 1));
let grad2 = Math.round(Math.random() * (gradient.len - 1));

while (grad1 == grad2) {
grad2 = Math.round(Math.random() * (gradient.len - 1));
}

console.log(grad1, grad2);

grad1 = gradient.gradients[grad1];
grad2 = gradient.gradients[grad2];

function initialize_background() {
for (let i = 0; i < numNodes; i++) {
let posX = Math.random() * 100;
let posY = Math.random() * 100;
let coord = [posX, posY]
ac.push(coord);

let vecX = Math.random() * 2 - 1;
let vecY = Math.random() * 2 - 1;
let vector = [vecX, vecY];
moveAC.push(vector);
}

let edgeSmooth = 10;

for (let i = 1; i < edgeSmooth; i++) {
let pos = (i / edgeSmooth) * 100;
ac.push([pos, 0]);
ac.push([pos, 100]);
ac.push([0, pos]);
ac.push([100, pos]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);
}

ac.push([0, 0]);
ac.push([0, 100]);
ac.push([100, 0]);
ac.push([100, 100]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);
moveAC.push([0, 0]);

updateBackground();
}

function updateElementPosition(element, index) {
let speed = 0.1;
let newX = element[0] + moveAC[index][0]*speed;
let newY = element[1] + moveAC[index][1]*speed;

newX = (newX < 0)? 100 : ((newX > 100)? 0 : newX);
newY = (newY < 0)? 100 : ((newY > 100)? 0 : newY);

ac[index] = [newX, newY];
}

async function updateBackground() {
document.querySelectorAll(".triangle").forEach((element) => {
element.remove();
});

for (let i = 0; i < ac.length; i++) {
updateElementPosition(ac[i], i);
}

let triangles = orderCoordinatesToTriangles();

const docFrag = document.createDocumentFragment();

triangles.forEach((element) => {
let child = createTriangle(ac[element[0]], ac[element[1]], ac[element[2]], element[4]);
if (child != null) docFrag.appendChild(child);
});

document.getElementById("background-container").appendChild(docFrag);

await delay(25);
updateBackground();

}

function orderCoordinatesToTriangles() {
let triangles = [];
for (let e1 = 0; e1 < ac.length; e1 ++) {
for (let e2 = e1+1; e2 < ac.length; e2 ++) {
for (let e3 = e2+1; e3 < ac.length; e3 ++) {
let coord = sortToCounterClockwise(e1, e2, e3, ac);
let anyPointsWithin = false;

for (let e4 = 0; e4 < ac.length;  e4 ++) {
if (e1 == e4 || e2 == e4 || e3 == e4) {
continue;
}
if (calculateDeterminant3x3(coord, e4)) {
anyPointsWithin = true;
break;
}
}

if (!anyPointsWithin) {
triangles.push(coord);
}
}
}
}

return triangles;
}

function calculateDeterminant3x3(coord, e4) {
const ax = ac[(coord[0])][0];
const ay = ac[coord[0]][1];
const bx = ac[coord[1]][0];
const by = ac[coord[1]][1];
const cx = ac[coord[2]][0];
const cy = ac[coord[2]][1];
const dx = ac[e4][0];
const dy = ac[e4][1];

const det1 = (ax-dx) * calculateDeterminant2x2((by-dy), calcDifferentDet(bx, dx, by, dy), (cy-dy), calcDifferentDet(cx, dx, cy, dy));
const det2 = (ay-dy) * calculateDeterminant2x2((bx-dx), calcDifferentDet(bx, dx, by, dy), (cx-dx), calcDifferentDet(cx, dx, cy, dy));
const det3 = calcDifferentDet(ax, dx, ay, dy) * calculateDeterminant2x2((bx-dx), (by-dy), (cx-dx), (cy-dy));

const result = det1 - det2 + det3;
return (result > 0);
}

// returns (e1 - e2)^2 + (e3 - e4)^2
function calcDifferentDet(e1, e2, e3, e4) {
return Math.pow(e1 - e2, 2) + Math.pow(e3 - e4, 2);
}

// | e1, e2 |
// | e3, e4 |
function calculateDeterminant2x2(e1, e2, e3, e4) {
return ((e1 * e4) - (e2*e3));
}

function sortToCounterClockwise(e1, e2, e3, ac) {
let coord = [];
const centerX = (ac[e1][0] + ac[e2][0] + ac[e3][0])/3;
const centerY = (ac[e1][1] + ac[e2][1] + ac[e3][1])/3;

let angle1 = get_angle([ac[e1][0] - centerX, ac[e1][1] - centerY]);
let angle2 = get_angle([ac[e2][0] - centerX, ac[e2][1] - centerY]);
let angle3 = get_angle([ac[e3][0] - centerX, ac[e3][1] - centerY]);

if (angle1 < 90) angle1 += 360;
if (angle2 < 90) angle2 += 360;
if (angle3 < 90) angle3 += 360;

if (angle1 < angle2 && angle1 < angle3) {
coord.push(e1);
if (angle2 < angle3) {coord.push(e2); coord.push(e3);}
else {coord.push(e3); coord.push(e2);}
}
else if (angle2 < angle1 && angle2 < angle3) {
coord.push(e2);
if (angle1 < angle3) {coord.push(e1); coord.push(e3);}
else {coord.push(e3); coord.push(e1);}
}
else {
coord.push(e3);
if (angle1 < angle2) {coord.push(e1); coord.push(e2);}
else {coord.push(e2); coord.push(e1);}
}

coord.push(centerX);
coord.push(centerY);

return coord;
}

const getScale = (cX, cY, pX, pY, s) => {
sSx = window.innerWidth;
sSy = window.innerHeight;

v = make_vector([pX, pY], [cX, cY]);
u = unit_vector(v);

return (pX + s*u[0])*sSx/100 + "px " + (pY+ s*u[1])*sSy/100 + "px";
}

function createTriangle(p1, p2, p3, centerY) {
const newTriangle = document.createElement("div");
newTriangle.className = "triangle";
let cX = (p1[0] + p2[0] + p3[0]) / 3;
let cY = ((p1[1]) + (p2[1]) + (p3[1])) / 3;
let scale = 0.2;

coord1 = getScale(cX, cY, p1[0], (p1[1]), scale);
coord2 = getScale(cX, cY, p2[0], (p2[1]), scale);
coord3 = getScale(cX, cY, p3[0], (p3[1]), scale);
newTriangle.style.backgroundColor = "rgb(" + colourFunction(0, centerY) + ", " + colourFunction(1, centerY) + ", " + colourFunction(2, centerY) + ")";
newTriangle.style.clipPath = "polygon(" + coord1 + ", " + coord2 + ", " + coord3 + ")";

if (!newTriangle.style.clipPath) {
return null;
}

return newTriangle;
}

function colourFunction(i, cY) {
return (grad1[i] + ((grad2[i] - grad1[i]) * (1 - (cY / 100))));
}
А код векторов следующий

Код: Выделить всё

//Turn current position into a vector given a vector matrix
const get_vector = (e1, e2, a) => {
const wa = a[e2][1] - a[e1][1];
const wb = a[e2][0] - a[e1][0];
return [wb, wa];
};

//make a vector given arrays
const make_vector = (e1, e2) => {
const wa = e2[1] - e1[1];
const wb = e2[0] - e1[0];
return [wb, wa];
};

//Get current width of a vector
const get_width = (v) =>  {
const wa = Math.pow(v[0], 2);
const wb = Math.pow(v[1], 2);
return Math.sqrt(wa + wb);
};

//Get current angle of a vector with the line 
const get_angle = (v) => {
let angle = Math.acos((v[0] / get_width(v)))*180/Math.PI;
if (v[1] < 0) {angle = 360 - angle;}
return angle;
};

//get unit vector
const unit_vector= (v) => {
let width = get_width(v);
return [v[0]/width, v[1]/width];
};
Однако я получаю нечто похожее на следующий результат:
Один кадр анимации
Некоторые границы толще других, и я не уверен, в чем проблема

Подробнее здесь: https://stackoverflow.com/questions/784 ... -correctly
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «CSS»