Аналогично функции выбора билетов (svg)

задняя часть товар

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

нужно

  • Распределение сидений в передней части салона
  • Перетащите, чтобы увеличить или уменьшить масштаб. Нажмите, чтобы выбрать место.

стек технологий

визуализация

捏放

拖动

Подробные эффекты можно перейти к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...
}

полный код


напиши в конце

Он не идеален, но он также отвечает текущим потребностям, и я надеюсь, что он может вдохновить вас. Недостаточно мест, я также надеюсь, что великие боги могут дать указатели.