В последнее время в проекте нужно сделать функцию, которая может выбирать места и бронировать билеты на мобильном терминале. Искал в интернете и не нашел готовой библиотеки для решения нужд, поэтому написал черновой вариант сам.
нужно
- Распределение сидений в передней части салона
- Перетащите, чтобы увеличить или уменьшить масштаб. Нажмите, чтобы выбрать место.
стек технологий
- svg
- hammerjs
визуализация
Подробные эффекты можно перейти кdemoТогда попробуйте, для этого рекомендуется использовать мобильный терминал.
svg
SVG карты рассадки экспортируется после отрисовки пользовательского интерфейса, а весь тег SVG и содержимое внутри возвращаются через внутренний интерфейс. Внешний интерфейс просто делает запрос на получение SVG и вставляет его. После вставки заказанная позиция сиденья должна быть затемнена и не может быть выбрана.
hammerjs
hammerjsЭто библиотека жестов, которая обеспечивает различные события жестов, такие как касание, двойное касание, нажатие, панорамирование, пролистывание, сжатие и вращение, а также предоставляет множество пользовательских конфигураций, которые позволяют вам выполнять различные продукты (нао) (дон) (да) ) как (кай) требования.
Применение
let hammertime = new Hammer(myElement, myOptions);
hammertime.on('pan', function(ev) {
console.log(ev)
})
HTML-структура
Box svg-box для щипка (масштабирования)
svg для смещения
<div class="ticket-map">
<div class=svg-box>
<svg>.....</svg>
</div>
</div>
инициализация
Установите переменную для записи изменения свойства после операции жеста
// 记录位移变量
let transform = {
svgScale: 0.5, // svg 默认缩放
scale: 1, // svg-box 缩放
maxScale: 7, // svg-box 最大缩放
minScale: 1, // svg-box 最小缩放
translateX: 0, // svg X轴偏移
translateY: 0, // svg Y轴偏移
minX: 0, // svg 最小X轴偏移
maxX: 0, // svg 最大X轴偏移
minY: 0, // svg 最小Y轴偏移
maxY: 0 // svg 最大Y轴偏移
}
Поскольку SVG, предоставленный пользовательским интерфейсом, немного больше, чем 1000*715, для адаптации к экрану масштабируется svgScale: 0,5.
После получения SVG вам нужно центрировать и рассчитать границу перетаскивания (minX/Y maxX/Y)
let svgTarget = document.querySelector('svg')
let svgBox = document.querySelector('.svg-box')
transform.translateX = Math.round((svgBox.clientWidth - svgTarget.clientWidth) / 2) // 垂直居中时的X偏移
transform.translateY = Math.round((svgBox.clientHeight - svgTarget.clientHeight) / 2) // 垂直居中时的Y偏移
transform.minX = transform.translateX - svgBox.clientWidth / 4
transform.maxX = transform.translateX + svgBox.clientWidth / 4
transform.minY = transform.translateY - svgBox.clientHeight / 2.5
transform.maxY = transform.translateY + svgBox.clientHeight / 2.5
svgTarget.style.transform = `translate(${transform.translateX}px, ${transform.translateY}px) scale(${transform.svgScale})`
Возьмите 1/4 ширины svg-box и 1/2,5 высоты в качестве предела смещения по осям X и Y для svg, чтобы предотвратить перетаскивание svg за пределы экрана. Оценка может быть скорректирована на основе фактического SVG.
Конфигурация жестов
// 初始化 hammer对象
var svgHam = new Hammer(svgBox)
svgHam.get('pinch').set({ enable: true }) // 返回pinch识别器 设置 可捏放 (放大缩小手势) 默认不监听
svgHam.get('pan').set({ direction: Hammer.DIRECTION_ALL }) // 返回pan识别器 设置拖动方向为 所有方向
Слушайте svg-box, чтобы событие не могло быть запущено, если палец щелкнет после перемещения svg
щипковое событие
svgHam.on('pinchstart pinchmove', (e) => {
let { scale, maxScale, minScale } = transform
scale *= e.scale
scale = scale >= maxScale ? maxScale : scale
scale = scale <= minScale ? minScale : scale
transform.scale = scale
svgBox.style.transform = `scale(${scale})`
})
Установите maxScale, minScale, чтобы избежать бесконечных или бесконечно малых
· Обратите внимание, что здесь масштабируется окно, а не сам SVG, иначе весь SVG будет отклоняться после перетаскивания и масштабирования.
событие перетаскивания
function checkXY(x, y) {
let { minX, minY, maxX, maxY } = transform
x = x > maxX ? maxX : x
x = x < minX ? minX : x
y = y > maxY ? maxY : y
y = y < minY ? minY : y
return {
x,
y
}
}
svgHam.on('panstart panmove', (e) => {
let { scale, translateX, translateY, svgScale } = transform
let y = translateY + e.deltaY / scale
let x = translateX + e.deltaX / scale
let validXY = checkXY(x, y)
svgTarget.style.transform = `translate(${validXY.x}px, ${validXY.y}px) scale(${svgScale})`
})
svgHam.on('panend', (e) => {
let { scale, translateX, translateY} = transform
let y = translateY + e.deltaY / scale
let x = translateX + e.deltaX / scale
let validXY = checkXY(x, y)
transform.translateY = validXY.y
transform.translateX = validXY.x
})
Обновите значение смещения после окончания смещения, потому что значение смещения deltaY/deltaX события события, предоставленного молотком, представляет собой разницу между начальным положением щелчка пальцем и движением.
Смещение/масштаб может эффективно контролировать скорость перетаскивания после увеличения, иначе весь SVG убежит после увеличения и перетаскивания.
Выбор места
После выполнения вышеуказанных эффектов легко выбрать место, просто щелкнув событие напрямую.
document.querySelector('.svg-box').addEventListener('click', selectSeat)
// svg 点击事件 选座
function selectSeat (e) {
if (e.target.tagName !== 'circle') return false
e.target.style.fill = e.target.style.fill === 'red' ? '#ccc' : 'red' // 选中的座位变成红色
// do something...
}
полный код
напиши в конце
Он не идеален, но он также отвечает текущим потребностям, и я надеюсь, что он может вдохновить вас. Недостаточно мест, я также надеюсь, что великие боги могут дать указатели.