Соедините SVG Rect с гармошкой - PullRequest
0 голосов
/ 15 января 2020

У меня есть изображение SVG с наведением мыши на четыре прямоугольных элемента и аккордеон с четырьмя кнопками, выполненными с помощью javascript. Я хочу соединить каждый элемент, одновременно наведя на них курсор (прямоугольник и кнопочный аккордеон), и нажав на SVG-прямоугольник, он откроет кнопочный аккордеон и, нажав на аккордеон, заполнит прямоугольник. Вы можете проверить мою скрипку здесь: https://jsfiddle.net/pfrutuoso/zcsj8g05/2/ Это мой html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div class="wrapper">
        <div class="stage_info">
            <button class="accordion">Stage 1</button>
            <div class="panel">
                <p>Information here..</p>
            </div>

            <button class="accordion">Stage 2</button>
            <div class="panel">
                <p>Information here..</p>
            </div>
            <button class="accordion">Stage 3</button>
            <div class="panel">
                <p>Information here..</p>
            </div>
            <button class="accordion">Stage 4</button>
            <div class="panel">
                <p>Information here..</p>
            </div>
        </div>
        <div class="stage_img">
            <map id="big_stage">
            <svg version="1.1" id="stadium" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
            width="100%" height="100%" viewBox="0 0 456.122 451.02" enable-background="new 0 0 456.122 451.02"
            xml:space="preserve">
       <rect id="stage4" x="25.51" y="25.51" fill="#1C6131" width="200" height="200"/>
       <rect id="stage3" x="230.612" y="25.51" fill="#1C6131" width="200" height="200"/>
       <rect id="stage2" x="25.51" y="229.592" fill="#1C6131" width="200" height="200"/>
       <rect id="stage1" x="230.612" y="229.592" fill="#1C6131" width="200" height="200"/>
       </svg>
           </map>

        </div>
    </div>
</body>

</html>

Мой css:

.accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
}

.active,
.accordion:hover {
    background-color: #ccc;
}

.panel {
    padding: 0 18px;
    background-color: white;
    display: none;
    overflow: hidden;
}

.wrapper {
    display: inline-block;
    max-width: 1140px;
    margin: 0 auto;
    width: 100%;
    text-align: center;
}

.stage_info,
.stage_img {
    display: inline-block;
    width: calc(50% - 80px);
    vertical-align: top;
}

rect {
    cursor: pointer;
    z-index: 999;
    position: relative;
}

rect:hover {
    fill: #ccc;
    pointer-events: all;
}

И мой javascript:

var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var panel = this.nextElementSibling;
        if (panel.style.display === "block") {
            panel.style.display = "none";
        } else {
            panel.style.display = "block";
        }
    });
}

1 Ответ

1 голос
/ 16 января 2020

Я пытался сделать это настолько процедурно, насколько это было возможно, так, как вы, похоже, и ожидали в своем JS. Я добавил атрибуты значения к кнопкам вашей сцены с id соответствующих rect элементов и добавил class с именем grey с теми же свойствами, что и при наведении курсора.

	let stgInf = document.querySelector(".stage_info");
	let svg = document.querySelector("#stadium");

	function onClick(num) {
		let acc = stgInf.querySelector(`.accordion:nth-of-type(${num})`);
		let panel = acc.nextElementSibling;
		let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
		return () => {
			acc.classList.toggle("active");
			if (acc.classList.contains("active")) {
				panel.style.display = "block";
				rect.classList.add("grey");
			} else {
				panel.style.display = "none";
				rect.classList.remove("grey");
			}
		}
	}

	function hover(num) {
		let acc = stgInf.querySelector(`.accordion:nth-of-type(${num})`);
		let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
		return (event) => {
			if (event.type === "mouseenter") {
				acc.classList.add("grey");
				rect.classList.add("grey");
			} else if (!acc.classList.contains("active")) {
				acc.classList.remove("grey");
				rect.classList.remove("grey");
			}
		}
	}

	let accs = stgInf.querySelectorAll(".accordion");
	let i = 1;
	for (let acc of accs) {
		let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
		acc.addEventListener("click", onClick(i));
		acc.addEventListener("mouseenter", hover(i));
		acc.addEventListener("mouseout", hover(i));
		rect.addEventListener("click", onClick(i));
		rect.addEventListener("mouseenter", hover(i));
		rect.addEventListener("mouseout", hover(i));
		++i;
	}
		.accordion {
			background-color: #eee;
			color: #444;
			cursor: pointer;
			padding: 18px;
			width: 100%;
			text-align: left;
			border: none;
			outline: none;
			transition: 0.4s;
		}

		.panel {
			padding: 0 18px;
			background-color: white;
			display: none;
			overflow: hidden;
		}

		.wrapper {
			display: inline-block;
			max-width: 1140px;
			margin: 0 auto;
			width: 100%;
			text-align: center;
		}
		.stage_info,
		.stage_img {
			display: inline-block;
			width: calc(50% - 80px);
			vertical-align: top;
		}

		rect {
			cursor: pointer;
			z-index: 999;
			position: relative;
		}

		.grey,
		.active,
		.accordion:hover,
		rect:hover {
			fill: #ccc;
			background-color: #ccc;
			pointer-events: all;
		}
<div class="wrapper">
  <div class="stage_info">
    <button class="accordion" value="stage1">Stage 1</button>
    <div class="panel">
      <p>Information here..</p>
    </div>
    <button class="accordion" value="stage2">Stage 2</button>
    <div class="panel">
      <p>Information here..</p>
    </div>
    <button class="accordion" value="stage3">Stage 3</button>
    <div class="panel">
      <p>Information here..</p>
    </div>
    <button class="accordion" value="stage4">Stage 4</button>
    <div class="panel">
      <p>Information here..</p>
    </div>
  </div>
  <div class="stage_img">
    <map id="big_stage">
            <svg version="1.1" id="stadium" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
            width="100%" height="100%" viewBox="0 0 456.122 451.02" enable-background="new 0 0 456.122 451.02"
            xml:space="preserve">
				<rect id="stage4" x="25.51" y="25.51" fill="#1C6131" width="200" height="200"/>
				<rect id="stage3" x="230.612" y="25.51" fill="#1C6131" width="200" height="200"/>
				<rect id="stage2" x="25.51" y="229.592" fill="#1C6131" width="200" height="200"/>
				<rect id="stage1" x="230.612" y="229.592" fill="#1C6131" width="200" height="200"/>
			</svg>
           </map>
  </div>
</div>

РЕДАКТИРОВАТЬ

Я реализовал функцию наведения мыши, о которой вы упоминали в своем комментарии, добавив mouseenter и mouseout event слушатели в дополнение к слушателям щелчка.

...