Интерактивные формы многоугольника - PullRequest
0 голосов
/ 14 октября 2018

У меня есть несколько координатных точек, таких как [0, 0], [30, 0], [30, 20], [60, 20], [60, 40], [0, 40], [0, 0]

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

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

Во-вторых, что лучше всего преобразоватьэти точки как линии или пути?Сгенерированные линии должны быть достаточно толстыми, но не через штриховую ширину.

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

Пример кода со линиями и прямоугольниками, размещенными по углам, не дал мне идеальных результатов, возможно, из-за ширины штриха:

<svg id="SvgjsSvg1001" width="700" height="400" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" viewBox="-100 -20 350 200"><defs id="SvgjsDefs1002"></defs><g id="SvgjsG1008" transform="matrix(2.5,0,0,2.5,0,0)"><line id="SvgjsLine1009" x1="0" y1="0" x2="30" y2="0" stroke-linecap="square" stroke="#ffdc0b" stroke-width="4"></line><line id="SvgjsLine1010" x1="30" y1="0" x2="30" y2="20" stroke-linecap="square" stroke="#002438" stroke-width="4"></line><line id="SvgjsLine1011" x1="30" y1="20" x2="60" y2="20" stroke-linecap="square" stroke="#9b56bb" stroke-width="4"></line><line id="SvgjsLine1012" x1="60" y1="20" x2="60" y2="40" stroke-linecap="square" stroke="#c6c7e2" stroke-width="4"></line><line id="SvgjsLine1013" x1="60" y1="40" x2="0" y2="40" stroke-linecap="square" stroke="#318700" stroke-width="4"></line><line id="SvgjsLine1014" x1="0" y1="40" x2="0" y2="0" stroke-linecap="square" stroke="#fe854f" stroke-width="4"></line>
<rect width="5" height="5" x="30" y="0"></rect>
<rect width="5" height="5" x="30" y="20"></rect>
<rect width="5" height="5" x="60" y="20"></rect>
<rect width="5" height="5" x="60" y="40"></rect>
<rect width="5" height="5" x="0" y="40"></rect>
<rect width="5" height="5" x="0" y="0"></rect></g></svg>

1 Ответ

0 голосов
/ 14 октября 2018

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

Для взаимодействия с мышью я использую cursor: pointer; для каждого угла.

const SVG_NS = "http://www.w3.org/2000/svg";
let pathsRy = Array.from(document.querySelectorAll("path"));

let rectsRy = [];

pathsRy.forEach(p => {
  let pbbox = p.getBBox();
  rectsRy.push(
    drawRect(
      {
        x: pbbox.x,
        y: pbbox.y,
        width: 5,
        height: 5,
        class: "corner"
      },
      svg
    )
  );
});

let gbbox = group.getBBox();
rectsRy.push(
  drawRect(
    {
      x: gbbox.x + gbbox.width - 5,
      y: gbbox.y + gbbox.height - 5,
      width: 5,
      height: 5,
      class: "corner"
    },
    svg
  )
);

function drawRect(o, parent) {
  var rect = document.createElementNS(SVG_NS, "rect");
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      rect.setAttributeNS(null, name, o[name]);
    }
  }
  parent.appendChild(rect);
  return rect;
}
.corner {
  fill: rgba(255, 0, 0, 0.5);
  cursor: pointer;
}

svg {
  overflow: visible;
}

path {
  fill: none;
  stroke: black;
  stroke-linejoin: round;
}
<svg id="svg" viewBox="0 0 70 70" width="200" >
<g id="group">  
  <path d="M0,0 L30,0 25,5 5,5z" /> 
           
  <path d="M30,0 L30,20 25,25 25,5z" /> 
  
  <path d="M30,20 L60,20 55,25 25,25" />
  
  <path d="M60,20 L60,40 55,35 55,25" /> 
  
  <path d="M60,40 L0,40 5,35 55,35z" />
           
  <path d="M0,40 L0,0 5,5 5,35z" />
  </g>
</svg>

Обратите внимание, что это работает с такими формами.Для фигуры с несколькими «точками поворота» и в другом положении это не сработает.

ОБНОВЛЕНИЕ
  1. Я не загромождаю ваш код.Поскольку все строки имеют одинаковый stroke-linecap, я помещаю его в SVG.Также я перемещаю stroke-width в JavaScript, так как он мне нужен там.

  2. В Javascript я определяю массив строк linesRy.Для каждой строки я получаю значение атрибутов x1 и y1.

  3. Используя значения значений для атрибутов x1 и y1 каждой строки и stroke-width Я рисую розовый rect в каждом углу.

ОП обновил вопрос, опубликовав некоторый код.Я тоже обновляю свой код:

const SVG_NS = "http://www.w3.org/2000/svg";

let strokeWidth = 4

let linesRy = Array.from(document.querySelectorAll("line"));

linesRy.forEach((l)=>{
  l.setAttributeNS(null, "stroke-width", strokeWidth);
  let x = l.getAttribute("x1");
  let y = l.getAttribute("y1");
  
  drawRect({
    x:x-strokeWidth/2,
    y:y-strokeWidth/2,
    width:strokeWidth,
    height:strokeWidth,
    class:"pink"
  }, SvgjsG1008);
})


function drawRect(o, parent) {
  var rect = document.createElementNS(SVG_NS, "rect");
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      rect.setAttributeNS(null, name, o[name]);
    }
  }
  parent.appendChild(rect);
  return rect;
}
line{
stroke-linecap:square;
}

.pink{fill:pink}
<svg id="SvgjsSvg1001" width="700" height="400" viewBox="-100 -20 350 200">
<g id="SvgjsG1008" transform="matrix(2.5,0,0,2.5,0,0)"><line id="SvgjsLine1009" x1="0" y1="0" x2="30" y2="0"  stroke="#ffdc0b" ></line>
  
<line id="SvgjsLine1010" x1="30" y1="0" x2="30" y2="20" stroke="#002438"></line>

<line id="SvgjsLine1011" x1="30" y1="20" x2="60" y2="20" stroke="#9b56bb"></line>
  
<line id="SvgjsLine1012" x1="60" y1="20" x2="60" y2="40" stroke="#c6c7e2"></line>
   
<line id="SvgjsLine1013" x1="60" y1="40" x2="0" y2="40"  stroke="#318700" ></line>

<line id="SvgjsLine1014" x1="0" y1="40" x2="0" y2="0" stroke="#fe854f" ></line>
  
  
  
<!--  
<rect width="5" height="5" x="30" y="0"></rect>
<rect width="5" height="5" x="30" y="20"></rect>
<rect width="5" height="5" x="60" y="20"></rect>
<rect width="5" height="5" x="60" y="40"></rect>
<rect width="5" height="5" x="0" y="40"></rect>
<rect width="5" height="5" x="0" y="0"></rect>-->

</g></svg>
...