Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Добавление элементов при клике на данный блок

#javascript #svg #vuejs


Нужно сделать так, чтобы при клике по определённому блоку (100% на 100%, условно)
на месте клика появлялась SVG точка. 
    


Ответы

Ответ 1



Добавлять элементы на место клика можно так: var block = document.getElementById('block'); block.onclick = function(e) { var point = document.createElement('div'); point.className = 'point'; point.style.left = e.pageX + 'px'; point.style.top = e.pageY + 'px'; block.appendChild(point); } html, body { padding: 0px; margin: 0px; height: 100%; position: relative; } .block { width: 100%; height: 100%; position: absolute; left: 0px; top: 0px; } .block .point { position: absolute; width: 2px; height: 2px; background: #000; }


Ответ 2



Для реализации потребуется создать как минимум дочерний компонент, например: svg-point. Все точки из массива в родительском компоненте Vue перебираются через директиву v-for. В процессе перебора передаются необходимые данные компоненту svg-point. В качестве входящих параметров у этого компонента могут служить координаты XY. Сам же компонент отвечает только за визуальное отображение. Все действия по созданию/изменению/удалению точек происходят в родительском компоненте. При клике на родительский блок div необходимо проверять, не является ли элемент события click, унаследованным от SVGCircleElement, чтобы не размещать окружности друг над другом. В примере ниже все это реализовано: создание/редактирование/удаление. // Отключим ненужные для примера // сообщения в консоли. Vue.config.productionTip = false Vue.config.devtools = false const SvgPoint = { name: 'svg-point', props: { cx: Number, cy: Number }, computed: { // Для простоты задаём все атрибуты // ч/з вычисляемое свойство. pointStyle() { // Определим локально для удобства. // Критерием цвета послужит значение по оси Y. const criteria = this.$props.cy; // Цвет по умолчанию. let stroke = 'rgb(178, 214, 60)'; if (criteria > 300) { stroke = 'rgb(255, 121, 121)'; } else if (criteria > 150) { stroke = 'rgb(241, 196, 15)' } return { 'cx': this.$props.cx, // координата центра окружности по оси абсцисс 'cy': this.$props.cy, // координата центра окружности по оси ординат 'r': 1, // так как это точка, то радиус за единицу примем 'stroke': stroke, // цвет 'fill': 'transparent', // заливка роли не играет 'stroke-width': 8, // ..... чтобы точку видно было } } }, template: `` } new Vue({ el: '#app', // Локальная регистрация компонентов. components: { 'svg-point': SvgPoint }, data: { // Модель с точками. Добавим туда пару-тройку. points: [{ cx: 23, cy: 223 }, { cx: 118, cy: 280 }, { cx: 248, cy: 306.125 }, { cx: 341, cy: 261.125 }, { cx: 443, cy: 144.125 }, { cx: 508, cy: 26.125 }] }, methods: { // Обработка клика. clickHandler(event) { // event.stopPropagation(); // Определим локально для удобства // целевой объект клика. const target = event.target; // Если элемент, по которому кликнули - это точка: if (this.isCircle(target)) { // Отправляем на редактирование. // Индекс точки, взятый из атрибута `data-index`. return this.edit(target.dataset.index); } // Для подсчета координат точки. // Метод getBoundingClientRect() возвращает размер элемента и его позицию относительно `viewport`. // rectangle.left - слева; rectangle.top - сверху. // clientX - горизонтальная координата в пределах клиентской области приложения. // clientY - вертикальная координата в пределах клиентской области приложения. const rectangle = target.getBoundingClientRect(); // Сохраняем точку. this.save({ cx: event.clientX - rectangle.left, cy: event.clientY - rectangle.top }) }, // Обработка правого клика. removeHandler(event) { // event.stopPropagation(); // Определим локально для удобства. const target = event.target; // Если элемент, по которому кликнули - это точка: if (this.isCircle(target) && confirm('Удалить точку?')) { // Отправляем на удаление. // Индекс точки, взятый из атрибута `data-index`. return this.remove(target.dataset.index); } alert('Выберите точку для удаления!') }, // Сохранение точки. Просто добавляем в массив точек. save(data) { this.points.push({ cx: data.cx, cy: data.cy }) }, // Редактирование координат точки. edit(index) { // Найдем интересующую нас точку просто // по индексу из массива точек. const point = this.points[index]; const data = { // Сам в шоке, но почему бы и нет. cx: prompt('Укажите новую координату по оси абсцисс (x):', point.cx), cy: prompt('Укажите новую координату по оси ординат (y):', point.cy) } if (data.cx && data.cy) { // Отправляем на обновление. this.update(index, { // При ошибках в [0;0] отправляем. cx: parseFloat(data.cx), cy: parseFloat(data.cy) }) } }, // Обновление координат точки. update(index, data) { this.points.splice(index, 1, data); alert('Обновление точки'); }, // Удаление точки. remove(index) { this.points.splice(index, 1); alert('Удаление точки'); }, // Проверка объекта по принадлежности к классу. isCircle(element) { return element instanceof SVGCircleElement; }, // Экспорт в `.csv` файл. Без комментариев. exportToCsv(event) { let content = []; this.points.map(function(row) { content.push(Object.values(row).join(';')); }) // Заголовок и содержимое будущего файла. let csvContent = Object.keys(this.points[0]).join(';'); csvContent += "\r\n" + content.join("\r\n"); let url = URL.createObjectURL( new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }) ); event.target.setAttribute('href', url); event.target.setAttribute('download', '699135.csv'); } } }); *, *::after, *::before { box-sizing: border-box; } .points__boxs { margin: 0 auto; width: 600px; height: 400px; outline: 1px solid #08c; } .points__container { width: 100%; height: 100%; } circle:hover { r: 12px; }

Точкосоздаватель

  • ЛКМ - создание/редактирование точки.
  • ПКМ - удаление точки.
  • Экспорт файла .*csv по ссылке.
Дополнительно создан экспорт SVG точек в файл формата *.csv - разделителем служат ;.

Комментариев нет:

Отправить комментарий