当前位置: 首页 > news >正文

【PPTist】插入形状、插入图片、插入图表

一、插入形状

插入形状有两种情况,一种是插入固定的形状,
在这里插入图片描述

一种是插入自定义的形状。
插入固定的形状时,跟上一篇文章 绘制文本框 是一样一样的,都是调用的 mainStore.setCreatingElement() 方法,只不多传的类型不一样。还有插入线条,也是类似的。

mainStore.setCreatingElement({type: 'shape',data: shape,
})

所以咱们那接下来主要看插入自定义形状时的代码执行流程

1、点击
<Popover trigger="click" v-model:value="shapeMenuVisible" style="height: 100%;" :offset="10"><template #content><PopoverMenuItem center @click="() => { drawCustomShape(); shapeMenuVisible = false }">自由绘制</PopoverMenuItem></template><IconDown class="arrow" />
</Popover>

src/views/Editor/CanvasTool/index.vue

// 绘制自定义任意多边形
const drawCustomShape = () => {mainStore.setCreatingCustomShapeState(true)shapePoolVisible.value = false
}

src/store/main.ts

setCreatingCustomShapeState(state: boolean) {this.creatingCustomShape = state
},

有了 creatingCustomShape,下面的组件就会显示

<ShapeCreateCanvasv-if="creatingCustomShape"@created="data => insertCustomShape(data)"
/>
2、mousedown

src/views/Editor/Canvas/ShapeCreateCanvas.vue
触发 created 方法

const addPoint = (e: MouseEvent) => {const { pageX, pageY } = getPoint(e)isMouseDown.value = trueif (closed.value) emit('created', getCreateData())else points.value.push([pageX, pageY])document.onmouseup = () => {isMouseDown.value = false}
}
3、created

src/views/Editor/Canvas/index.vue
插入任意多边形

// 插入自定义任意多边形
const insertCustomShape = (data: CreateCustomShapeData) => {const {start,end,path,viewBox,} = dataconst position = formatCreateSelection({ start, end })if (position) {const supplement: Partial<PPTShapeElement> = {}if (data.fill) supplement.fill = data.fillif (data.outline) supplement.outline = data.outline// 创建形状元素createShapeElement(position, { path, viewBox }, supplement)}// 清除 creatingCustomShapemainStore.setCreatingCustomShapeState(false)
}
4、mousemove

src/views/Editor/Canvas/ShapeCreateCanvas.vue
如果鼠标按下,添加 points,就会形成折线的效果。
可以看到只要起点和终点比较近就算闭合了,防止对不上

const updateMousePosition = (e: MouseEvent) => {// 如果鼠标按下,则添加点if (isMouseDown.value) {const { pageX, pageY } = getPoint(e, true)points.value.push([pageX, pageY])mousePosition.value = nullreturn}// 更新鼠标位置const { pageX, pageY } = getPoint(e)mousePosition.value = [pageX, pageY]// 判断是否闭合if (points.value.length >= 2) {const [firstPointX, firstPointY] = points.value[0]if (Math.abs(firstPointX - pageX) < 5 && Math.abs(firstPointY - pageY) < 5) {closed.value = true}else closed.value = false}else closed.value = false
}

根据鼠标位置 mousePosition 计算 path

const path = computed(() => {let d = ''for (let i = 0; i < points.value.length; i++) {const point = points.value[i]if (i === 0) d += `M ${point[0]} ${point[1]} `else d += `L ${point[0]} ${point[1]} `}if (points.value.length && mousePosition.value) {d += `L ${mousePosition.value[0]} ${mousePosition.value[1]}`}return d
})

模版中的 path 元素随之更新

<svg overflow="visible"><path:d="path" stroke="#d14424" :fill="closed ? 'rgba(226, 83, 77, 0.15)' : 'none'" stroke-width="2" ></path>
</svg>
5、取消绘制的按键绑定
const keydownListener = (e: KeyboardEvent) => {const key = e.key.toUpperCase()if (key === KEYS.ESC) close()if (key === KEYS.ENTER) create()
}
onMounted(() => {message.success('点击绘制任意形状,首尾闭合完成绘制,按 ESC 键或鼠标右键取消,按 ENTER 键提前完成', {duration: 0,})document.addEventListener('keydown', keydownListener)
})

以及鼠标右键也会取消绘制

@contextmenu.stop.prevent="close()"
const close = () => {mainStore.setCreatingCustomShapeState(false)
}

二、插入图片

src/views/Editor/CanvasTool/index.vue
插入图片也是一个自定义组件

<FileInput @change="files => insertImageElement(files)"><IconPicture class="handler-item" v-tooltip="'插入图片'" />
</FileInput>

这个组件里面实现上传功能的是 input 标签

<input class="input"type="file" name="upload" ref="inputRef" :accept="accept" @change="$event => handleChange($event)"
>

上传之后插入图片元素

const insertImageElement = (files: FileList) => {const imageFile = files[0]if (!imageFile) returngetImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))
}

