Создание зала кинотеатра
Я изпользую svg для создания зала. Перепробовала кучу вариаций как сделать эти места кликабельными и все никак... Задача: при нажатии на определенное место должен выводится текст, например "Ряд:1, Место:1", и менятся цвет выбранного места, так же чтоб была возможность вторым кликом по месту отменить выбор.
В каждом ряду у меня по 15 мест, рядов 9. Вот кусочек кода мест.
<svg width="580" height="450" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#cccccc" id="canvas_background" height="452" width="582" y="-1" x="-1"/>
</g>
<g>
<rect type="button" onmousedown="viewDiv()" rx="4" id="svg_1" height="17" width="22" y="194.44792" x="90" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_2" height="17" width="22" y="194.44792" x="117" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_3" height="17" width="22" y="194.44792" x="144" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_4" height="17" width="22" y="194.44792" x="171" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_5" height="17" width="22" y="194.44792" x="198" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_6" height="17" width="22" y="194.44792" x="225" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_7" height="17" width="22" y="194.44792" x="252" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_8" height="17" width="22" y="194.44792" x="279" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_9" height="17" width="22" y="194.44792" x="306" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_10" height="17" width="22" y="194.44792" x="333" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_11" height="17" width="22" y="194.44792" x="360" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_12" height="17" width="22" y="194.44792" x="387" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_13" height="17" width="22" y="194.44792" x="414" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_14" height="17" width="22" y="194.44792" x="441" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_15" height="17" width="22" y="194" x="468" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_16" height="17" width="22" y="217" x="90" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_17" height="17" width="22" y="217" x="117" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_18" height="17" width="22" y="217" x="144" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_19" height="17" width="22" y="217" x="171" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_20" height="17" width="22" y="217" x="198" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_21" height="17" width="22" y="217" x="225" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
</g>
</svg>
Вот одна из попыток
<input type="button" value="Click" onmousedown="viewDiv()">
<div id="div1">Блок</div>
<script>
function viewDiv(){
document.getElementById("div1").style.display = "block";
};
</script>
<style>
#div1{
display: none;
}
</style>
Но так выводит текст только последнего места, и нет отмены нажатия и изменения цвета. Конечно же было и туча других проб, но все безрезультатны... Что-то да и не хотело работать, то цвет, то нажатие, то вывод текста. Помогите пожалуйста разобраться.
Ответы (3 шт):
Если кол-во мест в каждом ряде не является переменным значением, то сгодится такой подход:
- Задаем идентификатор для всей группы с прямоугольниками.
- Вешаем обработчик события click на группу.
- В обработчике выясняем индекс нажатого прямоугольника.
- Путем несложной арифметики вычисляем ряд и место.
let places = document.getElementById('places');
places.addEventListener("click", function(e) {
let target = e.target;
let i = Array.from(target.parentNode.children).indexOf(target);
let row = Math.floor(i / 15) + 1;
let place = i % 15 + 1;
target.classList.toggle('selected');
console.log('Ряд: ' + row + ', Место: ' + place);
});
.selected {
fill: green;
}
<svg width="580" height="450" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#cccccc" id="canvas_background" height="452" width="582" y="-1" x="-1"/>
</g>
<g id="places">
<rect type="button" rx="4" id="svg_1" height="17" width="22" y="194.44792" x="90" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_2" height="17" width="22" y="194.44792" x="117" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_3" height="17" width="22" y="194.44792" x="144" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_4" height="17" width="22" y="194.44792" x="171" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_5" height="17" width="22" y="194.44792" x="198" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_6" height="17" width="22" y="194.44792" x="225" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_7" height="17" width="22" y="194.44792" x="252" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_8" height="17" width="22" y="194.44792" x="279" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_9" height="17" width="22" y="194.44792" x="306" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_10" height="17" width="22" y="194.44792" x="333" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_11" height="17" width="22" y="194.44792" x="360" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_12" height="17" width="22" y="194.44792" x="387" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_13" height="17" width="22" y="194.44792" x="414" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_14" height="17" width="22" y="194.44792" x="441" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_15" height="17" width="22" y="194" x="468" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_16" height="17" width="22" y="217" x="90" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_17" height="17" width="22" y="217" x="117" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_18" height="17" width="22" y="217" x="144" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_19" height="17" width="22" y="217" x="171" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_20" height="17" width="22" y="217" x="198" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
<rect type="button" rx="4" id="svg_21" height="17" width="22" y="217" x="225" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#969696"/>
</g>
</svg>
Если структура мест неоднозначна, то следует применять другой подход. Каждому rect присвоить класс .place, например, а также атрибуты с указанием ряда и места. Для всех элементов с данным классом повесить обработчик, в котором из атрибутов извлечь ряд и место.
Предлагаю более гибкий вариант, чтобы не возиться с копипастой и вычислением x-ов и y-ов:
const places = document.querySelector('#places');
places.addEventListener('click', (e) => {
if (e.target.getAttribute('type') !== 'button') return;
e.target.classList.toggle('active');
console.log(e.target.dataset.text);
});
const rectStaticAttributes = [
['type', 'button'],
['rx', '4'],
['height', '17'],
['width', '22'],
['fill-opacity', 'null'],
['stroke-opacity', 'null'],
['stroke-width', '0'],
['stroke', '#000']
];
const horizontalOffset = 27;
const verticalOffset = 23;
const createRectTag = (id, column, row) => {
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
const setRectAttribute = (item) => rect.setAttribute(item[0], item[1])
rectStaticAttributes.forEach(setRectAttribute);
[
['id', id],
['x', 90 + horizontalOffset * column],
['y', 194 + verticalOffset * row],
['data-text', `Ряд:${row + 1}, Место:${column + 1}`]
].forEach(setRectAttribute);
return rect;
}
const placesInEachRow = 15;
const placesCount = 21;
const placesContainer = document.createDocumentFragment();
for (let i = 0, j = -1; i < placesCount; ++i) {
const column = i % placesInEachRow;
const row = column === 0 ? ++j : j;
placesContainer.append(createRectTag(`svg_${i + 1}`, column, row));
}
places.append(placesContainer);
rect[type=button] {
fill: #969696;
}
rect[type=button].active {
fill: green;
}
<svg width="580" height="450" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#cccccc" id="canvas_background" height="452" width="582" y="-1" x="-1"/>
</g>
<g id="places">
</g>
</svg>
Я бы сделал следующим образом, назначал для элементов дата атрибуты.
let places = document.querySelector('#places'),
output = document.querySelector('#output');
places.addEventListener('click', function(e) {
let target = e.target;
if(target.tagName.toLowerCase() === 'use') {
target.classList.toggle('selected');
let selected = places.querySelectorAll('.selected');
if(selected.length > 0) {
output.innerHTML = '';
selected.forEach(function(e) {
let row = e.getAttribute('data-row'),
place = e.getAttribute('data-place');
output.innerHTML += `Место: ${place}, ряд: ${row};<br>`;
});
} else output.innerText = 'Ничего не выбрано';
}
});
#places use {
fill: #969696;
}
#place:hover {
stroke-width: 1;
stroke: #08f;
}
#places .selected {
fill: green;
}
<svg width="580" height="450" xmlns="http://www.w3.org/2000/svg" id="hall">
<defs>
<rect type="button" rx="4" id="place" height="17" width="22" stroke-width="0" stroke="#000"/>
</defs>
<g>
<rect fill="#cccccc" id="canvas_background" height="452" width="582" y="-1" x="-1"/>
</g>
<g id="places">
<use xlink:href="#place" y="194.44792" x="90" data-row="1" data-place="1"/>
<use xlink:href="#place" y="194.44792" x="117" data-row="1" data-place="2"/>
<use xlink:href="#place" y="194.44792" x="144" data-row="1" data-place="3"/>
<use xlink:href="#place" y="194.44792" x="171" data-row="1" data-place="4"/>
<use xlink:href="#place" y="194.44792" x="198" data-row="1" data-place="5"/>
<use xlink:href="#place" y="194.44792" x="225" data-row="1" data-place="6"/>
<use xlink:href="#place" y="194.44792" x="252" data-row="1" data-place="7"/>
<use xlink:href="#place" y="194.44792" x="279" data-row="1" data-place="8"/>
<use xlink:href="#place" y="194.44792" x="306" data-row="1" data-place="9"/>
<use xlink:href="#place" y="194.44792" x="333" data-row="1" data-place="10"/>
<use xlink:href="#place" y="194.44792" x="360" data-row="1" data-place="11"/>
<use xlink:href="#place" y="194.44792" x="387" data-row="1" data-place="12"/>
<use xlink:href="#place" y="194.44792" x="414" data-row="1" data-place="13"/>
<use xlink:href="#place" y="194.44792" x="441" data-row="1" data-place="14"/>
<use xlink:href="#place" y="194" x="468" data-row="2" data-place="1"/>
<use xlink:href="#place" y="217" x="90" data-row="2" data-place="2"/>
<use xlink:href="#place" y="217" x="117" data-row="2" data-place="3"/>
<use xlink:href="#place" y="217" x="144" data-row="2" data-place="4"/>
<use xlink:href="#place" y="217" x="171" data-row="2" data-place="5"/>
<use xlink:href="#place" y="217" x="198" data-row="2" data-place="6"/>
<use xlink:href="#place" y="217" x="225" data-row="2" data-place="7"/>
</g>
</svg>
<div id="output"></div>