【PPTist】批注、选择窗格

前言:本篇文章研究批注和选择窗格两个小功能

一、批注

批注功能就是介个小图标

点击可以为当前页的幻灯片添加批注,还能删除之前的批注

如果我们增加了登录功能,还可以在批注上显示当前的用户名和头像,不过现在是写死的。

左侧幻灯片缩略图的左上角会显示当前幻灯片的批注的数量

首先我们来换一个个性的头像吧!

看下头像现在是一个icon

这段HTML在 src/views/Editor/NotesPanel.vue 文件中

首先创建一个文件目录 src/assets/images/avatars ,然后把中意的头像放进去,然后把模版中的icon改成我们的头像就好啦

不过我们也可以写的更智能一点,通过用户名动态渲染

typescript 复制代码
<img :src="getImageUrl(note.user)">
const getImageUrl = (user: string) => {
  return new URL(`../../assets/images/avatars/${user}.png`, import.meta.url).href
}

图片的名字和用户名保持一致就可以了

最爱的小乔~~~

这里的批注就是一个列表,添加批注就向批注列表中增加一个数据,然后还需要通过 slidesStore.updateSlide() 方法,更新当前幻灯片的批注

typescript 复制代码
const createNote = () => {
  if (!content.value) {
    if (textAreaRef.value) textAreaRef.value.focus()
    return
  }

  const newNote: Note = {
    id: nanoid(),
    content: content.value,
    time: new Date().getTime(),
    user: '小乔',
  }
  if (handleElementId.value) newNote.elId = handleElementId.value

  const newNotes = [
    ...notes.value,
    newNote,
  ]
  slidesStore.updateSlide({ notes: newNotes })

  content.value = ''
}

还有一个可以给别人的批注回复的功能

回复是 note.replie 属性,添加回复也跟上面的添加批注的逻辑差不多,没啥复杂的

有一点,这里没有调用 addHistorySnapshot() ,说明批注相关的操作是不能回退的

二、选择窗格

可以控制幻灯片的几个部分的显示和隐藏。

我们在全局搜索 "选择窗格" 就可以发现,点击这个按钮的时候,会触发的方法是
src/views/Editor/CanvasTool/index.vue

typescript 复制代码
// 打开选择面板
const toggleSelectPanel = () => {
  mainStore.setSelectPanelState(!showSelectPanel.value)
}

修改公共的数据中的属性 showSelectPanel
src/store/main.ts

typescript 复制代码
setSelectPanelState(show: boolean) {
  this.showSelectPanel = show
},

然后全局搜索这个属性,会在下面这个模版中发现它的踪迹
src/views/Editor/index.vue

typescript 复制代码
<SelectPanel v-if="showSelectPanel" />

组件是 src/views/Editor/SelectPanel.vue

组件的根元素是 MoveablePanel 组件,通过它的名字我们也可以看出,这个组件是可移动的。而且既然这个自定义组件的标签中能放东西,肯定是使用插槽实现的。src/components/MoveablePanel.vue

然后我们还是看选择窗格组件,里面的功能

1、全部显示全部隐藏

是在 src/hooks/useHideElement.ts 中的 showAllElementshideAllElements

typescript 复制代码
const showAllElements = () => {
  const currentSlideElIdList = currentSlide.value.elements.map(item => item.id)
  const needHiddenElementIdList = hiddenElementIdList.value.filter(item => !currentSlideElIdList.includes(item))
  mainStore.setHiddenElementIdList(needHiddenElementIdList)
}
const hideAllElements = () => {
  const currentSlideElIdList = currentSlide.value.elements.map(item => item.id)
  mainStore.setHiddenElementIdList([...hiddenElementIdList.value, ...currentSlideElIdList])
  if (activeElementIdList.value.length) mainStore.setActiveElementIdList([])
}

隐藏元素主要是通过修改 hiddenElementIdList

src/views/Editor/Canvas/index.vue 中,元素会通过 hiddenElementIdList 判断是否展示

typescript 复制代码
v-show="!hiddenElementIdList.includes(element.id)"
2、点击菜单项

点击下面的列表中的菜单项的时候,幻灯片中的对应的元素会被选中

执行的是这个方法,好像之前见过来着,这是个公共的方法
src/hooks/useSelectElement.ts

typescript 复制代码
// 将指定元素设置为被选择状态
const selectElement = (id: string) => {
  if (handleElementId.value === id) return
  if (hiddenElementIdList.value.includes(id)) return
  
  const lockedElements = currentSlide.value.elements.filter(el => el.lock)
  if (lockedElements.some(el => el.id === id)) return

  mainStore.setActiveElementIdList([id])
}

点击菜单项后面的小眼睛切换元素的显示的时候,还是修改 hiddenElementIdList
src/hooks/useHideElement.ts

typescript 复制代码
const toggleHideElement = (id: string) => {
  if (hiddenElementIdList.value.includes(id)) {
    mainStore.setHiddenElementIdList(hiddenElementIdList.value.filter(item => item !== id))
  }
  else mainStore.setHiddenElementIdList([...hiddenElementIdList.value, id])

  if (activeElementIdList.value.includes(id)) mainStore.setActiveElementIdList([])
}

所以元素的显示隐藏相关的功能都是通过修改 hiddenElementIdList 数组实现的。

如果是组合的话,会显示成二级菜单

另外选中某个元素的时候,右侧的样式也会改变成选中元素的样式

右侧 Tab 栏组件是 src/views/Editor/Toolbar/index.vue

typescript 复制代码
const { activeElementIdList, handleElement, toolbarState } = storeToRefs(mainStore)

我们看一下 handleElement,会显示填充色、宽高、位置、类型等属性

修改的时候就修改这个目标元素的属性即可。
handleElementsrc/store/main.ts 中的一个计算属性,实时计算

typescript 复制代码
// 获取当前操作的元素
handleElement(state) {
  const slidesStore = useSlidesStore()
  const currentSlide = slidesStore.currentSlide
  if (!currentSlide || !currentSlide.elements) return null
  return currentSlide.elements.find(element => state.handleElementId === element.id) || null
},
相关推荐
小毛驴8505 分钟前
创建 Vue 项目的 4 种主流方式
前端·javascript·vue.js
使二颗心免于哀伤29 分钟前
《设计模式之禅》笔记摘录 - 10.装饰模式
笔记·设计模式
誰能久伴不乏34 分钟前
Linux如何执行系统调用及高效执行系统调用:深入浅出的解析
java·服务器·前端
悠哉悠哉愿意44 分钟前
【电赛学习笔记】MaxiCAM 项目实践——与单片机的串口通信
笔记·python·单片机·嵌入式硬件·学习·视觉检测
快乐肚皮1 小时前
ZooKeeper学习专栏(五):Java客户端开发(原生API)详解
学习·zookeeper·java-zookeeper
慕y2741 小时前
Java学习第七十二部分——Zookeeper
java·学习·java-zookeeper
岩中竹2 小时前
广东省省考备考——常识:科技常识(持续更新)
笔记
涔溪2 小时前
响应式前端设计:CSS 自适应布局与字体大小的最佳实践
前端·css
今禾2 小时前
前端开发中的Mock技术:深入理解vite-plugin-mock
前端·react.js·vite
你这个年龄怎么睡得着的2 小时前
Babel AST 魔法:Vite 插件如何让你的 try...catch 不再“裸奔”?
前端·javascript·vite