src/utils/image.ts

获取图片宽高的方法,相比大家都挺熟悉的

/*** 获取图片的原始宽高* @param src 图片地址*/
export const getImageSize = (src: string): Promise<ImageSize> => {return new Promise(resolve => {const img = document.createElement('img')img.src = srcimg.style.opacity = '0'document.body.appendChild(img)img.onload = () => {const imgWidth = img.clientWidthconst imgHeight = img.clientHeightimg.onload = nullimg.onerror = nulldocument.body.removeChild(img)resolve({ width: imgWidth, height: imgHeight })}img.onerror = () => {img.onload = nullimg.onerror = null}})
}

获取图片宽高之后,创建图片元素,通过 lefttop 将图片水平垂直居中
src/hooks/useCreateElement.ts

/*** 创建图片元素* @param src 图片地址*/
const createImageElement = (src: string) => {getImageSize(src).then(({ width, height }) => {const scale = height / widthif (scale < viewportRatio.value && width > VIEWPORT_SIZE) {width = VIEWPORT_SIZEheight = width * scale}else if (height > VIEWPORT_SIZE * viewportRatio.value) {height = VIEWPORT_SIZE * viewportRatio.valuewidth = height / scale}createElement({type: 'image',id: nanoid(10),src,width,height,left: (VIEWPORT_SIZE - width) / 2,top: (VIEWPORT_SIZE * viewportRatio.value - height) / 2,fixedRatio: true,rotate: 0,})})
}

复习一下创建元素的方法,会把元素放到当前幻灯片的元素列表中

// 创建(插入)一个元素并将其设置为被选中元素
const createElement = (element: PPTElement, callback?: () => void) => {// 添加元素到元素列表slidesStore.addElement(element)// 设置被选中元素列表mainStore.setActiveElementIdList([element.id])if (creatingElement.value) mainStore.setCreatingElement(null)setTimeout(() => {// 设置编辑器区域为聚焦状态mainStore.setEditorareaFocus(true)}, 0)if (callback) callback()// 添加历史快照addHistorySnapshot()
}

三、插入图表

插入图表的方法,其实也差不多,就是往当前的幻灯片里添加一个图表对象。不过这里就不讲前面怎么添加元素了,讲讲后面怎么展示元素吧。先来看一下图表元素的数据:

const newElement: PPTChartElement = {type: 'chart',id: nanoid(10),chartType: CHART_TYPES[type],left: 300,top: 81.25,width: 400,height: 400,rotate: 0,themeColor: [theme.value.themeColor],gridColor: theme.value.fontColor,data: {labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],legends: ['系列1'],series: [[12, 19, 5, 2, 18],],},
}

是这个元素对元素列表进行循环的
src/views/Editor/Canvas/index.vue

<EditableElement v-for="(element, index) in elementList" :key="element.id":elementInfo="element":elementIndex="index + 1":isMultiSelect="activeElementIdList.length > 1":selectElement="selectElement":openLinkDialog="openLinkDialog"v-show="!hiddenElementIdList.includes(element.id)"
/>

src/views/Editor/Canvas/EditableElement.vue
这个组件中通过动态组件的方式控制显示哪个元素

<component:is="currentElementComponent":elementInfo="elementInfo":selectElement="selectElement":contextmenus="contextmenus"
></component>
const currentElementComponent = computed<unknown>(() => {const elementTypeMap = {[ElementTypes.IMAGE]: ImageElement,[ElementTypes.TEXT]: TextElement,[ElementTypes.SHAPE]: ShapeElement,[ElementTypes.LINE]: LineElement,[ElementTypes.CHART]: ChartElement,[ElementTypes.TABLE]: TableElement,[ElementTypes.LATEX]: LatexElement,[ElementTypes.VIDEO]: VideoElement,[ElementTypes.AUDIO]: AudioElement,}return elementTypeMap[props.elementInfo.type] || null
})

