Форум программистов, компьютерный форум, киберфорум
JavaScript
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 23.09.2019
Сообщений: 2

Интерактивная карта предприятия на чистом js

06.04.2024, 17:45. Показов 1109. Ответов 3
Метки html, js (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, форумчане!
Задача такая, есть div с фоном изображения карты условного предприятия. По кнопке в этот div должен добавить объект, например, камеру. По странице должен уметь перемещать сам div, а также внутри div перемещать добавленные объекты. На колесико должен применять zoom к div (уменьшение и увеличение).
Приблизительный код есть. Не могу побороть следующую ситуацию: после увеличения пытаюсь переместить камеру в div, но при первой попытке она резко увеличивается и отскакивает от курсора, при следующих она уже ведет себя как надо - перемещается за курсором без изменений размера.
Я понимаю, что это связано с координатной сеткой, dataset и scale объекта, но никак не могу побороть это. Помогите, пожалуйста!!!!
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
var scale = 1,
    images = document.querySelectorAll('.draggable-image'),
    activeImage = null,
    minScale = 0.7,
    maxScale = 2,
    panning = false;
 
function setTransform(element, pointX, pointY) {
    element.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
}
 
function handleMouseDown(e) {
    e.preventDefault();
    var target = e.target;
    if (target.classList.contains('draggable-image')) {
        activeImage = target;
        activeImage.startX = e.clientX - parseInt(activeImage.dataset.pointX || 0);
        activeImage.startY = e.clientY - parseInt(activeImage.dataset.pointY || 0);
        panning = true;
    }
}
 
function handleMouseUp() {
    panning = false;
    activeImage = null;
}
 
function handleMouseMove(e) {
    if (!panning || !activeImage) {
        return;
    }
 
    activeImage.dataset.pointX = e.clientX - activeImage.startX;
    activeImage.dataset.pointY = e.clientY - activeImage.startY;
    setTransform(activeImage, parseInt(activeImage.dataset.pointX / scale), parseInt(activeImage.dataset.pointY / scale));
}
 
function handleWheel(e) {
    var delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
    var canvasDiv = document.getElementById('canvas-cameras');
    var image = document.getElementById('image0');
    if (delta > 0 && scale < maxScale) {
        scale *= 1.2;
        
    } else if (delta < 0 && scale > minScale) {
        scale /= 1.2;
    }
 
    var xs = (e.clientX - parseInt(canvasDiv.dataset.pointX)) / scale,
        ys = (e.clientY - parseInt(canvasDiv.dataset.pointY)) / scale;
    canvasDiv.dataset.pointX = e.clientX - xs * scale;
    canvasDiv.dataset.pointY = e.clientY - ys * scale;
    setTransform(canvasDiv, parseInt(canvasDiv.dataset.pointX), parseInt(canvasDiv.dataset.pointY));
}
 
document.addEventListener('mousedown', handleMouseDown, { passive: false });
document.addEventListener('mouseup', handleMouseUp);
document.addEventListener('mousemove', handleMouseMove, { passive: false });
document.addEventListener('wheel', handleWheel, { passive: false });
 
var imageCounter = 0;
 
document.getElementById('addCamera').addEventListener('click', function () {
    showImage();
});
 
function showImage() {
    var imgElement = document.createElement('img');
    var canvasDiv = document.getElementById('canvas-cameras');
 
    imgElement.src = 'https://30.img.avito.st/image/1/1._DJTzra2UNtFburbJ_2oIZJtUNHtzVFh521S.o30giUQW-wMG3ar610UkHqINEtoYfC7c5jPPw6qYZxQ';
    imgElement.alt = 'Картинка ' + imageCounter;
    imgElement.className = 'draggable-image';
 
    imgElement.style.position = 'absolute';
   
    imgElement.style.maxHeight = '20px';
    imgElement.style.maxWidth = '20px';
    imgElement.style.height = 'auto';
    imgElement.style.width = 'auto';
    imgElement.style.display= 'block';
 
    var uniqueId = 'image' + imageCounter;
    imgElement.id = uniqueId;
 
    canvasDiv.appendChild(imgElement);
 
    images = document.querySelectorAll('.draggable-image');
 
    imgElement.dataset.pointX = 0;
    imgElement.dataset.pointY = 0;
 
    imageCounter++;
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.04.2024, 17:45
Ответы с готовыми решениями:

Интерактивная карта / псевдо карта
Всем добрый день. Столкнулся с проблемой построения интерактивной карти. Просмотреть такую карту можно на этом сайте - это границы...

Интерактивная карта
Создаю интерактивную карту подделаетесь опытом кто делал. собираюсь подсвечивать 72 региона. Делал с помощью с firework на сss получилось...

Интерактивная карта
Здравствуйте.Подскажите,какой командой или каким методом можно задать границы города при создании карт?Не заливка слоем внутри, а именно...

3
 Аватар для voraa
1289 / 1262 / 187
Регистрация: 21.01.2024
Сообщений: 5,804
07.04.2024, 08:45
Лучший ответ Сообщение было отмечено Sokolikk23 как решение

Решение

Вот такой вариант работает
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<!DOCTYPE html>
<html>
<head>
<style>
div {
    position:relative;
    width: 300px;
    height: 400px;  
    padding: 0;
    margin: 20px 30px;
}
img {
    display: block;
    width: 100%;
    height: 100%;
}
</style>
</head>
<body>
<div id="canvas-cameras" data-point-x="0" data-point-y="0">
<img src="https://www.cyberforum.ru/javascript/...map image....">
</div>
<button id="addCamera">addCamera</button>
<script>
var scale = 1,
    images = document.querySelectorAll('.draggable-image'),
    activeImage = null,
    minScale = 0.7,
    maxScale = 2,
    panning = false;
 
function setTransform(element, pointX, pointY) {
    element.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
}
 
function setTransformCamera(element, pointX, pointY) {
    element.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + 1/scale + ")";
}
 
function handleMouseDown(e) {
    e.preventDefault();
    var target = e.target;
    if (target.classList.contains('draggable-image')) {
        activeImage = target;
        activeImage.startX = e.clientX/scale - parseInt(activeImage.dataset.pointX || 0);
        activeImage.startY = e.clientY/scale - parseInt(activeImage.dataset.pointY || 0);
        panning = true;
    }
}
 
function handleMouseUp() {
    panning = false;
    activeImage = null;
}
 
function handleMouseMove(e) {
    if (!panning || !activeImage) {
        return;
    }
 
    activeImage.dataset.pointX = e.clientX/scale - activeImage.startX;
    activeImage.dataset.pointY = e.clientY/scale - activeImage.startY;
 
    setTransformCamera(activeImage, parseInt(activeImage.dataset.pointX), parseInt(activeImage.dataset.pointY));
}
 
function handleWheel(e) {
    var delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
    var canvasDiv = document.getElementById('canvas-cameras');
    var image = document.getElementById('image0');
    if (delta > 0 && scale < maxScale) {
        scale *= 1.2;
        
    } else if (delta < 0 && scale > minScale) {
        scale /= 1.2;
    }
 
    setTransform(canvasDiv, parseInt(canvasDiv.dataset.pointX), parseInt(canvasDiv.dataset.pointY));
    // Что бы камеры не изменяли размеры
    for (const image of images) {
        setTransformCamera(image,  parseInt(image.dataset.pointX), parseInt(image.dataset.pointY))
    }
}
 
document.addEventListener('mousedown', handleMouseDown, { passive: false });
document.addEventListener('mouseup', handleMouseUp);
document.addEventListener('mousemove', handleMouseMove, { passive: false });
document.addEventListener('wheel', handleWheel, { passive: false });
 
var imageCounter = 0;
 
document.getElementById('addCamera').addEventListener('click', function () {
    showImage();
});
 
function showImage() {
    var imgElement = document.createElement('img');
    var canvasDiv = document.getElementById('canvas-cameras');
 
    imgElement.src = 'https://30.img.avito.st/image/1/1._DJTzra2UNtFburbJ_2oIZJtUNHtzVFh521S.o30giUQW-wMG3ar610UkHqINEtoYfC7c5jPPw6qYZxQ';
    imgElement.alt = 'Картинка ' + imageCounter;
    imgElement.className = 'draggable-image';
 
    imgElement.style.position = 'absolute';
   
    imgElement.style.maxHeight = '20px';
    imgElement.style.maxWidth = '20px';
    imgElement.style.height = 'auto';
    imgElement.style.width = 'auto';
    imgElement.style.display= 'block';
    
    var uniqueId = 'image' + imageCounter;
    imgElement.id = uniqueId;
 
    canvasDiv.appendChild(imgElement);
 
    images = document.querySelectorAll('.draggable-image');
 
    imgElement.dataset.pointX = 0;
    imgElement.dataset.pointY = 0;
 
    imageCounter++;
}
</script>
</body>
</html>
Рисунок и размеры свои задайте
setTransformCamera и цикл в строках 80-82, что бы изображение камеры не изменялось при изменении масштаба.
2
0 / 0 / 0
Регистрация: 23.09.2019
Сообщений: 2
08.04.2024, 10:13  [ТС]
Спасибо большое!
Подскажите, как добавить перемещение по div как в гугл мапс, когда div после зума больше окна браузера? Для большего удобства перемещения без скроллов.
Я так понимаю, для этого можно сделать div движущимся и при сдвиге обновлять координаты дочерних картинок? Или есть способ проще?
0
 Аватар для voraa
1289 / 1262 / 187
Регистрация: 21.01.2024
Сообщений: 5,804
08.04.2024, 11:59
Мне кажется, что проще будет рисунок задавать как фоновый (background-image) и тогда можно будет менять его размеры и позицию через background-size и background-position.
Ну и да. При сдвиге фона надо будет двигать все наложенные рисунки.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.04.2024, 11:59
Помогаю со студенческими работами здесь

интерактивная карта
Здравствуйте, мне нужно создать пользовательскую карту на сайте. Т.е мое изображение карты, а на нем уже метки. Подскажите есть ли какой-то...

Интерактивная карта ТЦ
Товарищи! Может кто сталкивался с такой проблемой в Битриксе. Версия старенькая 15.0.6. Хотя бы подскажите в какую сторону копать... ...

Интерактивная карта
Подскажите пожалуйста!:umnik: Возможно ли создание интерактивных карт в Borland C++ Builder 2009 и как это сделать?:wall:

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

Интерактивная карта
Есть картинка/карта страны, на которой нужно изобразить фотографии в разных частях странны, при наведении мышки на фото, всплывает доп....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru