【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
},
相关推荐
SuperW9 分钟前
linux课程学习二——缓存
学习
庸俗今天不摸鱼11 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下18 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox28 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞31 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行31 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581032 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周35 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
lulinhao40 分钟前
HCIA/HCIP基础知识笔记汇总
网络·笔记
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js