我们的目标就是 ChartElementsrc/views/components/element/ChartElement/index.vue
然后图表那一小块是这个:src/views/components/element/ChartElement/Chart.vue,图表是通过 chartist 库实现的

import { BarChart, LineChart, PieChart } from 'chartist'

相关文章:

【PPTist】插入形状、插入图片、插入图表

一、插入形状 插入形状有两种情况&#xff0c;一种是插入固定的形状&#xff0c; 一种是插入自定义的形状。 插入固定的形状时&#xff0c;跟上一篇文章 绘制文本框 是一样一样的&#xff0c;都是调用的 mainStore.setCreatingElement() 方法&#xff0c;只不多传的类型不一…...

三台Centos7.9中Docker部署Redis集群

Docker部署Redis集群 1. 安装 Docker 和 Docker Compose安装 Docker&#xff1a;安装 Docker Compose&#xff1a; 2. 配置 Redis 容器和网络3. 启动 Redis 容器4. 设置 Redis 集群4.1 集群创建异常处理 5. 验证和测试总结 如果 CentOS 服务器上还没有安装 Docker 和 Docker Co…...

Entity 的材质(棋盘、条纹、网格)

Entity 的材质 普通物体的材质 import { nextTick, onMounted, ref } from vue import * as Cesium from cesium // console.log(Cesium, Cesium)const viewer ref<any>(null)onMounted(() > { ... })let material Cesium.Color.YELLOW.withAlpha(0.5)Cesium.Colo…...

MACPA:fMRI连接性分析的新工具

摘要 不同脑区的共同激活为它们之间的功能交互或连接提供了一个有价值的衡量指标。元分析连接模型(MACM)是一种经过充分验证的研究某一特定区域共激活模式的方法&#xff0c;该方法对基于任务的功能磁共振成像(task-fMRI)数据进行种子点(seed-based)元分析。虽然MACM是一种强大…...

JavaScript-一份你的前端入门说明书(计算机专业)

一.简介 1.起源 JavaScript 起源于 1995 年,当时它主要是为了满足网页交互的需求而被创建。它最初的设计目的是为了让网页开发者能够在网页中添加一些简单的交互效果和动态内容。在那个时期,网页大多是静态的,而 JavaScript 的出现为网页带来了新的活力。Netscape 公司的 B…...

STM32供电参考设计

STM32供电参考设计 ​ 在图中有VDD&#xff0c;VSS和VDDA&#xff0c;VSSA两种类型的供电引脚&#xff0c;其数据手册解释如下&#xff1a; ​ 令我不解的是&#xff1a;VDDA和VSSA必须分别连接到VDD和VSS&#xff0c;这是什么意思&#xff1f;有大佬能够解答一下吗&#xff1f…...

python+fpdf:创建pdf并实现表格数据写入

目录 创建pdf文件对象 新增页 添加自定义字体 设置字体 设置文字颜色和背景色 插入内容 换行 插入图片 保存pdf 完整代码 安装&#xff1a;pip install fpdf 创建pdf文件对象 from fpdf import FPDF, Alignpdf FPDF() # 创建pdf文件对象 获取边距 print(pdf.l_…...

亚远景-ASPICE评估:汽车软件项目的过程能力评价

ASPICE&#xff08;Automotive SPICE&#xff09;的评估对象主要是汽车软件研发过程。 这个评估过程不仅仅关注最终的软件产品&#xff0c;而是深入到软件开发的全生命周期中&#xff0c;从需求分析、设计、编码、测试到发布和维护等各个环节。 具体来说&#xff0c;ASPICE评…...

电脑提示directx错误导致玩不了游戏怎么办?dx出错的解决方法

想必大家都有过这样的崩溃瞬间&#xff1a;满心欢喜打开心仪的游戏&#xff0c;准备在虚拟世界里大杀四方或者畅游冒险&#xff0c;结果屏幕上突然弹出个 DirectX 错误的提示框&#xff0c;紧接着游戏闪退&#xff0c;一切美好戛然而止。DirectX 作为 Windows 系统下游戏运行的…...

