Как получить javascript указатель мыши, чтобы выделить другие элементы в SVG-файле (изменение контекста) - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь решить очень простую задачу: два элемента; кнопка и прямоугольник. Когда вы наводите курсор на кнопку, прямоугольник меняет цвет заливки. Я попытался CSS, но по какой-то причине я не могу заставить ' className : hover targetClass {}' работать. Основная часть взята из Visio, и я пытался отредактировать его (* Редактировать: удаленные метаданные visio):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" 
width="8.26772in" height="11.6929in" viewBox="0 0 595.276 841.89" xml:space="preserve" color-interpolation-filters="sRGB" class="st3">

    <style type="text/css">
    <![CDATA[

        .st1 {fill:#5b9bd5;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5}
        .st2 {fill:#ffffff;font-family:Calibri;font-size:0.833336em}
        .st3 {fill:#FFFF00;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
        .button {fill:#5b9bd5;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5}
        .button:hover{fill: #FFFF00;}
    ]]>
    </style>

 <g id="ThePage">   
    <title>Page-1</title>

    <g id="shape2" transform="translate(283.465,-531.496)">
        <title>Multi-Attachment rectangle.2</title>
        <desc>Button text</desc>
        <rect x="0" y="799.37" width="56.6929" height="42.5197" class="button"/>
        <text x="5.25" y="823.63" class="st2" >Button text</text>   
    </g>

    <g id="shape1" transform="translate(255.118,-595.276)">
        <title>Multi-Attachment rectangle</title>
        <desc>Big box text</desc>
        <rect x="0" y="756.85" width="113.386" height="85.0394" class="st1"/>
        <text x="32.78" y="802.37" class="st2" >Big box text</text>     
    </g>
 </g>

</svg>

Мой javascript код, который я пытался реализовать, но не смог выполнить:

var javaButton = document.getElementsByClassName('button');

for (var i = 0; i < javaButton.length; i++) {
    javaButton[i].addEventListener('mouseover', mouseOverEffect);
    javaButton[i].addEventListener('mouseout', mouseOutEffect);
}

function mouseOverEffect() {
    this.classList.add("rect-highlight");
}

function mouseOutEffect() {
    this.classList.remove("rect-highlight");
}

Где "rect-highlight" находится в CSS части svg как: .rect-highlight {fill: # ec008c;}. Я знаю, что это работает, так как кнопка меняет цвет, если я наведу на нее курсор, однако необходимо получить контекст «this» для другого элемента. Как я могу это сделать?

* Редактировать: удалены метаданные visio

** Редактировать: добавлено тело кода

*** Редактировать: добавлены ограждения для кода, чтобы уценка не поедала мой код.

Ответы [ 3 ]

1 голос
/ 18 марта 2020

Не знаю, в чем ваша проблема, поскольку вы не предоставили образец SVG, но если вы хотите выделить связанные элементы, вы можете использовать селектор :hover.

Вы можете получить предыдущего и следующего родного брата текущего элемента путем доступа к previousElementSibling и nextElementSibling соответственно.

const showSiblings = (e) => toggleSiblings(e.target, true);
const resetSiblings = (e) => toggleSiblings(e.target, false);

Array.from(document.querySelectorAll('.box')).forEach(box => {
  box.addEventListener('mouseenter', showSiblings);
  box.addEventListener('mouseleave', resetSiblings);
});

function toggleSiblings(curr, visible) {
  let prev = curr.previousElementSibling;
  let next = curr.nextElementSibling;
  if (prev) {
    prev.classList.toggle('sib-prev', visible);
  }
  if (next) {
    next.classList.toggle('sib-next', visible);
  }
}
svg { background: #FF7F7F; }

.box { stroke-width: 4; cursor: pointer; }

.foo { fill: #4C4C7F; stroke: #00007F; }
.foo:hover { fill: #7F7FFF; }

.bar { fill: #7F7F4C; stroke: #7F7F00; }
.bar:hover { fill: #FFFF7F; }

.sib-prev.box {
  stroke: #FF0000;
}

.sib-next.box {
  stroke: #00FF00;
}
<svg width="260" height="196">
  <rect class="box foo" x="6" y="6" width="120" height="40" />
  <rect class="box bar" x="6" y="54" width="120" height="40" />
  <rect class="box foo" x="6" y="102" width="120" height="40" />
  <rect class="box bar" x="6" y="150" width="120" height="40" />
  
  <rect class="box bar" x="134" y="6" width="120" height="40" />
  <rect class="box foo" x="134" y="54" width="120" height="40" />
  <rect class="box bar" x="134" y="102" width="120" height="40" />
  <rect class="box foo" x="134" y="150" width="120" height="40" />
</svg>
0 голосов
/ 20 марта 2020

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

Я создал jsFiddle, который, я думаю, делает то, что вы хотите. Взгляните: https://jsfiddle.net/visioguy/nv3ew0fh/

Сначала я внес несколько изменений в ваш код :

  1. Я дал самый верхний a id = "ThePage", чтобы я мог избежать этого в коде js.
  2. Я установил class = "button" на , который содержит прямоугольник, а не на прямоугольник «подуровня», где он у вас был.
  3. Я добавил pointer-events = "none" к элементам внутри группы фигур кнопки. При наведении указателя мыши на элемент вызывается отключение мыши, даже если курсор все еще находится внутри группы. Эта установка событий указателя останавливает это поведение, но теперь вы не можете выбрать / скопировать текст. Это может быть просто отлично.
  4. В jsFiddle есть несколько стилей в отдельной области CSS.

Вот следующие дополнения к стилю CSS:

/* 
Make the SVG big enough to see and give
it a subtle color: 
*/
svg {
  background: whitesmoke;
  width: 500px;
  height: 500px;
}

/* 
Highlight direct <rect> children of any <g>
that has this class: 
*/
.rect-highlight > rect {
  fill: red;
}

А вот и javaScript. Я использовал querySelectorAll, чтобы найти фигуры в соответствии с CSS правилами. Если вы добавите другие поля без кнопок в , этот код найдет их и выделит:

// Select all <g> elements that are classed as 'button':
let buttonShapes = document.querySelectorAll('.button');
console.log("buttonShapes: ", buttonShapes.length);

// Add the event handlers to all of these button shapes:
for(let buttonShape of buttonShapes) {
    buttonShape.addEventListener('mouseenter', mouseEnterEffect);
    buttonShape.addEventListener('mouseout'  , mouseOutEffect);
}

function mouseEnterEffect(){

    // Select all other <g> in the SVG that are not classed as button
    // and are not id'd as ThePage:
    let otherShapes = document.querySelectorAll('g:not(.button):not(#ThePage)');
    console.log("otherShapes:", otherShapes.length); 

    for(let g of otherShapes) {
        g.classList.add("rect-highlight");
    }

}

function mouseOutEffect(){

    // Select all shapes that are groups <g> and are classed
    // with "rect-highlight":
    let highlightShapes = document.querySelectorAll('g.rect-highlight');
    console.log("highlightShapes:", highlightShapes.length); 

    for(let g of highlightShapes) {
        g.classList.remove("rect-highlight");
    }  

}

Последнее замечание: вы можете удалить все дополнительные элементы и атрибуты, которые добавляет Visio. По сути, все, что начинается с "v:". Это метаданные, которые Visio может прочитать, если вы решите повторно импортировать svg в Visio позднее. Такие вещи, как поля данных формы, пользовательские ячейки, слои, форматирование текста и другая информация хранятся в этих тегах.

0 голосов
/ 18 марта 2020

Когда вам действительно нужно решение javascript, go для ответов с javascript.

Этот ответ, однако, показывает простое решение, отличное от JS с использованием ванили CSS. Вы увидите кнопку и квадрат SVG. Просто используя CSS :hover и :focus на button и svg, цвет квадрата меняется в 4 раза ...

/*
    CSS Selector Reference
    https://www.w3schools.com/cssref/css_selectors.asp
*/
svg       { fill: red; width: 100px  }
svg:hover { fill: purple }

button:hover + svg { fill: lime } /* + = immediate sibling selector */
button:focus + svg { fill: blue }
<button>hover, click and unfocus me</button>
<svg viewbox="0 0 100 100"><rect width="100" height="100" x="0" y="0" /></svg>
...