docs: 补充代码注释
This commit is contained in:
parent
4b25579b45
commit
1b16514984
|
@ -26,11 +26,6 @@ import { ContextmenuItem, Axis } from './types'
|
|||
|
||||
import MenuContent from './MenuContent.vue'
|
||||
|
||||
const MENU_WIDTH = 170
|
||||
const MENU_HEIGHT = 30
|
||||
const DIVIDER_HEIGHT = 11
|
||||
const PADDING = 5
|
||||
|
||||
export default defineComponent({
|
||||
name: 'contextmenu',
|
||||
components: {
|
||||
|
@ -56,6 +51,11 @@ export default defineComponent({
|
|||
},
|
||||
setup(props) {
|
||||
const style = computed(() => {
|
||||
const MENU_WIDTH = 170
|
||||
const MENU_HEIGHT = 30
|
||||
const DIVIDER_HEIGHT = 11
|
||||
const PADDING = 5
|
||||
|
||||
const { x, y } = props.axis
|
||||
const menuCount = props.menus.filter(menu => !(menu.divider || menu.hide)).length
|
||||
const dividerCount = props.menus.filter(menu => menu.divider).length
|
||||
|
|
23
src/main.ts
23
src/main.ts
|
@ -10,16 +10,19 @@ import '@/assets/styles/antd.scss'
|
|||
import '@/assets/styles/font.scss'
|
||||
import 'animate.css'
|
||||
|
||||
// 自定义插件
|
||||
import Contextmenu from './plugins/contextmenu'
|
||||
import ClickOutside from './plugins/clickOutside'
|
||||
import IconPark from './plugins/iconPark'
|
||||
|
||||
// 自定义组件
|
||||
import FileInput from '@/components/FileInput.vue'
|
||||
import SvgWrapper from '@/components/SvgWrapper.vue'
|
||||
import CheckboxButton from '@/components/CheckboxButton.vue'
|
||||
import CheckboxButtonGroup from '@/components/CheckboxButtonGroup.vue'
|
||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||
|
||||
// antd 组件
|
||||
import {
|
||||
InputNumber,
|
||||
Divider,
|
||||
|
@ -40,6 +43,16 @@ import {
|
|||
|
||||
const app = createApp(App)
|
||||
|
||||
app.directive('contextmenu', Contextmenu)
|
||||
app.directive('click-outside', ClickOutside)
|
||||
app.use(IconPark)
|
||||
|
||||
app.component('FileInput', FileInput)
|
||||
app.component('SvgWrapper', SvgWrapper)
|
||||
app.component('CheckboxButton', CheckboxButton)
|
||||
app.component('CheckboxButtonGroup', CheckboxButtonGroup)
|
||||
app.component('ColorPicker', ColorPicker)
|
||||
|
||||
app.component('InputNumber', InputNumber)
|
||||
app.component('Divider', Divider)
|
||||
app.component('Button', Button)
|
||||
|
@ -63,15 +76,5 @@ app.component('MenuItem', Menu.Item)
|
|||
app.component('Checkbox', Checkbox)
|
||||
app.component('Drawer', Drawer)
|
||||
|
||||
app.directive('contextmenu', Contextmenu)
|
||||
app.directive('click-outside', ClickOutside)
|
||||
app.use(IconPark)
|
||||
|
||||
app.component('FileInput', FileInput)
|
||||
app.component('SvgWrapper', SvgWrapper)
|
||||
app.component('CheckboxButton', CheckboxButton)
|
||||
app.component('CheckboxButtonGroup', CheckboxButtonGroup)
|
||||
app.component('ColorPicker', ColorPicker)
|
||||
|
||||
app.use(store, key)
|
||||
app.mount('#app')
|
||||
|
|
|
@ -12,6 +12,7 @@ const contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: Direct
|
|||
|
||||
let container: HTMLDivElement | null = null
|
||||
|
||||
// 移除右键菜单并取消相关的事件监听
|
||||
const removeContextmenu = () => {
|
||||
if (container) {
|
||||
document.body.removeChild(container)
|
||||
|
@ -22,6 +23,7 @@ const contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: Direct
|
|||
window.removeEventListener('resize', removeContextmenu)
|
||||
}
|
||||
|
||||
// 创建自定义菜单
|
||||
const options = {
|
||||
axis: { x: event.x, y: event.y },
|
||||
el,
|
||||
|
@ -33,8 +35,10 @@ const contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: Direct
|
|||
render(vm, container)
|
||||
document.body.appendChild(container)
|
||||
|
||||
// 为目标节点添加菜单激活状态的className
|
||||
el.classList.add('contextmenu-active')
|
||||
|
||||
// 页面变化时移除菜单
|
||||
document.body.addEventListener('scroll', removeContextmenu)
|
||||
window.addEventListener('resize', removeContextmenu)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import Clipboard from 'clipboard'
|
||||
|
||||
// 复制文本到剪贴板
|
||||
/**
|
||||
* 复制文本到剪贴板
|
||||
* @param text 文本内容
|
||||
*/
|
||||
export const copyText = (text: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fakeElement = document.createElement('button')
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import padStart from 'lodash/padStart'
|
||||
|
||||
// 生成随机码
|
||||
/**
|
||||
* 生成随机码
|
||||
* @param len 随机码长度
|
||||
*/
|
||||
export const createRandomCode = (len = 6) => {
|
||||
const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`
|
||||
const maxLen = charset.length
|
||||
|
@ -12,7 +15,11 @@ export const createRandomCode = (len = 6) => {
|
|||
return ret
|
||||
}
|
||||
|
||||
// 数字补足位数,例如将6补足3位 -> 003
|
||||
/**
|
||||
* 补足数字位数
|
||||
* @param digit 数字
|
||||
* @param len 位数
|
||||
*/
|
||||
export const fillDigit = (digit: number, len: number) => {
|
||||
return padStart('' + digit, len, '0')
|
||||
}
|
|
@ -2,12 +2,18 @@ import CryptoJS from 'crypto-js'
|
|||
|
||||
const CRYPTO_KEY = 'pptist'
|
||||
|
||||
// 加密函数
|
||||
/**
|
||||
* 加密
|
||||
* @param msg 待加密字符串
|
||||
*/
|
||||
export const encrypt = (msg: string) => {
|
||||
return CryptoJS.AES.encrypt(msg, CRYPTO_KEY).toString()
|
||||
}
|
||||
|
||||
// 解密函数
|
||||
/**
|
||||
* 解密
|
||||
* @param ciphertext 待解密字符串
|
||||
*/
|
||||
export const decrypt = (ciphertext: string) => {
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, CRYPTO_KEY)
|
||||
return bytes.toString(CryptoJS.enc.Utf8)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { PPTElement } from '@/types/slides'
|
||||
|
||||
// 获取矩形旋转后在画布中的位置范围
|
||||
interface RotatedElementData {
|
||||
left: number;
|
||||
top: number;
|
||||
|
@ -8,6 +7,11 @@ interface RotatedElementData {
|
|||
height: number;
|
||||
rotate: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算元素在画布中的矩形范围旋转后的新位置范围
|
||||
* @param element 元素的位置大小和旋转角度信息
|
||||
*/
|
||||
export const getRectRotatedRange = (element: RotatedElementData) => {
|
||||
const { left, top, width, height, rotate = 0 } = element
|
||||
|
||||
|
@ -17,11 +21,8 @@ export const getRectRotatedRange = (element: RotatedElementData) => {
|
|||
const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180
|
||||
const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180
|
||||
|
||||
const halfWidth = width / 2
|
||||
const halfHeight = height / 2
|
||||
|
||||
const middleLeft = left + halfWidth
|
||||
const middleTop = top + halfHeight
|
||||
const middleLeft = left + width / 2
|
||||
const middleTop = top + height / 2
|
||||
|
||||
const xAxis = [
|
||||
middleLeft + radius * Math.cos(tlbraRadian),
|
||||
|
@ -42,7 +43,10 @@ export const getRectRotatedRange = (element: RotatedElementData) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 获取元素在画布中的位置范围
|
||||
/**
|
||||
* 计算元素在画布中的位置范围
|
||||
* @param element 元素信息
|
||||
*/
|
||||
export const getElementRange = (element: PPTElement) => {
|
||||
let minX, maxX, minY, maxY
|
||||
|
||||
|
@ -69,7 +73,10 @@ export const getElementRange = (element: PPTElement) => {
|
|||
return { minX, maxX, minY, maxY }
|
||||
}
|
||||
|
||||
// 获取元素集合在画布中的位置范围
|
||||
/**
|
||||
* 计算一组元素在画布中的位置范围
|
||||
* @param elementList 一组元素信息
|
||||
*/
|
||||
export const getElementListRange = (elementList: PPTElement[]) => {
|
||||
const leftValues: number[] = []
|
||||
const topValues: number[] = []
|
||||
|
@ -97,7 +104,10 @@ export interface AlignLine {
|
|||
range: [number, number];
|
||||
}
|
||||
|
||||
// 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条
|
||||
/**
|
||||
* 将一组参考线进行去重:同位置的的多条参考线仅留下一条,取该位置所有参考线的最大值和最小值为新的范围
|
||||
* @param lines 一组参考线信息
|
||||
*/
|
||||
export const uniqAlignLines = (lines: AlignLine[]) => {
|
||||
const uniqLines: AlignLine[] = []
|
||||
lines.forEach(line => {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
// 判断用户的操作系统是否安装了某字体
|
||||
/**
|
||||
* 判断操作系统是否存在某字体
|
||||
* @param fontFamily 字体名
|
||||
*/
|
||||
export const isSupportFontFamily = (fontFamily: string) => {
|
||||
if (typeof fontFamily !== 'string') return false
|
||||
|
||||
const arial = 'Arial'
|
||||
if (fontFamily.toLowerCase() === arial.toLowerCase()) return true
|
||||
const a = 'a'
|
||||
|
||||
const size = 100
|
||||
const width = 100
|
||||
const height = 100
|
||||
const str = 'a'
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
@ -22,7 +27,7 @@ export const isSupportFontFamily = (fontFamily: string) => {
|
|||
const getDotArray = (_fontFamily: string) => {
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
ctx.font = `${size}px ${_fontFamily}, ${arial}`
|
||||
ctx.fillText(a, width / 2, height / 2)
|
||||
ctx.fillText(str, width / 2, height / 2)
|
||||
const imageData = ctx.getImageData(0, 0, width, height).data
|
||||
return [].slice.call(imageData).filter(item => item !== 0)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,10 @@ interface ImageSize {
|
|||
height: number;
|
||||
}
|
||||
|
||||
// 获取图片的原始宽高
|
||||
/**
|
||||
* 获取图片的原始宽高
|
||||
* @param src 图片地址
|
||||
*/
|
||||
export const getImageSize = (src: string): Promise<ImageSize> => {
|
||||
return new Promise(resolve => {
|
||||
const img = document.createElement('img')
|
||||
|
@ -30,7 +33,10 @@ export const getImageSize = (src: string): Promise<ImageSize> => {
|
|||
})
|
||||
}
|
||||
|
||||
// 获取图片文件的dataURL
|
||||
/**
|
||||
* 读取图片文件的dataURL
|
||||
* @param file 图片文件
|
||||
*/
|
||||
export const getImageDataURL = (file: File): Promise<string> => {
|
||||
return new Promise(resolve => {
|
||||
const reader = new FileReader()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// 清除文字选区
|
||||
export const removeAllRanges = () => {
|
||||
const selection = window.getSelection()
|
||||
selection && selection.removeAllRanges()
|
||||
|
|
Loading…
Reference in New Issue