大屏编辑器快捷键功能

<template>
  <div class="shortcut-key">
    <el-popover width="235" placement="top" trigger="click" effect="dark" popper-class="shortcut-editor-popover">
      <template #reference>
        <!-- <img class="icon" src="@/assets/img/bigScreen/shortcut.png" alt="" /> -->
        <span>快捷键</span>
      </template>
      <div class="shortcut-wp">
        <div class="title">快捷键</div>
        <div v-for="item in shortcutList" :key="item.title" class="shortcut-item">
          <div class="shortcut-title">{{ item.title }}</div>
          <div class="shortcut-value">
            <template v-for="(i, o) in item.value" :key="i">
              <div class="value">
                <template v-if="item.iconText && item.isIcon === i">
                  <img :src="handleUrl(item.isIcon)" alt="" />
                  <span class="icon-text">{{ item.iconText }}</span>
                </template>
                <img v-else-if="item.isIcon === i" class="icon" :src="handleUrl(i)" alt="" />
                <span v-else>{{ i }}</span>
              </div>
              <span class="add">{{ o === item.value.length - 1 ? '' : '+' }}</span>
            </template>
          </div>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue'

import { usePanel } from 'dtp-widgets'

const shortcutList = [
  { title: '剪贴', value: ['Ctrl', 'X'] },
  { title: '复制', value: ['Ctrl', 'C'] },
  { title: '粘贴', value: ['Ctrl', 'V'] },
  { title: '成组', value: ['Ctrl', 'G'] },
  { title: '上移一层', value: ['Ctrl', ']'] },
  { title: '下移一层', value: ['Ctrl', '['] },
  { title: '加选', value: ['Ctrl', 'danji'], isIcon: 'danji' },
  { title: '多选(图层列表)', value: ['Shift', 'danji'], isIcon: 'danji' },
  { title: '拖动画布', value: ['Ctrl', 'zhongjian'], isIcon: 'zhongjian' },
  { title: '缩放画布', value: ['Ctrl', 'zhongjian'], isIcon: 'zhongjian', iconText: '滚轮' },
  { title: '置顶', value: ['Ctrl', 'Shift', ']'] },
  { title: '置底', value: ['Ctrl', 'Shift', '['] },
  { title: '取消成组', value: ['Ctrl', 'Shift', 'G'] },
  { title: '删除', value: ['Delete / Backspace'] },
]
// 处理图片地址
const handleUrl = (url) => {
  return new URL(`../../../assets/img/bigScreen/shortcut-key/${url}.png`, import.meta.url).href
}
const { current, layerUp, layerDn, deleteFn, copy, paste, layerTop, layerBottom, setGroup, setUnGroup } = usePanel() // hooks封装的变量及方法 (只用作参考,需根据实际情况来自行封装,本文旨在键盘逻辑介绍)
const ctrlDown = ref(false)
const shiftDown = ref(false)
// 键盘按住事件
const addShortcuts = (ev) => {
  const target = ev.target
  if (['input', 'textarea'].includes(target.tagName.toLowerCase())) return // 此处是判断是否在输入框内,避免影响复制输入框内的复制等操作
  const key = ev.key.toLowerCase()
  let data = current.value || {} // current.value 为当前选中的组件
  // 按住ctrl
  if (ev.ctrlKey) {
    ev.preventDefault()
    ctrlDown.value = true
    // 按住ctrl未按shift
    if (!ev.shiftKey) {
      switch (key) {
        // 创建分组
        case 'g':
          setGroup()
          break
        // 剪贴
        case 'x':
          copy(true)
          break
        // 复制
        case 'c':
          copy()
          break
        // 粘贴
        case 'v':
          paste()
          break
        // 上移
        case ']':
          if (data && JSON.stringify(data) !== '{}') layerUp(data)
          break
        // 下移
        case '[':
          if (data && JSON.stringify(data) !== '{}') layerDn(data)
          break
      }
      // 按住ctrl并按住shift
    } else {
      switch (key) {
        // 解除分组
        case 'g':
          setUnGroup()
          break
        // 置顶
        case '}':
          if (data && JSON.stringify(data) !== '{}') layerTop(data)
          break
        // 置底
        case '{':
          if (data && JSON.stringify(data) !== '{}') layerBottom(data)
          break
      }
    }
  } else {
    if (key === 'delete' || key === 'backspace') {
      deleteFn()
    }
  }
  // 按住shift
  if (ev.shiftKey) {
    shiftDown.value = true
  }
}
// 放开ctrl
const releaseCtrl = (ev) => {
  const key = ev.key.toLowerCase()
  if (key === 'control') {
    ctrlDown.value = false
  }
}
// 放开shift
const releaseShift = (ev) => {
  const key = ev.key.toLowerCase()
  if (key === 'shift') {
    shiftDown.value = false
  }
}
onMounted(() => {
  document.addEventListener('keydown', addShortcuts, false)
  document.addEventListener('keyup', releaseCtrl, false)
  document.addEventListener('keyup', releaseShift, false)
})

onUnmounted(() => {
  document.removeEventListener('keydown', addShortcuts, false)
  document.removeEventListener('keyup', releaseCtrl, false)
  document.removeEventListener('keyup', releaseShift, false)
})
</script>

<style lang="scss" scoped>
.shortcut-key {
  width: 30px;
  text-align: center;
  position: absolute;
  left: 5px;
  bottom: 0;
  z-index: 999;
  .icon {
    cursor: pointer;
    width: 30px;
    // height: 18px;
  }
}
.shortcut-wp {
  position: relative;
  font-size: 12px;
  // background: #fff;
  // box-shadow: #fff;
  user-select: none;
  .title {
    font-size: 14px;
    color: #fff;
  }
  .shortcut-item {
    display: flex;
    margin: 5px 0;
    justify-content: space-between;
    align-items: center;
    .shortcut-title {
      padding-right: 15px;
      color: #a9a9a9;
    }

    .shortcut-value {
      display: flex;
      justify-content: right;
      padding: 4px 6px;
      font-weight: 700;
      // color: #fff;
      // background: #fff;
      border-radius: 2px;
      line-height: 24px;
      .value {
        height: 24px;
        background-color: #474747;
        margin: 0 6px;
        line-height: 24px;
        text-align: center;
        min-width: 24px;
        border-radius: 2px;
        display: flex;
        align-items: center;
        span {
          display: block;
          padding: 0 6px;
          color: #fff;
        }
        .icon-text {
          padding-right: 6px;
          padding-left: 0;
        }
      }
      .add {
        color: #a9a9a9;
      }
    }
  }
}
</style>
<style lang="scss">
.shortcut-editor-popover {
  background-color: #303030 !important;
  border: 1px solid #515357 !important;
  --el-popover-padding: 16px;
  .el-popper__arrow::before {
    background-color: #303030 !important;
    border: 1px solid #515357 !important;
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值