Заостренная кривая Безье, созданная с помощью JavaScript - PullRequest
0 голосов
/ 01 ноября 2018

Я впервые поиграл с ванильным JavaScript и SVG. Сейчас я нахожусь в такой ситуации, когда не могу решить проблему самостоятельно.

Идея состояла в том, чтобы переместить точки на их оси Y. Ось X задается уже существующими точками (красные кружки).

Теперь я вычисляю равнобедренный треугольник, центрированный по значению x курсора. Треугольник движется вместе с мышью. Теперь пересечение данных точек (красные кружки) с треугольником вычислено. На этом точки пересечения установлены. Через эти точки я рисую кривую Безье.

Идея, лежащая в основе треугольника, заключается в том, что я не хочу создавать очень "крутой" кривой, когда красные точки находятся дальше друг от друга. Так что я могу «разложить это» / немного сгладить кривую. По крайней мере, это идея.

Основы пока работают отлично, но происходит странная вещь: в двух точках (отмеченных синим) кривая выглядит как симулированный треугольник - но все точки между ними создают идеальную кривую Безье.

Я не могу понять, что происходит. Буду очень признателен за любой вклад - пожалуйста, будьте добры с моим (возможно) плохим кодом - я новичок. ;)

Спасибо!

CodePen: https://codepen.io/clmsvie/pen/Edqzpp?editors=1111

var n = 0;

c1x = 50;
d = 350;

var gap = 100;

var dotsX = [];
var dotsXY = [];

// Kreise zeichnen
var svg = document.querySelector("svg");

for (var i = 0; i <= 8; i++) {
  var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
  circle.setAttributeNS(null, "class", "blub c" + i);
  circle.setAttributeNS(null, "cx", c1x);
  circle.setAttributeNS(null, "cy", d);
  circle.setAttributeNS(null, "r", 15);
  svg.appendChild(circle);
  dotsX.push(c1x); // Werte der Punkte ins Array schreiben
  dotsXY.push(c1x);
  c1x += gap;
}

// Dreieck zeichnen, entlang der virtuellen x Achse
var $tri = document.querySelectorAll(".triangle");

ta = 100; // Strecke = Höhe
tc = 250; // Strecke = Distanz x-Achse
tB = 350; // Punkt = X Punkt der Maus

ax = tB - tc; // A
ay = d;
bx = tB; // B
by = d;
cx = tB; //C
cy = d - ta;

// Maus Koordinaten feststellen

function mouseMove(e) {
  x = typeof e.pageX != "undefined" ? e.pageX : e.touches[0].pageX;
  y = typeof e.pageY != "undefined" ? e.pageY : e.touches[0].pageY;

  //console.log("x = " + x + " y = " + y);

  // Punkt entlang b Achse eines Rechtwinkligen Dreiecks verschieben

  tB = x;

  ax = x - tc; // A
  ay = d;
  bx = x; // B
  by = d;
  cx = x; //C
  cy = d - ta;

  setDots();
}

"mousemove touchmove".split(" ").forEach(function(e) {
  document.addEventListener(e, mouseMove, true);
});

function setDots() {
  // ### Rote Kreise auf Dreieck setzen

  // 2. Brechne neue Höhe der Punkte (auf Dreieck)

  var dotsXY = dotsX.map(function(dotX) {
    tA = tB - tc;
    disDotInTri = dotX < tB ? dotX - tA : tB + tc - dotX;
    dotY = d - disDotInTri * ta / tc;
    dotY = dotY <= d ? dotY : d; // Nicht negativ werden
    return [dotX, dotY.toFixed(2)];
  });

  //console.log("Y-Werte: " + dotsXY);

  var path =
    "M0," +
    d +
    " C" +
    dotsXY
      .map(function(dot) {
        return dot[0] + "," + dot[1];
      })
      .join(" ");

  console.log(path);
  console.log(dotsXY[0] + " - " + dotsXY[2] + " - " + dotsXY[4]);

  // Kontrollpunkte

  var paras = document.getElementsByClassName("kontrolle");

  while (paras[0]) {
    paras[0].parentNode.removeChild(paras[0]);
  }

  for (var i = 0; i < dotsXY.length; i++) {
    var circleKontrolle = document.createElementNS(
      "http://www.w3.org/2000/svg",
      "circle"
    );
    circleKontrolle.setAttributeNS(null, "class", "blub kontrolle");
    circleKontrolle.setAttributeNS(null, "cx", dotsXY[i][0]);
    circleKontrolle.setAttributeNS(null, "cy", dotsXY[i][1]);
    circleKontrolle.setAttributeNS(null, "r", 5);
    svg.appendChild(circleKontrolle);
  }

  document.querySelector("path").setAttribute("d", path);
}
svg {
  width: 100%;
  height: 400px;
  background-color:#d1ff88;
}

path {
  stroke: black;
  stroke-width: 10px;
  stroke-linecap: round;
  fill: none;
}

.blub {
  stroke: black;
  stroke-width: 3px;
  fill: red;
}

#bezier-path {
  stroke: red;
    fill: none;
    stroke-width: 1.2;
}

.c2, .c5 {
  fill: blue;
}
<svg class="test">
  <path xmlns="http://www.w3.org/2000/svg" stroke="red" fill="none" id="bezier-path" stroke-width="1.2" d="M0,350 C50,333.20 150,293.20 250,253.20 350,286.80 450,326.80 550,350.00 650,350.00 750,350.00 850,350.00"/>
</svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...