【13】制作镜像以及重启实例

制作镜像 k8s集群 有两个镜像需要制作&#xff0c;一个是master节点&#xff0c;一个是node节点。 在master节点上成功部署了k8s的控制平面&#xff0c;在node节点上部署了worker节点的配置&#xff0c;不知道打包镜像重启之后集群的状态是什么样的。 确认集群在运行&#…...

electron 启动警告

1. 问题 当启动 electron 时&#xff0c;控制台警告 Electron Security Warning (Insecure Content-Security-Policy) This renderer process has either no Content Security 2. 解决方法 在主进程文件 main.js 中添加如下内容 process.env["ELECTRON_DISABLE_SECURI…...

wow-agent 学习笔记

wow-agent-课程详情 | Datawhale 前两课比较基础&#xff0c;无笔记 第三课 阅卷智能体这一块&#xff0c;曾经做过一点和AI助教相关的内容&#xff0c;也是用了一个prompt去进行CoT&#xff0c;但是风格和课程中的不太相同&#xff0c;在下面附上我的prompt 你是一名资深教…...

使用Cilium/eBPF实现大规模云原生网络和安全

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 抽象 1 Trip.com 云基础设施 1.1 分层架构 1.2 更多细节 2 纤毛在 Trip.com 2.1 推出时间表 2.2 自定义 2.3 优化和调整 2.3.1 解耦安装 2.3.2 避免重试/重启风暴 2.3.3 稳定性优先 2…...

“深入浅出”系列之C++:(4)回调函数

在写项目的时候遇见一个问题&#xff0c;现在的需求是主项目需要拿到子项目的结果来进行显示&#xff0c;那么如何集成呢&#xff0c;子项目里面有一个MainWindow类&#xff0c;类里 回调函数是一种通过函数指针将函数作为参数传递给另一个函数的编程技术。这种机制允许程序在特…...

Mysql--运维篇--主从复制和集群(主从复制I/O线程,SQL线程,二进制日志,中继日志,集群NDB)

一、主从复制 MySQL的主从复制&#xff08;Master-Slave Replication&#xff09;是一种数据冗余和高可用性的解决方案&#xff0c;它通过将一个或多个从服务器&#xff08;Slave&#xff09;与主服务器&#xff08;Master&#xff09;同步来实现。主从复制的基本原理是&#…...

设计模式 行为型 状态模式(State Pattern)与 常见技术框架应用 解析

状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为&#xff0c;使得对象看起来好像修改了它的类。这种设计模式的核心思想是将对象的状态和行为封装成不同的状态类&#xff0c;通过状态对象的行为改变来避免…...

计算机网络 (38)TCP的拥塞控制

前言 TCP拥塞控制是传输控制协议&#xff08;Transmission Control Protocol&#xff0c;TCP&#xff09;避免网络拥塞的算法&#xff0c;是互联网上主要的一个拥塞控制措施。 一、目的 TCP拥塞控制的主要目的是防止过多的数据注入到网络中&#xff0c;使网络能够承受现有的网络…...

鸿蒙面试 2025-01-09

鸿蒙分布式理念&#xff1f;&#xff08;个人认为理解就好&#xff09; 鸿蒙操作系统的分布式理念主要体现在其独特的“流转”能力和相关的分布式操作上。在鸿蒙系统中&#xff0c;“流转”是指涉多端的分布式操作&#xff0c;它打破了设备之间的界限&#xff0c;实现了多设备…...

【关于for循环的几种写法】

关于for循环的几种写法 在 C 中&#xff0c;for(int i 0; i < n; i) 是一种常见的循环写法&#xff0c;用于遍历从 0 到 n-1 的索引。如果你希望简化这种写法&#xff0c;可以使用以下几种方法&#xff1a; 1. 使用范围 for 循环 如果你需要遍历一个容器&#xff08;如数…...

Apache和PHP:构建动态网站的黄金组合

在当今的互联网世界&#xff0c;网站已经成为了企业、个人和机构展示自己、与用户互动的重要平台。而在这些动态网站的背后&#xff0c;Apache和PHP无疑是最受开发者青睐的技术组合之一。这一组合提供了高效、灵活且可扩展的解决方案&#xff0c;帮助您快速搭建出强大的网站&am…...

Pixel Couplet Gen步骤详解:从输入愿望到生成可分享像素春联的完整链路

Pixel Couplet Gen步骤详解&#xff1a;从输入愿望到生成可分享像素春联的完整链路 1. 项目概览 Pixel Couplet Gen是一款融合传统春节文化与现代像素艺术风格的AI春联生成工具。通过ModelScope大模型驱动&#xff0c;它将用户的文字愿望转化为具有8-bit游戏视觉特色的数字春…...

mbedBug:面向mbed OS的轻量级嵌入式调试纳米框架

1. mbedBug&#xff1a;面向mbed OS的轻量级嵌入式调试纳米框架1.1 设计定位与工程价值mbedBug并非通用型调试器或完整测试框架&#xff0c;而是一个专为资源受限嵌入式环境裁剪的调试纳米框架&#xff08;Debug Nanoframework&#xff09;。其核心设计哲学是“最小侵入、最大可…...

如何通过智慧树自动化学习助手解决网课学习效率问题

如何通过智慧树自动化学习助手解决网课学习效率问题 【免费下载链接】zhihuishu 智慧树刷课插件&#xff0c;自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 副标题&#xff1a;面向时间紧张学习者的智能网课辅助工具 一、价…...

Android开发者的USB摄像头避坑指南:从设备枚举到SurfaceView预览的完整流程

Android开发者实战&#xff1a;USB摄像头集成全流程与疑难解析 去年接手一个医疗设备项目时&#xff0c;我需要在Android平板上接入工业级USB摄像头。本以为三天能搞定&#xff0c;结果光是解决画面拉伸问题就耗了一周。这份踩坑经验总结&#xff0c;将带你系统掌握从设备枚举到…...

别再只跑Demo了!手把手教你用TensorFlow训练自己的谷物分类模型(11类数据集)

从零构建高精度谷物分类模型&#xff1a;TensorFlow实战指南 当你第一次接触深度学习时&#xff0c;可能已经运行过MNIST手写数字识别或CIFAR-10这样的标准Demo。但真正要解决实际问题时&#xff0c;这些玩具数据集远远不够。本文将带你用TensorFlow处理一个真实的11类谷物图像…...

杰理之关机DAC未进入高阻【篇】

memset(JL_ADDA, 0x0, sizeof(JL_ADDA_TypeDef)); SFR(JL_ADDA->DAA_CON2, 15, 1, 1); SFR(JL_ADDA->DAA_CON2, 5, 1, 1);...

OpenClaw故障排查大全:百川2-13B接口连接失败解决方案

OpenClaw故障排查大全&#xff1a;百川2-13B接口连接失败解决方案 1. 问题背景与排查思路 上周我在本地部署百川2-13B量化版模型时&#xff0c;遭遇了OpenClaw对接失败的问题。这个13B参数的对话模型在消费级GPU上运行良好&#xff0c;但OpenClaw始终无法建立稳定连接。经过三…...

头皮上也长痘痘,一梳头就碰到好痛怎么办?

很多人都有过头皮长痘的困扰&#xff0c;一梳头碰到就痛&#xff0c;别提多难受了。其实&#xff0c;头皮长痘和我们的健康息息相关&#xff0c;下面就来详细说说其中的原因和解决办法。痘痘成因大揭秘清洁不到位头皮和脸部皮肤一样&#xff0c;会分泌油脂。如果平时洗头不勤&a…...

第五章作业

233817310313 文章目录图1&#xff1a;单位数码管显示7图2&#xff1a;单位数码管轮播0-9图3&#xff1a;6位数码管显示9图1&#xff1a;单位数码管显示7 #include <reg52.h>#define uchar unsigned char #define uint unsigned int// 定义锁存器控制引脚 sbit LE P2^7;…...

Goldfish4Tech空气泵驱动库:嵌入式直流泵安全控制方案

1. Goldfish4Tech空气泵驱动库技术解析1.1 库定位与工程价值Goldfish4TechAirPump 是一款面向嵌入式平台的轻量级空气泵控制库&#xff0c;专为金鱼科技&#xff08;Goldfish4Tech&#xff09;系列微型直流空气泵设计。该库并非通用型电机驱动框架&#xff0c;而是针对特定硬件…...