1 line
1.2 MiB
1 line
1.2 MiB
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/views/Editor/Toolbar/common/ColorButton.vue?bd6e","webpack:///./src/views/components/element/ChartElement/ScreenChartElement.vue?f10a","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue?0296","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageEllipseOutline.vue?a4df","webpack:///./src/views/components/element/ChartElement/Chart.vue?3987","webpack:///./src/views/components/element/TableElement/StaticTable.vue?70f4","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue?b78c","webpack:///./src/views/Editor/Canvas/index.vue?e6b0","webpack:///./src/views/Editor/Canvas/MouseSelection.vue?185b","webpack:///./src/views/components/element/ShapeElement/BaseShapeElement.vue?4e3a","webpack:///./src/views/components/element/TableElement/index.vue?916a","webpack:///./src/views/Editor/Thumbnails/index.vue?ec0b","webpack:///./src/views/components/element/LineElement/index.vue?b9de","webpack:///./src/views/Editor/CanvasTool/ShapePool.vue?9f2f","webpack:///./src/views/Editor/Toolbar/index.vue?7099","webpack:///./src/views/components/element/ChartElement/index.vue?34f2","webpack:///./src/components/ColorPicker/EditableInput.vue?72fc","webpack:///./src/views/components/element/ChartElement/BaseChartElement.vue?f399","webpack:///./node_modules/moment/locale sync ^\\.\\/.*$","webpack:///./src/views/Screen/WritingBoardTool.vue?85a4","webpack:///./src/components/ColorPicker/Saturation.vue?8110","webpack:///./src/views/components/element/ShapeElement/index.vue?e0c8","webpack:///./src/views/Editor/Canvas/GridLines.vue?a413","webpack:///./src/views/Editor/Toolbar/SlideAnimationPanel.vue?0831","webpack:///./src/views/Editor/EditorHeader/index.vue?2d98","webpack:///./src/views/components/element/TextElement/index.vue?3ccb","webpack:///./src/components/Contextmenu/MenuContent.vue?e6e4","webpack:///./src/views/components/element/ImageElement/index.vue?fac4","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TableStylePanel.vue?ef13","webpack:///./src/views/Editor/Canvas/Operate/ImageElementOperate.vue?8e40","webpack:///./src/components/ColorPicker/Alpha.vue?464a","webpack:///./src/components/ColorPicker/Checkboard.vue?024a","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImagePolygonOutline.vue?de61","webpack:///./src/views/Editor/Toolbar/common/ElementOpacity.vue?6c64","webpack:///./src/components/CheckboxButtonGroup.vue?3a3e","webpack:///./src/views/components/element/ImageElement/ImageClipHandler.vue?7480","webpack:///./src/components/WritingBoard.vue?261d","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ShapeStylePanel.vue?b1b9","webpack:///./src/views/Editor/CanvasTool/index.vue?3c4d","webpack:///./src/views/components/element/ImageElement/BaseImageElement.vue?750b","webpack:///./src/views/Screen/index.vue?a2ac","webpack:///./src/components/CheckboxButton.vue?2273","webpack:///./src/views/Editor/Toolbar/common/ElementOutline.vue?a0ca","webpack:///./src/components/Contextmenu/index.vue?3987","webpack:///./src/views/Editor/Toolbar/SlideStylePanel.vue?9f38","webpack:///./src/views/Editor/Canvas/Operate/RotateHandler.vue?ba52","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/LineStylePanel.vue?ae92","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue?627d","webpack:///./src/views/components/ThumbnailSlide/index.vue?4cde","webpack:///./src/views/Editor/Canvas/AlignmentLine.vue?fb4e","webpack:///./src/views/Editor/Canvas/Operate/index.vue?13d6","webpack:///./src/views/Screen/ScreenSlide.vue?83ff","webpack:///./src/views/Screen/SlideThumbnails.vue?dc65","webpack:///./src/views/Editor/Canvas/ElementCreateSelection.vue?c6bd","webpack:///./src/components/ColorPicker/Hue.vue?e4fe","webpack:///./src/App.vue?af3c","webpack:///./src/views/Editor/Toolbar/MultiPositionPanel.vue?756b","webpack:///./src/views/Editor/Canvas/Operate/ResizeHandler.vue?16dd","webpack:///./src/views/Editor/Toolbar/common/ElementFlip.vue?6131","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue?bc39","webpack:///./src/views/Editor/CanvasTool/LinePool.vue?211c","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageRectOutline.vue?a16c","webpack:///./src/views/Editor/CanvasTool/TableGenerator.vue?5e37","webpack:///./src/views/Editor/Toolbar/ElementPositionPanel.vue?9d3f","webpack:///./src/views/Editor/Canvas/SlideBackground.vue?4250","webpack:///./src/views/components/element/LineElement/BaseLineElement.vue?332d","webpack:///./src/views/components/element/TableElement/BaseTableElement.vue?04c5","webpack:///./src/views/components/element/TextElement/BaseTextElement.vue?eaae","webpack:///./src/views/Editor/Toolbar/common/ElementShadow.vue?152c","webpack:///./src/views/Editor/index.vue?639b","webpack:///./src/App.vue","webpack:///./src/store/constants.ts","webpack:///./src/mocks/index.ts","webpack:///./src/store/state.ts","webpack:///./src/store/getters.ts","webpack:///./src/utils/database.ts","webpack:///./src/store/actions.ts","webpack:///./src/configs/font.ts","webpack:///./src/utils/fontFamily.ts","webpack:///./src/store/mutations.ts","webpack:///./src/store/index.ts","webpack:///./src/views/Editor/index.vue","webpack:///./src/types/edit.ts","webpack:///./src/configs/hotkey.ts","webpack:///./src/utils/common.ts","webpack:///./src/utils/clipboard.ts","webpack:///./src/utils/crypto.ts","webpack:///./src/hooks/useHistorySnapshot.ts","webpack:///./src/utils/image.ts","webpack:///./src/configs/canvas.ts","webpack:///./src/hooks/useCreateElement.ts","webpack:///./src/hooks/usePasteTextClipboardData.ts","webpack:///./src/hooks/useSlideHandler.ts","webpack:///./src/hooks/useLockElement.ts","webpack:///./src/hooks/useDeleteElement.ts","webpack:///./src/hooks/useCombineElement.ts","webpack:///./src/hooks/useCopyAndPasteElement.ts","webpack:///./src/hooks/useSelectAllElement.ts","webpack:///./src/hooks/useMoveElement.ts","webpack:///./src/hooks/useOrderElement.ts","webpack:///./src/utils/fullscreen.ts","webpack:///./src/hooks/useScreening.ts","webpack:///./src/hooks/useScaleCanvas.ts","webpack:///./src/hooks/useGlobalHotkey.ts","webpack:///./src/hooks/usePasteEvent.ts","webpack:///./src/views/Editor/EditorHeader/index.vue","webpack:///./src/views/Editor/EditorHeader/HotkeyDoc.vue","webpack:///./src/views/Editor/EditorHeader/HotkeyDoc.vue?98af","webpack:///./src/views/Editor/EditorHeader/index.vue?ac7b","webpack:///./src/views/Editor/EditorHeader/index.vue?0c5a","webpack:///./src/views/Editor/Canvas/index.vue","webpack:///./src/utils/emitter.ts","webpack:///./src/utils/selection.ts","webpack:///./src/views/Editor/Canvas/hooks/useViewportSize.ts","webpack:///./src/utils/element.ts","webpack:///./src/views/Editor/Canvas/hooks/useMouseSelection.ts","webpack:///./src/views/Editor/Canvas/hooks/useDropImageOrText.ts","webpack:///./src/views/Editor/Canvas/hooks/useRotateElement.ts","webpack:///./src/configs/element.ts","webpack:///./src/views/Editor/Canvas/hooks/useScaleElement.ts","webpack:///./src/views/Editor/Canvas/hooks/useSelectElement.ts","webpack:///./src/views/Editor/Canvas/hooks/useDragElement.ts","webpack:///./src/views/Editor/Canvas/hooks/useDragLineElement.ts","webpack:///./src/views/Editor/Canvas/hooks/useInsertFromCreateSelection.ts","webpack:///./src/views/Editor/Canvas/EditableElement.vue","webpack:///./src/types/slides.ts","webpack:///./src/hooks/useAlignElementToCanvas.ts","webpack:///./src/configs/imageClip.ts","webpack:///./src/views/components/element/ImageElement/index.vue","webpack:///./src/views/components/element/hooks/useElementShadow.ts","webpack:///./src/views/components/element/hooks/useElementFlip.ts","webpack:///./src/views/components/element/ImageElement/useClipImage.ts","webpack:///./src/views/components/element/ImageElement/useFilter.ts","webpack:///./src/views/components/element/ImageElement/ImageOutline/index.vue","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageRectOutline.vue","webpack:///./src/views/components/element/hooks/useElementOutline.ts","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageRectOutline.vue?b8d0","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageRectOutline.vue?8b4e","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageEllipseOutline.vue","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageEllipseOutline.vue?b2f6","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImageEllipseOutline.vue?87cf","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImagePolygonOutline.vue","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImagePolygonOutline.vue?8d2c","webpack:///./src/views/components/element/ImageElement/ImageOutline/ImagePolygonOutline.vue?00b2","webpack:///./src/views/components/element/ImageElement/ImageOutline/index.vue?8881","webpack:///./src/views/components/element/ImageElement/ImageOutline/index.vue?f84d","webpack:///./src/views/components/element/ImageElement/ImageClipHandler.vue","webpack:///./src/views/components/element/ImageElement/ImageClipHandler.vue?90b3","webpack:///./src/views/components/element/ImageElement/ImageClipHandler.vue?59cd","webpack:///./src/views/components/element/ImageElement/index.vue?7284","webpack:///./src/views/components/element/ImageElement/index.vue?18e8","webpack:///./src/views/components/element/TextElement/index.vue","webpack:///./src/prosemirror/plugins/keymap.ts","webpack:///./src/prosemirror/plugins/inputrules.ts","webpack:///./src/prosemirror/plugins/index.ts","webpack:///./src/prosemirror/schema/nodes.ts","webpack:///./src/prosemirror/schema/marks.ts","webpack:///./src/prosemirror/schema/index.ts","webpack:///./src/prosemirror/index.ts","webpack:///./src/prosemirror/utils.ts","webpack:///./src/prosemirror/commands/setTextAlign.ts","webpack:///./src/prosemirror/commands/toggleList.ts","webpack:///./src/views/components/element/ElementOutline.vue","webpack:///./src/views/components/element/ElementOutline.vue?3f74","webpack:///./src/views/components/element/ElementOutline.vue?8633","webpack:///./src/views/components/element/TextElement/index.vue?f1a2","webpack:///./src/views/components/element/TextElement/index.vue?6e22","webpack:///./src/views/components/element/ShapeElement/index.vue","webpack:///./src/views/components/element/ShapeElement/GradientDefs.vue","webpack:///./src/views/components/element/ShapeElement/GradientDefs.vue?2333","webpack:///./src/views/components/element/ShapeElement/GradientDefs.vue?fbe6","webpack:///./src/views/components/element/ShapeElement/index.vue?c8a7","webpack:///./src/views/components/element/ShapeElement/index.vue?a321","webpack:///./src/views/components/element/LineElement/index.vue","webpack:///./src/views/components/element/LineElement/LinePointMarker.vue","webpack:///./src/views/components/element/LineElement/LinePointMarker.vue?9702","webpack:///./src/views/components/element/LineElement/LinePointMarker.vue?0e0f","webpack:///./src/views/components/element/LineElement/index.vue?a024","webpack:///./src/views/components/element/LineElement/index.vue?8fb3","webpack:///./src/views/components/element/ChartElement/index.vue","webpack:///./src/views/components/element/ChartElement/Chart.vue","webpack:///./src/views/components/element/ChartElement/Chart.vue?10d5","webpack:///./src/views/components/element/ChartElement/Chart.vue?9c6f","webpack:///./src/views/components/element/ChartElement/index.vue?e4b0","webpack:///./src/views/components/element/ChartElement/index.vue?2e94","webpack:///./src/views/components/element/TableElement/index.vue","webpack:///./src/views/components/element/TableElement/EditableTable.vue","webpack:///./src/views/components/element/TableElement/utils.ts","webpack:///./src/views/components/element/TableElement/useHideCells.ts","webpack:///./src/views/components/element/TableElement/useSubThemeColor.ts","webpack:///./src/views/components/element/TableElement/CustomTextarea.vue","webpack:///./src/views/components/element/TableElement/CustomTextarea.vue?aea3","webpack:///./src/views/components/element/TableElement/CustomTextarea.vue?e254","webpack:///./src/views/components/element/TableElement/EditableTable.vue?8831","webpack:///./src/views/components/element/TableElement/EditableTable.vue?4197","webpack:///./src/views/components/element/TableElement/index.vue?7604","webpack:///./src/views/components/element/TableElement/index.vue?1057","webpack:///./src/views/Editor/Canvas/EditableElement.vue?381f","webpack:///./src/views/Editor/Canvas/EditableElement.vue?de80","webpack:///./src/views/Editor/Canvas/MouseSelection.vue","webpack:///./src/views/Editor/Canvas/MouseSelection.vue?8b4c","webpack:///./src/views/Editor/Canvas/MouseSelection.vue?8ddc","webpack:///./src/views/Editor/Canvas/SlideBackground.vue","webpack:///./src/views/Editor/Canvas/GridLines.vue","webpack:///./src/views/Editor/Canvas/GridLines.vue?f828","webpack:///./src/views/Editor/Canvas/GridLines.vue?ee36","webpack:///./src/hooks/useSlideBackgroundStyle.ts","webpack:///./src/views/Editor/Canvas/SlideBackground.vue?ad31","webpack:///./src/views/Editor/Canvas/SlideBackground.vue?5457","webpack:///./src/views/Editor/Canvas/AlignmentLine.vue","webpack:///./src/views/Editor/Canvas/AlignmentLine.vue?b5a1","webpack:///./src/views/Editor/Canvas/AlignmentLine.vue?52c1","webpack:///./src/views/Editor/Canvas/ElementCreateSelection.vue","webpack:///./src/views/Editor/Canvas/ElementCreateSelection.vue?e8f4","webpack:///./src/views/Editor/Canvas/ElementCreateSelection.vue?464b","webpack:///./src/views/Editor/Canvas/Operate/MultiSelectOperate.vue","webpack:///./src/views/Editor/Canvas/hooks/useCommonOperate.ts","webpack:///./src/views/Editor/Canvas/Operate/ResizeHandler.vue","webpack:///./src/views/Editor/Canvas/Operate/ResizeHandler.vue?93e1","webpack:///./src/views/Editor/Canvas/Operate/ResizeHandler.vue?06a8","webpack:///./src/views/Editor/Canvas/Operate/BorderLine.vue","webpack:///./src/views/Editor/Canvas/Operate/BorderLine.vue?e6a8","webpack:///./src/views/Editor/Canvas/Operate/BorderLine.vue?c893","webpack:///./src/views/Editor/Canvas/Operate/MultiSelectOperate.vue?d499","webpack:///./src/views/Editor/Canvas/Operate/MultiSelectOperate.vue?65a2","webpack:///./src/views/Editor/Canvas/Operate/index.vue","webpack:///./src/views/Editor/Canvas/Operate/ImageElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/RotateHandler.vue","webpack:///./src/views/Editor/Canvas/Operate/RotateHandler.vue?f60b","webpack:///./src/views/Editor/Canvas/Operate/RotateHandler.vue?6579","webpack:///./src/views/Editor/Canvas/Operate/ImageElementOperate.vue?2229","webpack:///./src/views/Editor/Canvas/Operate/ImageElementOperate.vue?2d82","webpack:///./src/views/Editor/Canvas/Operate/TextElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/TextElementOperate.vue?84ca","webpack:///./src/views/Editor/Canvas/Operate/TextElementOperate.vue?592c","webpack:///./src/views/Editor/Canvas/Operate/ShapeElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/ShapeElementOperate.vue?c074","webpack:///./src/views/Editor/Canvas/Operate/ShapeElementOperate.vue?5f30","webpack:///./src/views/Editor/Canvas/Operate/LineElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/LineElementOperate.vue?df88","webpack:///./src/views/Editor/Canvas/Operate/LineElementOperate.vue?121c","webpack:///./src/views/Editor/Canvas/Operate/ChartElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/ChartElementOperate.vue?4d68","webpack:///./src/views/Editor/Canvas/Operate/ChartElementOperate.vue?054d","webpack:///./src/views/Editor/Canvas/Operate/TableElementOperate.vue","webpack:///./src/views/Editor/Canvas/Operate/TableElementOperate.vue?ce2a","webpack:///./src/views/Editor/Canvas/Operate/TableElementOperate.vue?bf02","webpack:///./src/views/Editor/Canvas/Operate/index.vue?4919","webpack:///./src/views/Editor/Canvas/Operate/index.vue?3933","webpack:///./src/views/Editor/Canvas/index.vue?3cd8","webpack:///./src/views/Editor/Canvas/index.vue?2ed7","webpack:///./src/views/Editor/CanvasTool/index.vue","webpack:///./src/views/Editor/CanvasTool/ShapePool.vue","webpack:///./src/configs/shapes.ts","webpack:///./src/views/Editor/CanvasTool/ShapePool.vue?ddb3","webpack:///./src/views/Editor/CanvasTool/ShapePool.vue?8e86","webpack:///./src/views/Editor/CanvasTool/LinePool.vue","webpack:///./src/configs/lines.ts","webpack:///./src/views/Editor/CanvasTool/LinePool.vue?cda8","webpack:///./src/views/Editor/CanvasTool/LinePool.vue?1c05","webpack:///./src/views/Editor/CanvasTool/ChartPool.vue","webpack:///./src/views/Editor/CanvasTool/ChartPool.vue?cfe0","webpack:///./src/views/Editor/CanvasTool/ChartPool.vue?067e","webpack:///./src/views/Editor/CanvasTool/TableGenerator.vue","webpack:///./src/views/Editor/CanvasTool/TableGenerator.vue?3234","webpack:///./src/views/Editor/CanvasTool/TableGenerator.vue?9744","webpack:///./src/views/Editor/CanvasTool/index.vue?0ffc","webpack:///./src/views/Editor/CanvasTool/index.vue?a532","webpack:///./src/views/Editor/Thumbnails/index.vue","webpack:///./src/views/components/ThumbnailSlide/index.vue","webpack:///./src/views/components/ThumbnailSlide/ThumbnailElement.vue","webpack:///./src/views/components/element/ImageElement/BaseImageElement.vue","webpack:///./src/views/components/element/ImageElement/BaseImageElement.vue?9dd5","webpack:///./src/views/components/element/ImageElement/BaseImageElement.vue?32f2","webpack:///./src/views/components/element/TextElement/BaseTextElement.vue","webpack:///./src/views/components/element/TextElement/BaseTextElement.vue?ac4f","webpack:///./src/views/components/element/TextElement/BaseTextElement.vue?6911","webpack:///./src/views/components/element/ShapeElement/BaseShapeElement.vue","webpack:///./src/views/components/element/ShapeElement/BaseShapeElement.vue?c63c","webpack:///./src/views/components/element/ShapeElement/BaseShapeElement.vue?a27a","webpack:///./src/views/components/element/LineElement/BaseLineElement.vue","webpack:///./src/views/components/element/LineElement/BaseLineElement.vue?24f7","webpack:///./src/views/components/element/LineElement/BaseLineElement.vue?3b6b","webpack:///./src/views/components/element/ChartElement/BaseChartElement.vue","webpack:///./src/views/components/element/ChartElement/BaseChartElement.vue?b511","webpack:///./src/views/components/element/ChartElement/BaseChartElement.vue?aa7f","webpack:///./src/views/components/element/TableElement/BaseTableElement.vue","webpack:///./src/views/components/element/TableElement/StaticTable.vue","webpack:///./src/views/components/element/TableElement/StaticTable.vue?a3ae","webpack:///./src/views/components/element/TableElement/StaticTable.vue?b2de","webpack:///./src/views/components/element/TableElement/BaseTableElement.vue?341a","webpack:///./src/views/components/element/TableElement/BaseTableElement.vue?a02b","webpack:///./src/views/components/ThumbnailSlide/ThumbnailElement.vue?2f2d","webpack:///./src/views/components/ThumbnailSlide/ThumbnailElement.vue?944e","webpack:///./src/views/components/ThumbnailSlide/index.vue?ef6c","webpack:///./src/views/components/ThumbnailSlide/index.vue?8be7","webpack:///./src/views/Editor/Thumbnails/index.vue?1806","webpack:///./src/views/Editor/Thumbnails/index.vue?ccb9","webpack:///./src/views/Editor/Toolbar/index.vue","webpack:///./src/types/toolbar.ts","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/index.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue","webpack:///./src/views/Editor/Toolbar/common/ElementOpacity.vue","webpack:///./src/views/Editor/Toolbar/common/ElementOpacity.vue?5b98","webpack:///./src/views/Editor/Toolbar/common/ElementOpacity.vue?a078","webpack:///./src/views/Editor/Toolbar/common/ElementOutline.vue","webpack:///./src/views/Editor/Toolbar/common/ColorButton.vue","webpack:///./src/views/Editor/Toolbar/common/ColorButton.vue?f8b9","webpack:///./src/views/Editor/Toolbar/common/ColorButton.vue?da97","webpack:///./src/views/Editor/Toolbar/common/ElementOutline.vue?3bfa","webpack:///./src/views/Editor/Toolbar/common/ElementOutline.vue?fb3b","webpack:///./src/views/Editor/Toolbar/common/ElementShadow.vue","webpack:///./src/views/Editor/Toolbar/common/ElementShadow.vue?d5a3","webpack:///./src/views/Editor/Toolbar/common/ElementShadow.vue?270f","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue?655d","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue?5a19","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue","webpack:///./src/views/Editor/Toolbar/common/ElementFlip.vue","webpack:///./src/views/Editor/Toolbar/common/ElementFlip.vue?e3e2","webpack:///./src/views/Editor/Toolbar/common/ElementFlip.vue?4679","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue?b46c","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue?fd61","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ShapeStylePanel.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ShapeStylePanel.vue?11b1","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ShapeStylePanel.vue?e0af","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/LineStylePanel.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/LineStylePanel.vue?f4cd","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/LineStylePanel.vue?e25e","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue?8789","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue?2855","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue?ef13","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue?b3de","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TableStylePanel.vue","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TableStylePanel.vue?ea14","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/TableStylePanel.vue?0d68","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/index.vue?7c3a","webpack:///./src/views/Editor/Toolbar/ElementStylePanel/index.vue?72ab","webpack:///./src/views/Editor/Toolbar/ElementPositionPanel.vue","webpack:///./src/views/Editor/Toolbar/ElementPositionPanel.vue?ed09","webpack:///./src/views/Editor/Toolbar/ElementPositionPanel.vue?e2ca","webpack:///./src/views/Editor/Toolbar/ElementAnimationPanel.vue","webpack:///./src/configs/animation.ts","webpack:///./src/views/Editor/Toolbar/ElementAnimationPanel.vue?9b7c","webpack:///./src/views/Editor/Toolbar/ElementAnimationPanel.vue?afe1","webpack:///./src/views/Editor/Toolbar/SlideStylePanel.vue","webpack:///./src/configs/theme.ts","webpack:///./src/views/Editor/Toolbar/SlideStylePanel.vue?1908","webpack:///./src/views/Editor/Toolbar/SlideStylePanel.vue?0da1","webpack:///./src/views/Editor/Toolbar/SlideAnimationPanel.vue","webpack:///./src/views/Editor/Toolbar/SlideAnimationPanel.vue?0069","webpack:///./src/views/Editor/Toolbar/SlideAnimationPanel.vue?7cbb","webpack:///./src/views/Editor/Toolbar/MultiPositionPanel.vue","webpack:///./src/views/Editor/Toolbar/MultiPositionPanel.vue?d8f3","webpack:///./src/views/Editor/Toolbar/MultiPositionPanel.vue?e1fe","webpack:///./src/views/Editor/Toolbar/index.vue?2e1e","webpack:///./src/views/Editor/Toolbar/index.vue?f66c","webpack:///./src/views/Editor/index.vue?a4f9","webpack:///./src/views/Editor/index.vue?894c","webpack:///./src/views/Screen/index.vue","webpack:///./src/views/Screen/ScreenSlide.vue","webpack:///./src/views/Screen/ScreenElement.vue","webpack:///./src/views/components/element/ChartElement/ScreenChartElement.vue","webpack:///./src/views/components/element/ChartElement/ScreenChartElement.vue?fccb","webpack:///./src/views/components/element/ChartElement/ScreenChartElement.vue?f992","webpack:///./src/views/Screen/ScreenElement.vue?e100","webpack:///./src/views/Screen/ScreenElement.vue?5632","webpack:///./src/views/Screen/ScreenSlide.vue?749f","webpack:///./src/views/Screen/ScreenSlide.vue?67b9","webpack:///./src/views/Screen/SlideThumbnails.vue","webpack:///./src/views/Screen/SlideThumbnails.vue?6af1","webpack:///./src/views/Screen/SlideThumbnails.vue?02c0","webpack:///./src/views/Screen/WritingBoardTool.vue","webpack:///./src/components/WritingBoard.vue","webpack:///./src/components/WritingBoard.vue?419f","webpack:///./src/components/WritingBoard.vue?f8b8","webpack:///./src/views/Screen/WritingBoardTool.vue?b982","webpack:///./src/views/Screen/WritingBoardTool.vue?2e1b","webpack:///./src/views/Screen/index.vue?4bb4","webpack:///./src/views/Screen/index.vue?5535","webpack:///./src/App.vue?1d14","webpack:///./src/App.vue?97f5","webpack:///./src/components/Contextmenu/index.vue","webpack:///./src/components/Contextmenu/MenuContent.vue","webpack:///./src/components/Contextmenu/MenuContent.vue?e94a","webpack:///./src/components/Contextmenu/MenuContent.vue?bb2c","webpack:///./src/components/Contextmenu/index.vue?93d7","webpack:///./src/components/Contextmenu/index.vue?d39d","webpack:///./src/plugins/contextmenu.ts","webpack:///./src/plugins/clickOutside.ts","webpack:///./src/plugins/iconPark.ts","webpack:///./src/components/FileInput.vue","webpack:///./src/components/FileInput.vue?c273","webpack:///./src/components/FileInput.vue?ebff","webpack:///./src/components/SvgWrapper.vue","webpack:///./src/components/SvgWrapper.vue?a337","webpack:///./src/components/SvgWrapper.vue?4c4a","webpack:///./src/components/CheckboxButton.vue","webpack:///./src/components/CheckboxButton.vue?a662","webpack:///./src/components/CheckboxButton.vue?e089","webpack:///./src/components/CheckboxButtonGroup.vue","webpack:///./src/components/CheckboxButtonGroup.vue?2771","webpack:///./src/components/CheckboxButtonGroup.vue?3ae2","webpack:///./src/components/ColorPicker/index.vue","webpack:///./src/components/ColorPicker/Alpha.vue","webpack:///./src/components/ColorPicker/Checkboard.vue","webpack:///./src/components/ColorPicker/Checkboard.vue?23ca","webpack:///./src/components/ColorPicker/Checkboard.vue?d504","webpack:///./src/components/ColorPicker/Alpha.vue?103b","webpack:///./src/components/ColorPicker/Alpha.vue?8cd5","webpack:///./src/components/ColorPicker/Hue.vue","webpack:///./src/components/ColorPicker/Hue.vue?8d53","webpack:///./src/components/ColorPicker/Hue.vue?e08e","webpack:///./src/components/ColorPicker/Saturation.vue","webpack:///./src/components/ColorPicker/Saturation.vue?7dac","webpack:///./src/components/ColorPicker/Saturation.vue?b755","webpack:///./src/components/ColorPicker/EditableInput.vue","webpack:///./src/components/ColorPicker/EditableInput.vue?6a4f","webpack:///./src/components/ColorPicker/EditableInput.vue?f9ac","webpack:///./src/components/ColorPicker/index.vue?5336","webpack:///./src/components/ColorPicker/index.vue?4c0a","webpack:///./src/main.ts","webpack:///./src/views/Editor/CanvasTool/ChartPool.vue?a1c8","webpack:///./src/views/components/element/ElementOutline.vue?a889","webpack:///./src/views/Editor/Canvas/Operate/MultiSelectOperate.vue?a30e","webpack:///./src/components/ColorPicker/index.vue?809b","webpack:///./src/components/FileInput.vue?320a","webpack:///./src/views/components/element/TableElement/EditableTable.vue?3919","webpack:///./src/views/components/element/ChartElement/Chart.vue?f277","webpack:///./src/views/Editor/EditorHeader/HotkeyDoc.vue?e4d6","webpack:///./src/views/Editor/Toolbar/ElementAnimationPanel.vue?e32e","webpack:///./src/views/Editor/Canvas/Operate/BorderLine.vue?efe0"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","map","webpackContext","req","id","webpackContextResolve","e","Error","code","keys","resolve","screening","MutationTypes","ActionTypes","elements","activeElementIdList","handleElementId","canvasPercentage","canvasScale","thumbnailsFocus","editorAreaFocus","disableHotkeys","showGridLines","creatingElement","availableFonts","toolbarState","theme","themeColor","fontColor","fontName","backgroundColor","slides","slideIndex","snapshotCursor","snapshotLength","ctrlKeyState","shiftKeyState","clipingImageElementId","getters","currentSlide","state","currentSlideAnimations","animations","els","elIds","el","filter","animation","includes","elId","activeElementList","element","handleElement","find","canUndo","canRedo","ctrlOrShiftKeyActive","version","stores","snapshots","table","actions","INIT_SNAPSHOT_DATABASE","commit","orderBy","toArray","lastSnapshot","clear","newFirstSnapshot","index","add","SET_SNAPSHOT_CURSOR","SET_SNAPSHOT_LENGTH","ADD_SNAPSHOT","allKeys","needDeleteKeys","snapshot","update","bulkDelete","UN_DO","SET_SLIDES","UPDATE_SLIDE_INDEX","SET_ACTIVE_ELEMENT_ID_LIST","RE_DO","SYS_FONTS","label","WEB_FONTS","isSupportFontFamily","fontFamily","arial","toLowerCase","size","width","height","str","canvas","document","createElement","ctx","getContext","textAlign","fillStyle","textBaseline","getDotArray","_fontFamily","clearRect","font","fillText","imageData","getImageData","item","join","mutations","SET_HANDLE_ELEMENT_ID","SET_CANVAS_PERCENTAGE","percentage","SET_CANVAS_SCALE","scale","SET_THUMBNAILS_FOCUS","isFocus","SET_EDITORAREA_FOCUS","SET_DISABLE_HOTKEYS_STATE","disable","SET_GRID_LINES_STATE","show","SET_CREATING_ELEMENT","SET_AVAILABLE_FONTS","SET_TOOLBAR_STATE","type","SET_CLIPING_IMAGE_ELEMENT_ID","SET_THEME","themeProps","ADD_SLIDE","slide","addIndex","UPDATE_SLIDE","props","DELETE_SLIDE","slideId","deleteIndex","findIndex","ADD_ELEMENT","Array","isArray","currentSlideEls","newEls","UPDATE_ELEMENT","elIdList","REMOVE_ELEMENT_PROPS","propName","propsNames","cursor","SET_CTRL_KEY_STATE","isActive","SET_SHIFT_KEY_STATE","SET_SCREENING","class","ElementOrderCommands","ElementAlignCommands","OperateBorderLines","OperateResizeHandlers","OperateLineHandlers","KEYS","HOTKEY_DOC","children","createRandomCode","len","charset","maxLen","ret","randomIndex","Math","floor","random","digit","Promise","reject","fakeElement","clipboard","text","action","container","body","on","destroy","appendChild","click","removeChild","readClipboard","navigator","readText","then","CRYPTO_KEY","msg","AES","encrypt","toString","ciphertext","bytes","decrypt","enc","Utf8","store","addHistorySnapshot","dispatch","trailing","redo","leading","undo","getImageSize","src","img","style","opacity","onload","imgWidth","clientWidth","imgHeight","clientHeight","onerror","getImageDataURL","file","reader","FileReader","addEventListener","readAsDataURL","VIEWPORT_SIZE","VIEWPORT_ASPECT_RATIO","useHistorySnapshot","createImageElement","left","top","fixedRatio","createChartElement","chartType","gridColor","labels","series","createTableElement","row","col","rowCells","fill","colspan","rowspan","DEFAULT_CELL_WIDTH","DEFAULT_CELL_HEIGHT","colWidths","outline","color","rowHeader","rowFooter","colHeader","colFooter","createTextElement","position","content","createShapeElement","viewBox","path","createLineElement","start","end","points","useCreateElement","pasteElement","groupIdMap","elIdMap","groupId","currentSlideElementIdList","inCurrentSlide","values","pasteSlide","pasteText","pasteTextClipboardData","options","clipboardData","onlySlide","onlyElements","JSON","parse","slidesLength","usePasteTextClipboardData","updateSlideIndex","command","targetIndex","UP","DOWN","copySlide","stringify","catch","err","message","warning","createSlide","emptySlide","background","copyAndPasteSlide","deleteSlide","cutSlide","lockElement","newElementList","lock","unlockElement","deleteElement","deleteAllElements","combineElements","combineElementList","combineElementMaxLevel","_element","combineElementIdList","insertLevel","uncombineElements","hasElementInGroup","some","handleElementIdList","useDeleteElement","copyElement","cutElement","quickCopyElement","selectAllElement","unlockedElements","newActiveElementIdList","moveElement","step","LEFT","RIGHT","getCombineElementLevelRange","elementList","minLevel","maxLevel","moveUpElement","copyOfElementList","nextElement","movedElementList","nextCombineElementList","level","movedElement","moveDownElement","prevElement","prevCombineElementList","moveTopElement","moveBottomElement","unshift","orderElement","TOP","BOTTOM","enterFullscreen","docElm","documentElement","requestFullscreen","mozRequestFullScreen","webkitRequestFullScreen","exitFullscreen","mozCancelFullScreen","webkitCancelFullScreen","isFullscreen","mozFullScreen","webkitIsFullScreen","webkitFullScreen","enterScreening","enterScreeningFromStart","exitScreening","scaleCanvas","max","min","setCanvasPercentage","ctrlKeyActive","shiftKeyActive","useSlideHandler","useCombineElement","useLockElement","useCopyAndPasteElement","useSelectAllElement","useMoveElement","useOrderElement","useScreening","useScaleCanvas","copy","cut","quickCopy","selectAll","combine","uncombine","remove","move","order","keydownListener","ctrlKey","shiftKey","altKey","metaKey","toUpperCase","F","preventDefault","C","X","D","Z","Y","A","L","G","B","DELETE","BACKSPACE","ENTER","MINUS","EQUAL","DIGIT_0","keyupListener","removeEventListener","pasteImageFile","imageFile","dataURL","pasteListener","clipboardDataItems","items","clipboardDataFirstItem","kind","indexOf","getAsFile","getAsString","href","target","trigger","overlay","toggleGridLines","resetSlides","openDoc","hotkeyDrawerVisible","mouseLeaveDelay","title","placement","visible","hotkeys","hotkey","setup","render","__scopeId","components","HotkeyDoc","EmitterEvents","ref","$event","mousewheelScaleCanvas","handleClickBlankArea","insertElementFromCreateSelection","alignmentLines","line","axis","scaleMultiElement","elementInfo","isSelected","isActiveGroupElement","activeGroupElementId","isMultiSelect","rotateElement","scaleElement","dragLineElement","mouseSelectionState","isShow","quadrant","elementIndex","selectElement","contextmenus","removeEditorAreaFocus","removeAllRanges","selection","getSelection","canvasRef","viewportLeft","viewportTop","setViewportPosition","canvasWidth","canvasHeight","viewportActualWidth","viewportActualHeight","viewportStyles","resizeObserver","ResizeObserver","observe","unobserve","getRectRotatedRange","rotate","radius","sqrt","pow","auxiliaryAngle","atan","PI","tlbraRadian","trblaRadian","middleLeft","middleTop","xAxis","cos","yAxis","sin","xRange","yRange","getElementRange","minX","maxX","minY","maxY","getElementListRange","leftValues","topValues","rightValues","bottomValues","forEach","uniqAlignLines","lines","uniqLines","_line","uniqLine","rangeMin","range","rangeMax","viewportRef","updateMouseSelection","isMouseDown","viewportRect","getBoundingClientRect","minSelectionRange","startPageX","pageX","startPageY","pageY","x","y","onmousemove","currentPageX","currentPageY","offsetWidth","offsetHeight","abs","onmouseup","inRangeElementList","mouseSelectionLeft","mouseSelectionTop","mouseSelectionWidth","mouseSelectionHeight","isInclude","inRangeElement","groupElementList","every","groupElement","inRangeElementIdList","elementRef","handleDrop","dataTransfer","dataTransferItem","ondragleave","ondrop","ondragenter","ondragover","getAngleFromCoordinate","radian","atan2","angle","elOriginRotate","elLeft","elTop","elWidth","elHeight","centerX","centerY","mouseX","mouseY","sorptionRange","emitter","ELEMENT_TYPE_ZH","image","shape","chart","MIN_SIZE","getRotateElementPoints","taRadian","raRadian","halfWidth","halfHeight","leftTopPoint","topPoint","rightTopPoint","rightPoint","rightBottomPoint","bottomPoint","leftBottomPoint","leftPoint","direction","oppositeMap","RIGHT_BOTTOM","LEFT_BOTTOM","LEFT_TOP","RIGHT_TOP","emit","SCALE_ELEMENT_STATE","elOriginLeft","elOriginTop","elOriginWidth","elOriginHeight","elRotate","rotateRadian","aspectRatio","minSize","getSizeWithinRange","baseLeft","baseTop","horizontalLines","verticalLines","oppositePoint","edgeWidth","edgeHeight","right","bottom","topLine","bottomLine","leftLine","rightLine","edgeTopLine","edgeBottomLine","edgeHorizontalCenterLine","edgeLeftLine","edgeRightLine","edgeVerticalCenterLine","alignedAdsorption","currentX","currentY","_alignmentLines","isVerticalAdsorbed","isHorizontalAdsorbed","correctionVal","offsetX","offsetY","revisedX","revisedY","currentPoints","currentOppositePoint","currentBaseLeft","currentBaseTop","moveX","moveY","operateWidth","operateHeight","originElementList","currentMinX","currentMaxX","currentMinY","currentMaxY","currentOppositeWidth","currentOppositeHeight","widthScale","heightScale","originElement","originEl","canMove","newActiveIdList","groupMembersId","dragElement","originActiveElementList","isMisoperation","horizontalCenterLine","verticalCenterLine","targetMinX","targetMaxX","targetMinY","targetMaxY","targetLeft","targetTop","targetCenterX","targetCenterY","adsorptionPoints","startX","startY","endX","endY","START","adsorptionPoint","formatCreateSelection","selectionData","formatCreateSelectionForLine","_start","_end","currentElementComponent","ElementTypes","ClipPathTypes","ClipPaths","alignElementToCanvas","viewportWidth","viewportHeight","CENTER","VERTICAL","HORIZONTAL","handleSelectElement","isCliping","clipData","clip","clipPath","clipShape","handleClip","draggable","alt","shadow","shadowStyle","h","v","blur","flip","flipStyle","CLIPPATHS","rect","RECT","rect2","POLYGON","createPath","rect3","roundRect","ellipse","ELLIPSE","triangle","triangle2","triangle3","rhombus","hexagon","pentagon","parallelogram","parallelogram2","trapezoid","trapezoid2","imgPosition","filters","overflow","vector-effect","stroke-linecap","stroke-miterlimit","stroke-linejoin","rx","ry","stroke","outlineColor","stroke-width","outlineWidth","stroke-dasharray","outlineStyle","Number","required","String","default","useElementOutline","cx","cy","Function","ImageRectOutline","ImageEllipseOutline","ImagePolygonOutline","useClipImage","shape-rendering","clipWrapperPositionStyle","bottomImgPositionStyle","topImgPositionStyle","topImgWrapperPositionStyle","moveClipRange","point","scaleClipRange","isSettingClipRange","currentRange","getClipDataTransformInfo","topImgWrapperPosition","bottomWidth","bottomHeight","topLeft","topTop","topWidth","topHeight","initClipPosition","clipedEmitData","keyboardListener","updateRange","retPosition","parseInt","bottomPosition","originPositopn","setTimeout","minWidth","minHeight","targetWidth","targetHeight","ImageOutline","ImageClipHandler","useElementShadow","useElementFlip","useFilter","stopPropagation","originClip","_props","schema","cmd","marks","strong","em","underline","strikethrough","nodes","list_item","nodeType","match","node","childCount","attrs","rules","blockquote","ordered_list","bullet_list","code_block","_orderedList","group","_bulletList","align","parseDOM","tag","getAttrs","dom","getAttribute","test","toDOM","paragraph","subscript","excludes","superscript","forecolor","mark","backcolor","inline","fontsize","fontname","replace","schemaNodes","schemaMarks","htmlString","parser","DOMParser","parseFromString","firstElementChild","fromSchema","doc","plugins","equalNodeType","findParentNodeClosestToPos","$pos","predicate","depth","pos","before","findParentNode","_ref","$from","findParentNodeOfType","isActiveOfParentNodeType","getMarkAttrs","view","from","nodeAt","markType","attr","getAttrValueInSelection","to","keepChecking","nodesBetween","getTextAttrs","isBold","isEm","isUnderline","isStrikethrough","isSuperscript","isSubscript","isCode","isBulletList","isOrderedList","isBlockquote","bold","bulletList","orderedList","tr","alignment","listItem","tasks","allowedNodeTypes","Set","has","task","setNodeMarkup","alignmentCommand","setSelection","isList","listType","itemType","$to","blockRange","parentList","validContent","ElementOutline","editorView","isScaling","realHeightCache","editorViewRef","scaleElementStateListener","off","updateTextElementHeight","entries","contentRect","realHeight","handleFocus","handleBlur","handleInput","innerHTML","handleClick","UPDATE_TEXT_STATE","handleKeydown","textContent","hasFocus","setProps","editable","handleDOMEvents","focus","keydown","execCommand","payload","commands","empty","addMark","removeMark","EXEC_TEXT_COMMAND","gradient","color1","color2","transform","x1","y1","x2","y2","gradientTransform","offset","stop-color","GradientDefs","svgWidth","svgHeight","baseSize","lineDashArray","marker-start","marker-end","markerUnits","orient","markerWidth","markerHeight","refX","refY","pathMap","dot","arrow","rotateMap","LinePointMarker","chartRef","slideScale","getDataAndOptions","propsOptopns","renderChart","updateChart","updateTheme","hsla","toHsl","_hsla","setProperty","toRgbString","updateGridColor","Chart","updateTableCells","widths","updateColWidths","cells","updateSelectedCells","startEdit","totalWidth","dragLinePosition","handleMousedownColHandler","subThemeColor","colSizeList","span","tableCells","rowIndex","cell","colIndex","data-cell-index","handleCellMousedown","handleCellMouseenter","activedCell","contenteditable","hideCells","getTextStyle","fontWeight","fontStyle","textDecoration","fontSize","rgba","toRgb","subRgba1","g","b","a","subRgba2","immediate","modelValue","Boolean","textareaRef","onpaste","CustomTextarea","isStartSelect","startCell","endCell","set","newData","useSubThemeColor","reduce","removeSelectedCells","useHideCells","selectedCells","selectedRange","handleMouseup","button","isHideCell","selectCol","maxRow","selectRow","maxCol","deleteRow","_tableCells","targetCells","hideCellsPos","deleteCol","insertRow","insertCol","mergeCells","splitCells","originWidth","round","clearSelectedCellText","tabActiveCell","getNextCell","nextRow","nextCol","nextCell","textRef","querySelector","TAB","split","getEffectiveTableCells","effectiveTableCells","_rowCells","checkCanDeleteRowOrCol","canDeleteRow","canDeleteCol","checkCanMergeOrSplit","isMultiSelected","targetCell","canMerge","canSplit","cellIndex","dataset","handler","divider","EditableTable","updateTableElementHeight","UPDATE_TABLE_SELECTED_CELL","elementTypeMap","IMAGE","ImageElement","TEXT","TextElement","SHAPE","ShapeElement","LINE","LineElement","CHART","ChartElement","TABLE","TableElement","useAlignElementToCanvas","subText","hide","validator","backgroundStyle","newRgba","gridSize","getPath","imageSize","gradientColor","gradientRotate","gradientType","backgroundImage","backgroundRepeat","backgroundSize","GridLines","useSlideBackgroundStyle","sizeStyle","createSelection","lineData","selectionRef","absX","absY","isOpposite","endPageX","endPageY","_startX","_startY","_endX","_endY","borderLines","disableResize","resizeHandlers","textElementResizeHandlers","T","R","isWide","ResizeHandler","BorderLine","localActiveElementList","useCommonOperate","setRange","currentOperateComponent","elementIndexInAnimation","scaleWidth","inheritAttrs","RotateHandler","scaleHeight","END","ImageElementOperate","TextElementOperate","ShapeElementOperate","LineElementOperate","ChartElementOperate","TableElementOperate","EditableElement","MouseSelection","SlideBackground","AlignmentLine","ElementCreateSelection","MultiSelectOperate","Operate","setLocalElementList","useViewportSize","useDropImageOrText","useMouseSelection","useDragElement","useDragLineElement","useSelectElement","useScaleElement","useRotateElement","throttleScaleCanvas","deltaY","useInsertFromCreateSelection","mouseEnterDelay","drawText","files","insertImageElement","shapePoolVisible","drawShape","linePoolVisible","drawLine","chartPoolVisible","tableGeneratorVisible","canvasScalePercentage","shapeList","selectShape","SHAPE_LIST","lineList","selectLine","LINE_LIST","chartList","selectChart","isCustom","customRow","customCol","close","insertCustomTable","handleClickTable","ShapePool","LinePool","ChartPool","TableGenerator","setThumbnailsFocus","scroll","scrollSensitivity","handleDragEnd","itemKey","changSlideIndex","fillDigit","contextmenusThumbnailItem","contextmenusThumbnails","strokeWidth","StaticTable","BaseImageElement","BaseTextElement","BaseShapeElement","BaseLineElement","BaseChartElement","BaseTableElement","ThumbnailElement","Draggable","ThumbnailSlide","eventData","newIndex","oldIndex","_slides","_slide","currentTabs","tab","setToolbarState","currentPanelComponent","ToolbarStates","EL_ANIMATION","EL_STYLE","EL_POSITION","SLIDE_STYLE","SLIDE_ANIMATION","MULTI_POSITION","presetStyles","emitBatchRichTextCommand","compact","richTextAttrs","emitRichTextCommand","suffixIcon","webFonts","fontSizeOptions","updateFill","checked","button-style","lineHeight","updateLineHeight","lineHeightOptions","wordSpace","updateWordSpace","wordSpaceOptions","updateOpacity","undefined","deep","fixed","hasOutline","toggleOutline","updateOutline","ColorButton","outlineProps","hasShadow","toggleShadow","updateShadow","shadowProps","ElementOpacity","ElementShadow","updateRichTextAttrs","clipImage","clipPanelVisible","shapeClipPathOptions","presetImageClip","ratioClipOptions","ratio","filterOptions","updateFilter","unit","replaceImage","resetImage","setBackgroundImage","updateFlip","defaultFilters","ElementFlip","originFilters","getImageElementDataBeforeClip","imgLeft","imgTop","originClipRange","originHeight","originLeft","originTop","imageRatio","distance","fillType","updateFillType","updateGradient","gradientProps","updateLine","chartDataEditorVisible","updateOptions","showArea","showLine","lineSmooth","horizontalBars","donut","footer","centered","closable","destroyOnClose","updateData","rangeLines","resizablePointStyle","changeSelectRange","autocomplete","closeEditor","getTableData","CELL_WIDTH","CELL_HEIGHT","tempRangeSize","initData","_data","rowCount","colCount","inputRef","labelsItem","labelInputRef","seriesItem","valueInputRef","ChartDataEditor","_lineSmooth","_showLine","_showArea","_horizontalBars","_donut","optionProps","newOptions","textAttrs","updateTextAttrs","en","zh","minRowCount","setTableRow","minColCount","setTableCol","hasTheme","toggleTheme","updateTextAttrState","selectedCell","textAttrProp","themeProp","currentTheme","newTableCells","newColSizeList","panelMap","TextStylePanel","ImageStylePanel","ShapeStylePanel","LineStylePanel","ChartStylePanel","TableStylePanel","updateLeft","updateTop","updateWidth","updateFixedRatio","disabled","updateHeight","updateRotate45","updateRotate","_rotate","animationPoolVisible","hoverPreviewAnimation","addAnimation","handleElementAnimation","animationSequence","elType","animationType","runAnimation","deleteAnimation","ANIMATIONS","animationTypes","prefix","elRef","animationName","classList","handleAnimationEnd","once","updateElementAnimation","duration","updateBackgroundType","updateBackground","uploadBackgroundImage","applyBackgroundAllSlide","themes","applyThemeAllSlide","PRESET_THEMES","newBackground","newSlides","currentTurningMode","updateTurningMode","applyAllSlide","turningMode","alignActiveElement","canCombine","firstGroupId","inSameGroup","groupElementRangeMap","activeElement","groupElements","horizontalCenter","center","verticalCenter","elementTabs","slideTabs","multiSelectTabs","currentTabsValue","ElementStylePanel","ElementPositionPanel","ElementAnimationPanel","SlideStylePanel","SlideAnimationPanel","MultiPositionPanel","EditorHeader","Canvas","CanvasTool","Thumbnails","Toolbar","useGlobalHotkey","usePasteEvent","mousewheelListener","animationIndex","slideThumbnailModelVisible","turnSlideToIndex","execPrev","execNext","writingBoardToolVisible","ScreenChartElement","needWaitAnimation","ScreenElement","writingBoardVisible","writingBoardColor","model","writingBoardModel","changePen","changeEraser","clearCanvas","closeWritingBoard","writingBoardColors","changeColor","handleMousedown","handleMousemove","mouseInCanvas","penSize","rubberSize","writingBoardRef","lastPos","lastTime","lastLineWidth","mouse","updateMousePosition","initCanvas","lineCap","lineJoin","draw","posX","posY","lineWidth","lastPosX","lastPosY","strokeStyle","beginPath","moveTo","lineTo","closePath","erase","sinRadius","cosRadius","rectPoint1","rectPoint2","rectPoint3","rectPoint4","save","arc","restore","Date","getTime","getDistance","getLineWidth","maxV","minV","maxWidth","time","WritingBoard","ScreenSlide","SlideThumbnails","WritingBoardTool","slideWidth","slideHeight","setSlideContentSize","winWidth","winHeight","windowResizeListener","lastIndex","SPACE","turnPrevSlide","turnNextSlide","Editor","Screen","removeContextmenu","menus","handleClickMenuItem","menu","MenuContent","MENU_WIDTH","MENU_HEIGHT","DIVIDER_HEIGHT","PADDING","menuCount","dividerCount","menuWidth","menuHeight","screenWidth","screenHeight","CTX_CONTEXTMENU_HANDLER","event","binding","vm","Contextmenu","ContextmenuDirective","mounted","unmounted","CTX_CLICK_OUTSIDE_HANDLER","clickListener","composedPath","isClickOutside","contains","ClickOutsideDirective","install","app","component","accept","handleChange","xmlns","xmlnsXlink","hue","currentColor","themeColors","selectPresetColor","presetColors","standardColors","handleMouseDown","bgStyle","checkboardCache","renderCheckboard","white","grey","fillRect","translate","toDataURL","getCheckboard","checkboard","Checkboard","rgbaStr","alphaRef","containerWidth","xOffset","pageXOffset","unbindEventListeners","pointerLeft","oldHue","pullDirection","hueRef","percent","bgColor","hsva","toHsv","pointerTop","emitChangeEvent","param","saturationRef","containerHeight","yOffset","pageYOffset","saturation","bright","val","_hex","toHex8String","toHexString","presetColorConfig","startColor","endColor","_startColor","_endColor","rStep","gStep","bStep","gradientColorArr","Alpha","Hue","Saturation","EditableInput","rgbaString","colorString","App","directive","use","FileInput","SvgWrapper","CheckboxButton","CheckboxButtonGroup","ColorPicker","Group","Option","OptGroup","Button","Item","mount"],"mappings":"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,QAAS,IACTC,KAAM,gFAER,CACED,QAAS,IACTC,KAAM,oHAER,CACED,QAAS,IACTC,KAAM,uDAER,CACED,QAAS,IACTC,KAAM,0DAER,CACED,QAAS,IACTC,KAAM,uEAER,CACED,QAAS,IACTC,KAAM,kEAER,CACED,QAAS,IACTC,KAAM,+CAER,CACED,QAAS,IACTC,KAAM,6CAER,CACED,QAAS,IACTC,KAAM,6CAER,CACED,QAAS,IACTC,KAAM,oHAER,CACED,QAAS,IACTC,KAAM,6DAER,CACED,QAAS,IACTC,KAAM,wEAER,CACED,QAAS,IACTC,KAAM,iEAER,CACED,QAAS,IACTC,KAAM,oHAER,CACED,QAAS,IACTC,KAAM,sHAER,CACED,QAAS,IACTC,KAAM,uEAER,CACED,QAAS,IACTC,KAAM,oIAER,CACED,QAAS,IACTC,KAAM,qEAER,CACED,QAAS,IACTC,KAAM,+CAKZ,CACEnI,KAAM,KACNoC,SAAU,CACR,CACE8F,QAAS,IACTC,KAAM,6EAER,CACED,QAAS,IACTC,KAAM,6EAER,CACED,QAAS,IACTC,KAAM,6EAER,CACED,QAAS,IACTC,KAAM,6EAER,CACED,QAAS,IACTC,KAAM,qGAER,CACED,QAAS,IACTC,KAAM,qGAER,CACED,QAAS,IACTC,KAAM,qOAER,CACED,QAAS,IACTC,KAAM,uFAER,CACED,QAAS,IACTC,KAAM,sFAER,CACED,QAAS,IACTC,KAAM,8GAER,CACED,QAAS,IACTC,KAAM,8GAER,CACED,QAAS,IACTC,KAAM,8DAER,CACED,QAAS,IACTC,KAAM,gEAER,CACED,QAAS,IACTC,KAAM,6DAER,CACED,QAAS,IACTC,KAAM,gEAER,CACED,QAAS,IACTC,KAAM,4CAER,CACED,QAAS,IACTC,KAAM,iDAER,CACED,QAAS,IACTC,KAAM,6DAER,CACED,QAAS,IACTC,KAAM,kEAER,CACED,QAAS,IACTC,KAAM,6FAER,CACED,QAAS,IACTC,KAAM,yFAER,CACED,QAAS,IACTC,KAAM,0HAER,CACED,QAAS,KACTC,KAAM,+IAER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","file":"js/app.d718d7f2.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"app\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([0,\"chunk-vendors\"]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ColorButton.vue?vue&type=style&index=0&id=39016b60&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ScreenChartElement.vue?vue&type=style&index=0&id=1423f8c2&lang=scss&scoped=true\"","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=4dd87e36&lang=scss&scoped=true\"","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImageEllipseOutline.vue?vue&type=style&index=0&id=6655f0f0&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Chart.vue?vue&type=style&index=1&id=561c26d2&lang=scss\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./StaticTable.vue?vue&type=style&index=0&id=01f791ba&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImageStylePanel.vue?vue&type=style&index=0&id=5685b9e0&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=0214a634&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MouseSelection.vue?vue&type=style&index=0&id=1619c258&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseShapeElement.vue?vue&type=style&index=0&id=d0a0fd1c&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=c0edfdac&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=1c5800c2&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=58592d51&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ShapePool.vue?vue&type=style&index=0&id=5aabd717&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=58d77c92&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=2fd38bde&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./EditableInput.vue?vue&type=style&index=0&id=0311fdee&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseChartElement.vue?vue&type=style&index=0&id=b4562eca&lang=scss&scoped=true\"","var map = {\n\t\"./af\": \"2bfb\",\n\t\"./af.js\": \"2bfb\",\n\t\"./ar\": \"8e73\",\n\t\"./ar-dz\": \"a356\",\n\t\"./ar-dz.js\": \"a356\",\n\t\"./ar-kw\": \"423e\",\n\t\"./ar-kw.js\": \"423e\",\n\t\"./ar-ly\": \"1cfd\",\n\t\"./ar-ly.js\": \"1cfd\",\n\t\"./ar-ma\": \"0a84\",\n\t\"./ar-ma.js\": \"0a84\",\n\t\"./ar-sa\": \"8230\",\n\t\"./ar-sa.js\": \"8230\",\n\t\"./ar-tn\": \"6d83\",\n\t\"./ar-tn.js\": \"6d83\",\n\t\"./ar.js\": \"8e73\",\n\t\"./az\": \"485c\",\n\t\"./az.js\": \"485c\",\n\t\"./be\": \"1fc1\",\n\t\"./be.js\": \"1fc1\",\n\t\"./bg\": \"84aa\",\n\t\"./bg.js\": \"84aa\",\n\t\"./bm\": \"a7fa\",\n\t\"./bm.js\": \"a7fa\",\n\t\"./bn\": \"9043\",\n\t\"./bn-bd\": \"9686\",\n\t\"./bn-bd.js\": \"9686\",\n\t\"./bn.js\": \"9043\",\n\t\"./bo\": \"d26a\",\n\t\"./bo.js\": \"d26a\",\n\t\"./br\": \"6887\",\n\t\"./br.js\": \"6887\",\n\t\"./bs\": \"2554\",\n\t\"./bs.js\": \"2554\",\n\t\"./ca\": \"d716\",\n\t\"./ca.js\": \"d716\",\n\t\"./cs\": \"3c0d\",\n\t\"./cs.js\": \"3c0d\",\n\t\"./cv\": \"03ec\",\n\t\"./cv.js\": \"03ec\",\n\t\"./cy\": \"9797\",\n\t\"./cy.js\": \"9797\",\n\t\"./da\": \"0f14\",\n\t\"./da.js\": \"0f14\",\n\t\"./de\": \"b469\",\n\t\"./de-at\": \"b3eb\",\n\t\"./de-at.js\": \"b3eb\",\n\t\"./de-ch\": \"bb71\",\n\t\"./de-ch.js\": \"bb71\",\n\t\"./de.js\": \"b469\",\n\t\"./dv\": \"598a\",\n\t\"./dv.js\": \"598a\",\n\t\"./el\": \"8d47\",\n\t\"./el.js\": \"8d47\",\n\t\"./en-au\": \"0e6b\",\n\t\"./en-au.js\": \"0e6b\",\n\t\"./en-ca\": \"3886\",\n\t\"./en-ca.js\": \"3886\",\n\t\"./en-gb\": \"39a6\",\n\t\"./en-gb.js\": \"39a6\",\n\t\"./en-ie\": \"e1d3\",\n\t\"./en-ie.js\": \"e1d3\",\n\t\"./en-il\": \"7333\",\n\t\"./en-il.js\": \"7333\",\n\t\"./en-in\": \"ec2e\",\n\t\"./en-in.js\": \"ec2e\",\n\t\"./en-nz\": \"6f50\",\n\t\"./en-nz.js\": \"6f50\",\n\t\"./en-sg\": \"b7e9\",\n\t\"./en-sg.js\": \"b7e9\",\n\t\"./eo\": \"65db\",\n\t\"./eo.js\": \"65db\",\n\t\"./es\": \"898b\",\n\t\"./es-do\": \"0a3c\",\n\t\"./es-do.js\": \"0a3c\",\n\t\"./es-mx\": \"b5b7\",\n\t\"./es-mx.js\": \"b5b7\",\n\t\"./es-us\": \"55c9\",\n\t\"./es-us.js\": \"55c9\",\n\t\"./es.js\": \"898b\",\n\t\"./et\": \"ec18\",\n\t\"./et.js\": \"ec18\",\n\t\"./eu\": \"0ff2\",\n\t\"./eu.js\": \"0ff2\",\n\t\"./fa\": \"8df4\",\n\t\"./fa.js\": \"8df4\",\n\t\"./fi\": \"81e9\",\n\t\"./fi.js\": \"81e9\",\n\t\"./fil\": \"d69a\",\n\t\"./fil.js\": \"d69a\",\n\t\"./fo\": \"0721\",\n\t\"./fo.js\": \"0721\",\n\t\"./fr\": \"9f26\",\n\t\"./fr-ca\": \"d9f8\",\n\t\"./fr-ca.js\": \"d9f8\",\n\t\"./fr-ch\": \"0e49\",\n\t\"./fr-ch.js\": \"0e49\",\n\t\"./fr.js\": \"9f26\",\n\t\"./fy\": \"7118\",\n\t\"./fy.js\": \"7118\",\n\t\"./ga\": \"5120\",\n\t\"./ga.js\": \"5120\",\n\t\"./gd\": \"f6b4\",\n\t\"./gd.js\": \"f6b4\",\n\t\"./gl\": \"8840\",\n\t\"./gl.js\": \"8840\",\n\t\"./gom-deva\": \"aaf2\",\n\t\"./gom-deva.js\": \"aaf2\",\n\t\"./gom-latn\": \"0caa\",\n\t\"./gom-latn.js\": \"0caa\",\n\t\"./gu\": \"e0c5\",\n\t\"./gu.js\": \"e0c5\",\n\t\"./he\": \"c7aa\",\n\t\"./he.js\": \"c7aa\",\n\t\"./hi\": \"dc4d\",\n\t\"./hi.js\": \"dc4d\",\n\t\"./hr\": \"4ba9\",\n\t\"./hr.js\": \"4ba9\",\n\t\"./hu\": \"5b14\",\n\t\"./hu.js\": \"5b14\",\n\t\"./hy-am\": \"d6b6\",\n\t\"./hy-am.js\": \"d6b6\",\n\t\"./id\": \"5038\",\n\t\"./id.js\": \"5038\",\n\t\"./is\": \"0558\",\n\t\"./is.js\": \"0558\",\n\t\"./it\": \"6e98\",\n\t\"./it-ch\": \"6f12\",\n\t\"./it-ch.js\": \"6f12\",\n\t\"./it.js\": \"6e98\",\n\t\"./ja\": \"079e\",\n\t\"./ja.js\": \"079e\",\n\t\"./jv\": \"b540\",\n\t\"./jv.js\": \"b540\",\n\t\"./ka\": \"201b\",\n\t\"./ka.js\": \"201b\",\n\t\"./kk\": \"6d79\",\n\t\"./kk.js\": \"6d79\",\n\t\"./km\": \"e81d\",\n\t\"./km.js\": \"e81d\",\n\t\"./kn\": \"3e92\",\n\t\"./kn.js\": \"3e92\",\n\t\"./ko\": \"22f8\",\n\t\"./ko.js\": \"22f8\",\n\t\"./ku\": \"2421\",\n\t\"./ku.js\": \"2421\",\n\t\"./ky\": \"9609\",\n\t\"./ky.js\": \"9609\",\n\t\"./lb\": \"440c\",\n\t\"./lb.js\": \"440c\",\n\t\"./lo\": \"b29d\",\n\t\"./lo.js\": \"b29d\",\n\t\"./lt\": \"26f9\",\n\t\"./lt.js\": \"26f9\",\n\t\"./lv\": \"b97c\",\n\t\"./lv.js\": \"b97c\",\n\t\"./me\": \"293c\",\n\t\"./me.js\": \"293c\",\n\t\"./mi\": \"688b\",\n\t\"./mi.js\": \"688b\",\n\t\"./mk\": \"6909\",\n\t\"./mk.js\": \"6909\",\n\t\"./ml\": \"02fb\",\n\t\"./ml.js\": \"02fb\",\n\t\"./mn\": \"958b\",\n\t\"./mn.js\": \"958b\",\n\t\"./mr\": \"39bd\",\n\t\"./mr.js\": \"39bd\",\n\t\"./ms\": \"ebe4\",\n\t\"./ms-my\": \"6403\",\n\t\"./ms-my.js\": \"6403\",\n\t\"./ms.js\": \"ebe4\",\n\t\"./mt\": \"1b45\",\n\t\"./mt.js\": \"1b45\",\n\t\"./my\": \"8689\",\n\t\"./my.js\": \"8689\",\n\t\"./nb\": \"6ce3\",\n\t\"./nb.js\": \"6ce3\",\n\t\"./ne\": \"3a39\",\n\t\"./ne.js\": \"3a39\",\n\t\"./nl\": \"facd\",\n\t\"./nl-be\": \"db29\",\n\t\"./nl-be.js\": \"db29\",\n\t\"./nl.js\": \"facd\",\n\t\"./nn\": \"b84c\",\n\t\"./nn.js\": \"b84c\",\n\t\"./oc-lnc\": \"167b\",\n\t\"./oc-lnc.js\": \"167b\",\n\t\"./pa-in\": \"f3ff\",\n\t\"./pa-in.js\": \"f3ff\",\n\t\"./pl\": \"8d57\",\n\t\"./pl.js\": \"8d57\",\n\t\"./pt\": \"f260\",\n\t\"./pt-br\": \"d2d4\",\n\t\"./pt-br.js\": \"d2d4\",\n\t\"./pt.js\": \"f260\",\n\t\"./ro\": \"972c\",\n\t\"./ro.js\": \"972c\",\n\t\"./ru\": \"957c\",\n\t\"./ru.js\": \"957c\",\n\t\"./sd\": \"6784\",\n\t\"./sd.js\": \"6784\",\n\t\"./se\": \"ffff\",\n\t\"./se.js\": \"ffff\",\n\t\"./si\": \"eda5\",\n\t\"./si.js\": \"eda5\",\n\t\"./sk\": \"7be6\",\n\t\"./sk.js\": \"7be6\",\n\t\"./sl\": \"8155\",\n\t\"./sl.js\": \"8155\",\n\t\"./sq\": \"c8f3\",\n\t\"./sq.js\": \"c8f3\",\n\t\"./sr\": \"cf1e\",\n\t\"./sr-cyrl\": \"13e9\",\n\t\"./sr-cyrl.js\": \"13e9\",\n\t\"./sr.js\": \"cf1e\",\n\t\"./ss\": \"52bd\",\n\t\"./ss.js\": \"52bd\",\n\t\"./sv\": \"5fbd\",\n\t\"./sv.js\": \"5fbd\",\n\t\"./sw\": \"74dc\",\n\t\"./sw.js\": \"74dc\",\n\t\"./ta\": \"3de5\",\n\t\"./ta.js\": \"3de5\",\n\t\"./te\": \"5cbb\",\n\t\"./te.js\": \"5cbb\",\n\t\"./tet\": \"576c\",\n\t\"./tet.js\": \"576c\",\n\t\"./tg\": \"3b1b\",\n\t\"./tg.js\": \"3b1b\",\n\t\"./th\": \"10e8\",\n\t\"./th.js\": \"10e8\",\n\t\"./tk\": \"5aff\",\n\t\"./tk.js\": \"5aff\",\n\t\"./tl-ph\": \"0f38\",\n\t\"./tl-ph.js\": \"0f38\",\n\t\"./tlh\": \"cf75\",\n\t\"./tlh.js\": \"cf75\",\n\t\"./tr\": \"0e81\",\n\t\"./tr.js\": \"0e81\",\n\t\"./tzl\": \"cf51\",\n\t\"./tzl.js\": \"cf51\",\n\t\"./tzm\": \"c109\",\n\t\"./tzm-latn\": \"b53d\",\n\t\"./tzm-latn.js\": \"b53d\",\n\t\"./tzm.js\": \"c109\",\n\t\"./ug-cn\": \"6117\",\n\t\"./ug-cn.js\": \"6117\",\n\t\"./uk\": \"ada2\",\n\t\"./uk.js\": \"ada2\",\n\t\"./ur\": \"5294\",\n\t\"./ur.js\": \"5294\",\n\t\"./uz\": \"2e8c\",\n\t\"./uz-latn\": \"010e\",\n\t\"./uz-latn.js\": \"010e\",\n\t\"./uz.js\": \"2e8c\",\n\t\"./vi\": \"2921\",\n\t\"./vi.js\": \"2921\",\n\t\"./x-pseudo\": \"fd7e\",\n\t\"./x-pseudo.js\": \"fd7e\",\n\t\"./yo\": \"7f33\",\n\t\"./yo.js\": \"7f33\",\n\t\"./zh-cn\": \"5c3a\",\n\t\"./zh-cn.js\": \"5c3a\",\n\t\"./zh-hk\": \"49ab\",\n\t\"./zh-hk.js\": \"49ab\",\n\t\"./zh-mo\": \"3a6c\",\n\t\"./zh-mo.js\": \"3a6c\",\n\t\"./zh-tw\": \"90ea\",\n\t\"./zh-tw.js\": \"90ea\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"4678\";","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./WritingBoardTool.vue?vue&type=style&index=0&id=0bfb345d&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Saturation.vue?vue&type=style&index=0&id=5310dbb4&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=a0860bd0&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./GridLines.vue?vue&type=style&index=0&id=5664d2b2&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./SlideAnimationPanel.vue?vue&type=style&index=0&id=6e3028f1&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=23ee4d75&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=3f17bdc9&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MenuContent.vue?vue&type=style&index=0&id=d08042ec&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=5e75c7ca&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./TableStylePanel.vue?vue&type=style&index=0&id=90d47588&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImageElementOperate.vue?vue&type=style&index=0&id=5b0628aa&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Alpha.vue?vue&type=style&index=0&id=ecf7d10e&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Checkboard.vue?vue&type=style&index=0&id=e9a0ac98&lang=scss&scoped=true\"","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImagePolygonOutline.vue?vue&type=style&index=0&id=8d85e878&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementOpacity.vue?vue&type=style&index=0&id=b884607e&lang=scss&scoped=true\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CheckboxButtonGroup.vue?vue&type=style&index=0&id=7dafd0a9&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImageClipHandler.vue?vue&type=style&index=0&id=1d9b5032&lang=scss&scoped=true\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./WritingBoard.vue?vue&type=style&index=0&id=4ddc4b2c&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ShapeStylePanel.vue?vue&type=style&index=0&id=998a7a02&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=236c5f54&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseImageElement.vue?vue&type=style&index=0&id=1285108e&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=7ab5e859&lang=scss&scoped=true\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CheckboxButton.vue?vue&type=style&index=0&id=7cae2b90&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementOutline.vue?vue&type=style&index=0&id=2d8ce9c0&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=71468c62&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./SlideStylePanel.vue?vue&type=style&index=0&id=5069f2f0&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./RotateHandler.vue?vue&type=style&index=0&id=9a549510&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./LineStylePanel.vue?vue&type=style&index=0&id=65b24fb3&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./TextStylePanel.vue?vue&type=style&index=0&id=43fccffc&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=5332dba4&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./AlignmentLine.vue?vue&type=style&index=0&id=2d3eddf5&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=558a94fe&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ScreenSlide.vue?vue&type=style&index=0&id=5e193d56&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./SlideThumbnails.vue?vue&type=style&index=0&id=49960bc8&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementCreateSelection.vue?vue&type=style&index=0&id=97a153b6&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Hue.vue?vue&type=style&index=0&id=7b983451&lang=scss&scoped=true\"","export * from \"-!../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./App.vue?vue&type=style&index=0&id=7fa1c35b&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MultiPositionPanel.vue?vue&type=style&index=0&id=540e3d06&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ResizeHandler.vue?vue&type=style&index=0&id=1c2a68d0&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementFlip.vue?vue&type=style&index=0&id=b6fdb886&lang=scss&scoped=true\"","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ChartDataEditor.vue?vue&type=style&index=0&id=08aba838&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./LinePool.vue?vue&type=style&index=0&id=08f7cf5a&lang=scss&scoped=true\"","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ImageRectOutline.vue?vue&type=style&index=0&id=4126ab7f&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./TableGenerator.vue?vue&type=style&index=0&id=576c614c&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementPositionPanel.vue?vue&type=style&index=0&id=15c9ddcc&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./SlideBackground.vue?vue&type=style&index=0&id=a1052b6c&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseLineElement.vue?vue&type=style&index=0&id=54a876d6&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseTableElement.vue?vue&type=style&index=0&id=dea016ac&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BaseTextElement.vue?vue&type=style&index=0&id=fc2d45e0&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementShadow.vue?vue&type=style&index=0&id=5cca6474&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=5186b40b&lang=scss&scoped=true\"","<template>\r\n <Editor v-if=\"!screening\" />\r\n <Screen v-else />\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onMounted } from 'vue'\r\nimport { MutationTypes, ActionTypes, useStore } from '@/store'\r\n\r\nimport Editor from './views/Editor/index.vue'\r\nimport Screen from './views/Screen/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'app',\r\n components: {\r\n Editor,\r\n Screen,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const screening = computed(() => store.state.screening)\r\n\r\n onMounted(() => {\r\n store.commit(MutationTypes.SET_AVAILABLE_FONTS)\r\n store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)\r\n })\r\n\r\n return {\r\n screening,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n#app {\r\n height: 100%;\r\n}\r\n</style>","export const enum MutationTypes {\r\n\r\n // editor\r\n SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList',\r\n SET_HANDLE_ELEMENT_ID = 'setHandleElementId',\r\n SET_CANVAS_PERCENTAGE = 'setCanvasPercentage',\r\n SET_CANVAS_SCALE = 'setCanvasScale',\r\n SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus',\r\n SET_EDITORAREA_FOCUS = 'setEditorAreaFocus',\r\n SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState',\r\n SET_GRID_LINES_STATE = 'setGridLinesState',\r\n SET_CREATING_ELEMENT = 'setCreatingElement',\r\n SET_AVAILABLE_FONTS = 'setAvailableFonts',\r\n SET_TOOLBAR_STATE = 'setToolbarState',\r\n SET_CLIPING_IMAGE_ELEMENT_ID = 'setClipingImageElementId',\r\n\r\n // slides\r\n SET_THEME = 'setTheme',\r\n SET_SLIDES = 'setSlides',\r\n ADD_SLIDE = 'addSlide',\r\n UPDATE_SLIDE = 'updateSlide',\r\n DELETE_SLIDE = 'deleteSlide',\r\n UPDATE_SLIDE_INDEX = 'updateSlideIndex',\r\n ADD_ELEMENT = 'addElement',\r\n UPDATE_ELEMENT = 'updateElement',\r\n REMOVE_ELEMENT_PROPS = 'removeElementProps',\r\n\r\n // snapshot\r\n SET_SNAPSHOT_CURSOR = 'setSnapshotCursor',\r\n SET_SNAPSHOT_LENGTH = 'setSnapshotLength',\r\n\r\n // keyboard\r\n SET_CTRL_KEY_STATE = 'setCtrlKeyState',\r\n SET_SHIFT_KEY_STATE = 'setShiftKeyState',\r\n\r\n // screen\r\n SET_SCREENING = 'setScreening',\r\n}\r\n\r\nexport const enum ActionTypes {\r\n INIT_SNAPSHOT_DATABASE = 'initSnapshotDatabase',\r\n ADD_SNAPSHOT = 'addSnapshot',\r\n UN_DO = 'undo',\r\n RE_DO = 'redo',\r\n}","import { Slide } from '@/types/slides'\r\n\r\nexport const slides: Slide[] = [\r\n {\r\n id: 'test123456',\r\n elements: [],\r\n },\r\n]","import { Slide, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { ToolbarState } from '@/types/toolbar'\r\nimport { slides } from '@/mocks/index'\r\nimport { SYS_FONTS } from '@/configs/font'\r\n\r\nexport interface State {\r\n activeElementIdList: string[];\r\n handleElementId: string;\r\n canvasPercentage: number;\r\n canvasScale: number;\r\n thumbnailsFocus: boolean;\r\n editorAreaFocus: boolean;\r\n disableHotkeys: boolean;\r\n showGridLines: boolean;\r\n creatingElement: CreatingElement | null;\r\n availableFonts: typeof SYS_FONTS;\r\n toolbarState: ToolbarState;\r\n theme: SlideTheme;\r\n slides: Slide[];\r\n slideIndex: number;\r\n snapshotCursor: number;\r\n snapshotLength: number;\r\n ctrlKeyState: boolean;\r\n shiftKeyState: boolean;\r\n screening: boolean;\r\n clipingImageElementId: string;\r\n}\r\n\r\nexport const state: State = {\r\n activeElementIdList: [],\r\n handleElementId: '',\r\n canvasPercentage: 90,\r\n canvasScale: 1,\r\n thumbnailsFocus: false,\r\n editorAreaFocus: false,\r\n disableHotkeys: false,\r\n showGridLines: false,\r\n creatingElement: null,\r\n availableFonts: [],\r\n toolbarState: 'slideStyle',\r\n theme: {\r\n themeColor: '#d14424',\r\n fontColor: '#333',\r\n fontName: '微软雅黑',\r\n backgroundColor: '#fff',\r\n },\r\n slides: slides,\r\n slideIndex: 0,\r\n snapshotCursor: -1,\r\n snapshotLength: 0,\r\n ctrlKeyState: false,\r\n shiftKeyState: false,\r\n screening: false,\r\n clipingImageElementId: '',\r\n}","import { GetterTree } from 'vuex'\r\nimport { State } from './state'\r\n\r\nexport const getters: GetterTree<State, State> = {\r\n currentSlide(state) {\r\n return state.slides[state.slideIndex] || null\r\n },\r\n\r\n currentSlideAnimations(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if (!currentSlide) return null\r\n const animations = currentSlide.animations\r\n if (!animations) return null\r\n\r\n const els = currentSlide.elements\r\n const elIds = els.map(el => el.id)\r\n return animations.filter(animation => elIds.includes(animation.elId))\r\n },\r\n\r\n activeElementList(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if (!currentSlide || !currentSlide.elements) return []\r\n return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))\r\n },\r\n\r\n handleElement(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if (!currentSlide || !currentSlide.elements) return null\r\n return currentSlide.elements.find(element => state.handleElementId === element.id) || null\r\n },\r\n\r\n canUndo(state) {\r\n return state.snapshotCursor > 0\r\n },\r\n\r\n canRedo(state) {\r\n return state.snapshotCursor < state.snapshotLength - 1\r\n },\r\n\r\n ctrlOrShiftKeyActive(state) {\r\n return state.ctrlKeyState || state.shiftKeyState\r\n },\r\n}","import Dexie from 'dexie'\r\nimport { Slide } from '@/types/slides'\r\n\r\nexport interface Snapshot {\r\n index: number;\r\n slides: Slide[];\r\n}\r\n\r\nclass SnapshotDatabase extends Dexie {\r\n public snapshots: Dexie.Table<Snapshot, number>\r\n\r\n public constructor() {\r\n super('SnapshotDatabase')\r\n this.version(1).stores({\r\n snapshots: '++id'\r\n })\r\n this.snapshots = this.table('snapshots')\r\n }\r\n}\r\n\r\nexport default new SnapshotDatabase()","import { ActionTree } from 'vuex'\r\nimport { IndexableTypeArray } from 'dexie'\r\nimport { State } from './state'\r\nimport { ActionTypes, MutationTypes } from './constants'\r\nimport db, { Snapshot } from '@/utils/database'\r\n\r\nexport const actions: ActionTree<State, State> = {\r\n async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit, state }) {\r\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\r\n const lastSnapshot = snapshots.slice(-1)[0]\r\n\r\n if (lastSnapshot) {\r\n db.snapshots.clear()\r\n }\r\n\r\n const newFirstSnapshot = {\r\n index: state.slideIndex,\r\n slides: state.slides,\r\n }\r\n await db.snapshots.add(newFirstSnapshot)\r\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, 0)\r\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, 1)\r\n },\r\n\r\n async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {\r\n const allKeys = await db.snapshots.orderBy('id').keys()\r\n\r\n let needDeleteKeys: IndexableTypeArray = []\r\n\r\n if (state.snapshotCursor >= 0 && state.snapshotCursor < allKeys.length - 1) {\r\n needDeleteKeys = allKeys.slice(state.snapshotCursor + 1)\r\n }\r\n\r\n const snapshot = {\r\n index: state.slideIndex,\r\n slides: state.slides,\r\n }\r\n await db.snapshots.add(snapshot)\r\n\r\n let snapshotLength = allKeys.length - needDeleteKeys.length + 1\r\n\r\n if (snapshotLength > 20) {\r\n needDeleteKeys.push(allKeys[0])\r\n snapshotLength--\r\n }\r\n if (snapshotLength >= 2) {\r\n db.snapshots.update(allKeys[snapshotLength - 2] as number, { index: state.slideIndex })\r\n }\r\n\r\n await db.snapshots.bulkDelete(needDeleteKeys)\r\n\r\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotLength - 1)\r\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, snapshotLength)\r\n },\r\n\r\n async [ActionTypes.UN_DO]({ state, commit }) {\r\n if (state.snapshotCursor <= 0) return\r\n\r\n const snapshotCursor = state.snapshotCursor - 1\r\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\r\n const snapshot = snapshots[snapshotCursor]\r\n const { index, slides } = snapshot\r\n\r\n commit(MutationTypes.SET_SLIDES, slides)\r\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\r\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n },\r\n\r\n async [ActionTypes.RE_DO]({ state, commit }) {\r\n if (state.snapshotCursor >= state.snapshotLength - 1) return\r\n\r\n const snapshotCursor = state.snapshotCursor + 1\r\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\r\n const snapshot = snapshots[snapshotCursor]\r\n const { index, slides } = snapshot\r\n\r\n commit(MutationTypes.SET_SLIDES, slides)\r\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\r\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n },\r\n}","export const SYS_FONTS = [\r\n { label: 'Arial', value: 'Arial' },\r\n { label: '微软雅黑', value: 'Microsoft Yahei' },\r\n { label: '宋体', value: 'SimSun' },\r\n { label: '黑体', value: 'SimHei' },\r\n { label: '楷体', value: 'KaiTi' },\r\n { label: '新宋体', value: 'NSimSun' },\r\n { label: '仿宋', value: 'FangSong' },\r\n { label: '苹方', value: 'PingFang SC' },\r\n { label: '华文黑体', value: 'STHeiti' },\r\n { label: '华文楷体', value: 'STKaiti' },\r\n { label: '华文宋体', value: 'STSong' },\r\n { label: '华文仿宋', value: 'STFangSong' },\r\n { label: '华文中宋', value: 'STZhongSong' },\r\n { label: '华文琥珀', value: 'STHupo' },\r\n { label: '华文新魏', value: 'STXinwei' },\r\n { label: '华文隶书', value: 'STLiti' },\r\n { label: '华文行楷', value: 'STXingkai' },\r\n { label: '冬青黑体', value: 'Hiragino Sans GB' },\r\n { label: '兰亭黑', value: 'Lantinghei SC' },\r\n { label: '偏偏体', value: 'Hanzipen SC' },\r\n { label: '手札体', value: 'Hannotate SC' },\r\n { label: '宋体', value: 'Songti SC' },\r\n { label: '娃娃体', value: 'Wawati SC' },\r\n { label: '行楷', value: 'Xingkai SC' },\r\n { label: '圆体', value: 'Yuanti SC' },\r\n { label: '华文细黑', value: 'STXihei' },\r\n { label: '幼圆', value: 'YouYuan' },\r\n { label: '隶书', value: 'LiSu' },\r\n]\r\n\r\nexport const WEB_FONTS = [\r\n { label: '仓耳小丸子', value: '仓耳小丸子' },\r\n { label: '优设标题黑', value: '优设标题黑' },\r\n { label: '峰广明锐体', value: '峰广明锐体' },\r\n { label: '摄图摩登小方体', value: '摄图摩登小方体' },\r\n { label: '站酷快乐体', value: '站酷快乐体' },\r\n { label: '站酷酷黑体', value: '站酷酷黑体' },\r\n { label: '素材集市康康体', value: '素材集市康康体' },\r\n { label: '联盟起艺卢帅正锐黑体', value: '联盟起艺卢帅正锐黑体' },\r\n { label: '谦度手写楷体', value: '谦度手写楷体' },\r\n { label: '途牛类圆体', value: '途牛类圆体' },\r\n { label: '锐字真言体', value: '锐字真言体' },\r\n { label: '问藏书房', value: '问藏书房' },\r\n]","/**\r\n * 判断操作系统是否存在某字体\r\n * @param fontFamily 字体名\r\n */\r\nexport const isSupportFontFamily = (fontFamily: string) => {\r\n if (typeof fontFamily !== 'string') return false\r\n\r\n const arial = 'Arial'\r\n if (fontFamily.toLowerCase() === arial.toLowerCase()) return true\r\n\r\n const size = 100\r\n const width = 100\r\n const height = 100\r\n const str = 'a'\r\n\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d')\r\n\r\n if (!ctx) return false\r\n\r\n canvas.width = width\r\n canvas.height = height\r\n ctx.textAlign = 'center'\r\n ctx.fillStyle = 'black'\r\n ctx.textBaseline = 'middle'\r\n\r\n const getDotArray = (_fontFamily: string) => {\r\n ctx.clearRect(0, 0, width, height)\r\n ctx.font = `${size}px ${_fontFamily}, ${arial}`\r\n ctx.fillText(str, width / 2, height / 2)\r\n const imageData = ctx.getImageData(0, 0, width, height).data\r\n return [].slice.call(imageData).filter(item => item !== 0)\r\n }\r\n\r\n return getDotArray(arial).join('') !== getDotArray(fontFamily).join('')\r\n}","import { MutationTree } from 'vuex'\r\nimport omit from 'lodash/omit'\r\nimport { MutationTypes } from './constants'\r\nimport { State } from './state'\r\nimport { Slide, PPTElement, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { SYS_FONTS } from '@/configs/font'\r\nimport { isSupportFontFamily } from '@/utils/fontFamily'\r\n\r\ninterface RemoveElementPropData {\r\n id: string;\r\n propName: string | string[];\r\n}\r\n\r\ninterface UpdateElementData {\r\n id: string | string[];\r\n props: Partial<PPTElement>;\r\n}\r\n\r\nexport const mutations: MutationTree<State> = {\r\n\r\n // editor\r\n\r\n [MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST](state, activeElementIdList: string[]) {\r\n if (activeElementIdList.length === 1) state.handleElementId = activeElementIdList[0]\r\n else state.handleElementId = ''\r\n \r\n state.activeElementIdList = activeElementIdList\r\n },\r\n \r\n [MutationTypes.SET_HANDLE_ELEMENT_ID](state, handleElementId: string) {\r\n state.handleElementId = handleElementId\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_PERCENTAGE](state, percentage: number) {\r\n state.canvasPercentage = percentage\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_SCALE](state, scale: number) {\r\n state.canvasScale = scale\r\n },\r\n\r\n [MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) {\r\n state.thumbnailsFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_EDITORAREA_FOCUS](state, isFocus: boolean) {\r\n state.editorAreaFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_DISABLE_HOTKEYS_STATE](state, disable: boolean) {\r\n state.disableHotkeys = disable\r\n },\r\n\r\n [MutationTypes.SET_GRID_LINES_STATE](state, show: boolean) {\r\n state.showGridLines = show\r\n },\r\n\r\n [MutationTypes.SET_CREATING_ELEMENT](state, element: CreatingElement | null) {\r\n state.creatingElement = element\r\n },\r\n\r\n [MutationTypes.SET_AVAILABLE_FONTS](state) {\r\n state.availableFonts = SYS_FONTS.filter(font => isSupportFontFamily(font.value))\r\n },\r\n\r\n [MutationTypes.SET_TOOLBAR_STATE](state, type) {\r\n state.toolbarState = type\r\n },\r\n\r\n [MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID](state, elId) {\r\n state.clipingImageElementId = elId\r\n },\r\n\r\n // slides\r\n\r\n [MutationTypes.SET_THEME](state, themeProps: Partial<SlideTheme>) {\r\n state.theme = { ...state.theme, ...themeProps }\r\n },\r\n\r\n [MutationTypes.SET_SLIDES](state, slides: Slide[]) {\r\n state.slides = slides\r\n },\r\n\r\n [MutationTypes.ADD_SLIDE](state, slide: Slide) {\r\n const addIndex = state.slideIndex + 1\r\n state.slides.splice(addIndex, 0, slide)\r\n state.slideIndex = addIndex\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE](state, props: Partial<Slide>) {\r\n const slideIndex = state.slideIndex\r\n state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }\r\n },\r\n\r\n [MutationTypes.DELETE_SLIDE](state, slideId: string) {\r\n const deleteIndex = state.slides.findIndex(item => item.id === slideId)\r\n\r\n if (deleteIndex === state.slides.length - 1) {\r\n state.slideIndex = deleteIndex - 1\r\n }\r\n state.slides.splice(deleteIndex, 1)\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE_INDEX](state, index: number) {\r\n state.slideIndex = index\r\n },\r\n\r\n [MutationTypes.ADD_ELEMENT](state, element: PPTElement | PPTElement[]) {\r\n const elements = Array.isArray(element) ? element : [element]\r\n const currentSlideEls = state.slides[state.slideIndex].elements\r\n const newEls = [...currentSlideEls, ...elements]\r\n state.slides[state.slideIndex].elements = newEls\r\n },\r\n\r\n [MutationTypes.UPDATE_ELEMENT](state, data: UpdateElementData) {\r\n const { id, props } = data\r\n const elIdList = typeof id === 'string' ? [id] : id\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return elIdList.includes(el.id) ? { ...el, ...props } : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n [MutationTypes.REMOVE_ELEMENT_PROPS](state, data: RemoveElementPropData) {\r\n const { id, propName } = data\r\n const propsNames = typeof propName === 'string' ? [propName] : propName\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return el.id === id ? omit(el, propsNames) : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n // snapshot\r\n\r\n [MutationTypes.SET_SNAPSHOT_CURSOR](state, cursor: number) {\r\n state.snapshotCursor = cursor\r\n },\r\n\r\n [MutationTypes.SET_SNAPSHOT_LENGTH](state, length: number) {\r\n state.snapshotLength = length\r\n },\r\n\r\n // keyboard\r\n\r\n [MutationTypes.SET_CTRL_KEY_STATE](state, isActive: boolean) {\r\n state.ctrlKeyState = isActive\r\n },\r\n [MutationTypes.SET_SHIFT_KEY_STATE](state, isActive: boolean) {\r\n state.shiftKeyState = isActive\r\n },\r\n\r\n // screen\r\n\r\n [MutationTypes.SET_SCREENING](state, screening) {\r\n state.screening = screening\r\n },\r\n}","import { InjectionKey } from 'vue'\r\nimport { createStore, Store, useStore as baseUseStore } from 'vuex'\r\nimport { state, State } from './state'\r\nimport { getters } from './getters'\r\nimport { actions } from './actions'\r\nimport { mutations } from './mutations'\r\nimport { MutationTypes, ActionTypes } from './constants'\r\n\r\nexport { MutationTypes, ActionTypes }\r\n\r\nexport const key: InjectionKey<Store<State>> = Symbol()\r\n\r\nexport const store = createStore<State>({\r\n state,\r\n getters,\r\n mutations,\r\n actions,\r\n})\r\n\r\nexport const useStore = () => baseUseStore(key)","<template>\r\n <div class=\"hamster-ppt-editor\">\r\n <EditorHeader class=\"layout-header\" />\r\n <div class=\"layout-content\">\r\n <Thumbnails class=\"layout-content-left\" />\r\n <div class=\"layout-content-center\">\r\n <CanvasTool class=\"center-top\" />\r\n <Canvas class=\"center-body\" />\r\n </div>\r\n <Toolbar class=\"layout-content-right\" />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent } from 'vue'\r\n\r\nimport useGlobalHotkey from '@/hooks/useGlobalHotkey'\r\nimport usePasteEvent from '@/hooks/usePasteEvent'\r\n\r\nimport EditorHeader from './EditorHeader/index.vue'\r\nimport Canvas from './Canvas/index.vue'\r\nimport CanvasTool from './CanvasTool/index.vue'\r\nimport Thumbnails from './Thumbnails/index.vue'\r\nimport Toolbar from './Toolbar/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor',\r\n components: {\r\n EditorHeader,\r\n Canvas,\r\n CanvasTool,\r\n Thumbnails,\r\n Toolbar,\r\n },\r\n setup() {\r\n useGlobalHotkey()\r\n usePasteEvent()\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.hamster-ppt-editor {\r\n height: 100%;\r\n}\r\n.layout-header {\r\n height: 40px;\r\n}\r\n.layout-content {\r\n height: calc(100% - 40px);\r\n display: flex;\r\n}\r\n.layout-content-left {\r\n width: 160px;\r\n height: 100%;\r\n flex-shrink: 0;\r\n}\r\n.layout-content-center {\r\n width: calc(100% - 160px - 260px);\r\n\r\n .center-top {\r\n height: 40px;\r\n }\r\n .center-body {\r\n height: calc(100% - 40px);\r\n }\r\n}\r\n.layout-content-right {\r\n width: 260px;\r\n height: 100%;\r\n}\r\n</style>","import { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\n\r\nexport type ElementOrderCommand = 'up' | 'down' | 'top' | 'bottom'\r\n\r\nexport const enum ElementOrderCommands {\r\n UP = 'up',\r\n DOWN = 'down',\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n}\r\n\r\nexport type ElementAlignCommand = 'top'| 'bottom' | 'left' | 'right' | 'vertical' | 'horizontal' | 'center'\r\n\r\nexport const enum ElementAlignCommands {\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n VERTICAL = 'vertical',\r\n HORIZONTAL = 'horizontal',\r\n CENTER = 'center',\r\n}\r\n\r\nexport type OperateBorderLine = 'top' | 'bottom' | 'left' | 'right'\r\n\r\nexport const enum OperateBorderLines {\r\n T = 'top',\r\n B = 'bottom',\r\n L = 'left',\r\n R = 'right',\r\n}\r\n\r\nexport type OperateResizeHandler = '' | 'left-top' | 'top' | 'right-top' | 'left' | 'right' | 'left-bottom' | 'bottom' | 'right-bottom'\r\n\r\nexport const enum OperateResizeHandlers {\r\n LEFT_TOP = 'left-top',\r\n TOP = 'top',\r\n RIGHT_TOP = 'right-top',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n LEFT_BOTTOM = 'left-bottom',\r\n BOTTOM = 'bottom',\r\n RIGHT_BOTTOM = 'right-bottom',\r\n}\r\n\r\nexport type OperateLineHandler = 'start' | 'end'\r\n\r\nexport const enum OperateLineHandlers {\r\n START = 'start',\r\n END = 'end,'\r\n}\r\n\r\nexport interface AlignmentLineAxis {\r\n x: number; \r\n y: number;\r\n}\r\n\r\nexport interface AlignmentLineProps {\r\n type: 'vertical' | 'horizontal';\r\n axis: AlignmentLineAxis;\r\n length: number;\r\n}\r\n\r\nexport interface MultiSelectRange {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n}\r\n\r\nexport type ImageClipDataRange = [[number, number], [number, number]]\r\n\r\nexport interface ImageClipData {\r\n range: ImageClipDataRange;\r\n path: string;\r\n}\r\n\r\nexport interface ImageClipedEmitData {\r\n range: ImageClipDataRange;\r\n position: {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n };\r\n}\r\n\r\nexport interface CreateElementSelectionData {\r\n start: [number, number];\r\n end: [number, number];\r\n}\r\n\r\nexport interface CreatingTextElement {\r\n type: 'text';\r\n}\r\nexport interface CreatingShapeElement {\r\n type: 'shape';\r\n data: ShapePoolItem;\r\n}\r\nexport interface CreatingLineElement {\r\n type: 'line';\r\n data: LinePoolItem;\r\n}\r\nexport type CreatingElement = CreatingTextElement | CreatingShapeElement | CreatingLineElement","export const enum KEYS {\r\n C = 'C',\r\n X = 'X',\r\n Z = 'Z',\r\n Y = 'Y',\r\n A = 'A',\r\n G = 'G',\r\n L = 'L',\r\n F = 'F',\r\n D = 'D',\r\n B = 'B',\r\n MINUS = '-',\r\n EQUAL = '=',\r\n DIGIT_0 = '0',\r\n DELETE = 'DELETE',\r\n UP = 'ARROWUP',\r\n DOWN = 'ARROWDOWN',\r\n LEFT = 'ARROWLEFT',\r\n RIGHT = 'ARROWRIGHT',\r\n ENTER = 'ENTER',\r\n SPACE = ' ',\r\n TAB = 'TAB',\r\n BACKSPACE = 'BACKSPACE',\r\n}\r\n\r\nexport const HOTKEY_DOC = [\r\n {\r\n type: '通用',\r\n children: [\r\n { label: '剪切', value: 'Ctrl + X' },\r\n { label: '复制', value: 'Ctrl + C' },\r\n { label: '粘贴', value: 'Ctrl + V' },\r\n { label: '快速复制粘贴', value: 'Ctrl + D' },\r\n { label: '全选', value: 'Ctrl + A' },\r\n { label: '撤销', value: 'Ctrl + Z' },\r\n { label: '恢复', value: 'Ctrl + Y' },\r\n { label: '删除', value: 'Delete / Backspace' },\r\n ],\r\n },\r\n {\r\n type: '幻灯片放映',\r\n children: [\r\n { label: '开始放映幻灯片', value: 'Ctrl + F' },\r\n { label: '切换上一页', value: '↑ / ←' },\r\n { label: '切换下一页', value: '↓ / → / Enter / Space' },\r\n { label: '退出放映', value: 'ESC' },\r\n ],\r\n },\r\n {\r\n type: '幻灯片编辑',\r\n children: [\r\n { label: '新建幻灯片', value: 'Enter' },\r\n { label: '缩放画布', value: 'Ctrl + 鼠标滚动' },\r\n { label: '放大画布', value: 'Ctrl + =' },\r\n { label: '缩小画布', value: 'Ctrl + -' },\r\n { label: '缩放画布到合适大小', value: 'Ctrl + 0' },\r\n { label: '编辑上一页', value: '↑ / ←' },\r\n { label: '编辑下一页', value: '↓ / →' },\r\n ],\r\n },\r\n {\r\n type: '元素操作',\r\n children: [\r\n { label: '移动', value: '↑ / ← / ↓ / →' },\r\n { label: '锁定', value: 'Ctrl + L' },\r\n { label: '组合', value: 'Ctrl + G' },\r\n { label: '取消组合', value: 'Ctrl + Shift + G' },\r\n { label: '置顶层', value: 'Alt + F' },\r\n { label: '置底层', value: 'Alt + B' },\r\n { label: '多选', value: '按住 Ctrl 或 Shift' },\r\n { label: '锁定宽高比例', value: '按住 Ctrl 或 Shift' },\r\n { label: '创建水平 / 垂直线条', value: '按住 Ctrl 或 Shift' },\r\n { label: '确认图片裁剪', value: 'Enter' },\r\n ],\r\n },\r\n {\r\n type: '表格编辑',\r\n children: [\r\n { label: '聚焦到下一个单元格', value: 'Tab' },\r\n { label: '在上方插入一行', value: 'Ctrl + ↑' },\r\n { label: '在下方插入一行', value: 'Ctrl + ↓' },\r\n { label: '在左侧插入一列', value: 'Ctrl + ←' },\r\n { label: '在右侧插入一列', value: 'Ctrl + →' },\r\n ],\r\n },\r\n {\r\n type: '文本编辑',\r\n children: [\r\n { label: '加粗', value: 'Ctrl + B' },\r\n { label: '斜体', value: 'Ctrl + I' },\r\n { label: '下划线', value: 'Ctrl + U' },\r\n { label: '删除线', value: 'Ctrl + D' },\r\n ],\r\n },\r\n]","import padStart from 'lodash/padStart'\r\n\r\n/**\r\n * 生成随机码\r\n * @param len 随机码长度\r\n */\r\nexport const createRandomCode = (len = 6) => {\r\n const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`\r\n const maxLen = charset.length\r\n let ret = ''\r\n for (let i = 0; i < len; i++) {\r\n const randomIndex = Math.floor(Math.random() * maxLen)\r\n ret += charset[randomIndex]\r\n }\r\n return ret\r\n}\r\n\r\n/**\r\n * 补足数字位数\r\n * @param digit 数字\r\n * @param len 位数\r\n */\r\nexport const fillDigit = (digit: number, len: number) => {\r\n return padStart('' + digit, len, '0')\r\n}","import Clipboard from 'clipboard'\r\n\r\n/**\r\n * 复制文本到剪贴板\r\n * @param text 文本内容\r\n */\r\nexport const copyText = (text: string) => {\r\n return new Promise((resolve, reject) => {\r\n const fakeElement = document.createElement('button')\r\n const clipboard = new Clipboard(fakeElement, {\r\n text: () => text,\r\n action: () => 'copy',\r\n container: document.body,\r\n })\r\n clipboard.on('success', e => {\r\n clipboard.destroy()\r\n resolve(e)\r\n })\r\n clipboard.on('error', e => {\r\n clipboard.destroy()\r\n reject(e)\r\n })\r\n document.body.appendChild(fakeElement)\r\n fakeElement.click()\r\n document.body.removeChild(fakeElement)\r\n })\r\n}\r\n\r\n// 读取剪贴板\r\nexport const readClipboard = (): Promise<string> => {\r\n return new Promise((resolve, reject) => {\r\n if (navigator.clipboard) {\r\n navigator.clipboard.readText().then(text => {\r\n if (!text) reject('剪贴板为空或者不包含文本')\r\n return resolve(text)\r\n })\r\n }\r\n else reject('浏览器不支持或禁止访问剪贴板')\r\n })\r\n}","import CryptoJS from 'crypto-js'\r\n\r\nconst CRYPTO_KEY = 'pptist'\r\n\r\n/**\r\n * 加密\r\n * @param msg 待加密字符串\r\n */\r\nexport const encrypt = (msg: string) => {\r\n return CryptoJS.AES.encrypt(msg, CRYPTO_KEY).toString()\r\n}\r\n\r\n/**\r\n * 解密\r\n * @param ciphertext 待解密字符串\r\n */\r\nexport const decrypt = (ciphertext: string) => {\r\n const bytes = CryptoJS.AES.decrypt(ciphertext, CRYPTO_KEY)\r\n return bytes.toString(CryptoJS.enc.Utf8)\r\n}","import debounce from 'lodash/debounce'\r\nimport throttle from 'lodash/throttle'\r\nimport { ActionTypes, useStore } from '@/store'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n\r\n // 添加历史快照(历史记录)\r\n const addHistorySnapshot = debounce(function() {\r\n store.dispatch(ActionTypes.ADD_SNAPSHOT)\r\n }, 300, { trailing: true })\r\n\r\n // 重做\r\n const redo = throttle(function() {\r\n store.dispatch(ActionTypes.RE_DO)\r\n }, 100, { leading: true, trailing: false })\r\n\r\n // 撤销\r\n const undo = throttle(function() {\r\n store.dispatch(ActionTypes.UN_DO)\r\n }, 100, { leading: true, trailing: false })\r\n\r\n return {\r\n addHistorySnapshot,\r\n redo,\r\n undo,\r\n }\r\n}","interface ImageSize {\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/**\r\n * 获取图片的原始宽高\r\n * @param src 图片地址\r\n */\r\nexport const getImageSize = (src: string): Promise<ImageSize> => {\r\n return new Promise(resolve => {\r\n const img = document.createElement('img')\r\n img.src = src\r\n img.style.opacity = '0'\r\n document.body.appendChild(img)\r\n\r\n img.onload = () => {\r\n const imgWidth = img.clientWidth\r\n const imgHeight = img.clientHeight\r\n \r\n img.onload = null\r\n img.onerror = null\r\n\r\n document.body.removeChild(img)\r\n\r\n resolve({ width: imgWidth, height: imgHeight })\r\n }\r\n\r\n img.onerror = () => {\r\n img.onload = null\r\n img.onerror = null\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * 读取图片文件的dataURL\r\n * @param file 图片文件\r\n */\r\nexport const getImageDataURL = (file: File): Promise<string> => {\r\n return new Promise(resolve => {\r\n const reader = new FileReader()\r\n reader.addEventListener('load', () => {\r\n resolve(reader.result as string)\r\n })\r\n reader.readAsDataURL(file)\r\n })\r\n}","export const VIEWPORT_SIZE = 1000\r\nexport const VIEWPORT_ASPECT_RATIO = 0.5625","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { getImageSize } from '@/utils/image'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport { ChartType, PPTElement, TableCell } from '@/types/slides'\r\nimport { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\ninterface CommonElementPosition {\r\n top: number;\r\n left: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\ninterface LineElementPosition {\r\n top: number;\r\n left: number;\r\n start: [number, number];\r\n end: [number, number];\r\n}\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const themeColor = computed(() => store.state.theme.themeColor)\r\n const fontColor = computed(() => store.state.theme.fontColor)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 创建(插入)一个元素并将其设置为被选中元素\r\n const createElement = (element: PPTElement) => {\r\n store.commit(MutationTypes.ADD_ELEMENT, element)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.id])\r\n addHistorySnapshot()\r\n }\r\n\r\n /**\r\n * 创建图片元素\r\n * @param src 图片地址\r\n */\r\n const createImageElement = (src: string) => {\r\n getImageSize(src).then(({ width, height }) => {\r\n const scale = height / width\r\n \r\n if (scale < VIEWPORT_ASPECT_RATIO && width > VIEWPORT_SIZE) {\r\n width = VIEWPORT_SIZE\r\n height = width * scale\r\n }\r\n else if (height > VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO) {\r\n height = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n width = height / scale\r\n }\r\n\r\n createElement({\r\n type: 'image',\r\n id: createRandomCode(),\r\n src,\r\n width,\r\n height,\r\n left: (VIEWPORT_SIZE - width) / 2,\r\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\r\n fixedRatio: true,\r\n })\r\n })\r\n }\r\n \r\n /**\r\n * 创建图表元素\r\n * @param chartType 图表类型\r\n */\r\n const createChartElement = (chartType: ChartType) => {\r\n createElement({\r\n type: 'chart',\r\n id: createRandomCode(),\r\n chartType,\r\n left: 300,\r\n top: 81.25,\r\n width: 400,\r\n height: 400,\r\n themeColor: themeColor.value,\r\n gridColor: fontColor.value,\r\n data: {\r\n labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],\r\n series: [\r\n [12, 19, 5, 2, 18],\r\n ],\r\n },\r\n })\r\n }\r\n \r\n /**\r\n * 创建表格元素\r\n * @param row 行数\r\n * @param col 列数\r\n */\r\n const createTableElement = (row: number, col: number) => {\r\n const rowCells: TableCell[] = new Array(col).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\r\n const data: TableCell[][] = new Array(row).fill(rowCells)\r\n\r\n const DEFAULT_CELL_WIDTH = 100\r\n const DEFAULT_CELL_HEIGHT = 36\r\n\r\n const colWidths: number[] = new Array(col).fill(1 / col)\r\n\r\n const width = col * DEFAULT_CELL_WIDTH\r\n const height = row * DEFAULT_CELL_HEIGHT\r\n\r\n createElement({\r\n type: 'table',\r\n id: createRandomCode(),\r\n width,\r\n height,\r\n colWidths,\r\n data,\r\n left: (VIEWPORT_SIZE - width) / 2,\r\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\r\n outline: {\r\n width: 2,\r\n style: 'solid',\r\n color: '#eeece1',\r\n },\r\n theme: {\r\n color: themeColor.value,\r\n rowHeader: true,\r\n rowFooter: false,\r\n colHeader: false,\r\n colFooter: false,\r\n },\r\n })\r\n }\r\n \r\n /**\r\n * 创建文本元素\r\n * @param position 位置大小信息\r\n * @param content 文本内容\r\n */\r\n const createTextElement = (position: CommonElementPosition, content = '请输入内容') => {\r\n const { left, top, width, height } = position\r\n createElement({\r\n type: 'text',\r\n id: createRandomCode(),\r\n left, \r\n top, \r\n width, \r\n height,\r\n content,\r\n })\r\n }\r\n \r\n /**\r\n * 创建形状元素\r\n * @param position 位置大小信息\r\n * @param data 形状路径信息\r\n */\r\n const createShapeElement = (position: CommonElementPosition, data: ShapePoolItem) => {\r\n const { left, top, width, height } = position\r\n createElement({\r\n type: 'shape',\r\n id: createRandomCode(),\r\n left, \r\n top, \r\n width, \r\n height,\r\n viewBox: data.viewBox,\r\n path: data.path,\r\n fill: themeColor.value,\r\n fixedRatio: false,\r\n })\r\n }\r\n \r\n /**\r\n * 创建线条元素\r\n * @param position 位置大小信息\r\n * @param data 线条的路径和样式\r\n */\r\n const createLineElement = (position: LineElementPosition, data: LinePoolItem) => {\r\n const { left, top, start, end } = position\r\n createElement({\r\n type: 'line',\r\n id: createRandomCode(),\r\n left, \r\n top, \r\n start,\r\n end,\r\n points: data.points,\r\n color: themeColor.value,\r\n style: data.style,\r\n width: 2,\r\n })\r\n }\r\n\r\n return {\r\n createImageElement,\r\n createChartElement,\r\n createTableElement,\r\n createTextElement,\r\n createShapeElement,\r\n createLineElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { decrypt } from '@/utils/crypto'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\nimport useCreateElement from '@/hooks/useCreateElement'\r\n\r\ninterface PasteTextClipboardDataOptions {\r\n onlySlide?: boolean;\r\n onlyElements?: boolean;\r\n}\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n const { createTextElement } = useCreateElement()\r\n\r\n /**\r\n * 粘贴元素(一组)\r\n * @param elements 元素列表数据\r\n */\r\n const pasteElement = (elements: PPTElement[]) => {\r\n const groupIdMap = {}\r\n const elIdMap = {}\r\n for (const element of elements) {\r\n const groupId = element.groupId\r\n if (groupId && !groupIdMap[groupId]) {\r\n groupIdMap[groupId] = createRandomCode()\r\n }\r\n elIdMap[element.id] = createRandomCode()\r\n }\r\n const currentSlideElementIdList = currentSlide.value.elements.map(el => el.id)\r\n \r\n for (const element of elements) {\r\n const inCurrentSlide = currentSlideElementIdList.includes(element.id)\r\n \r\n element.id = elIdMap[element.id]\r\n\r\n if (inCurrentSlide) {\r\n element.left = element.left + 10\r\n element.top = element.top + 10\r\n }\r\n\r\n if (element.groupId) element.groupId = groupIdMap[element.groupId]\r\n }\r\n store.commit(MutationTypes.ADD_ELEMENT, elements)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))\r\n addHistorySnapshot()\r\n }\r\n\r\n /**\r\n * 粘贴页面\r\n * @param slide 页面数据\r\n */\r\n const pasteSlide = (slide: Slide) => {\r\n store.commit(MutationTypes.ADD_SLIDE, {\r\n ...slide,\r\n id: createRandomCode(8),\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n /**\r\n * 粘贴普通文本:创建为新的文本元素\r\n * @param text 文本\r\n */\r\n const pasteText = (text: string) => {\r\n createTextElement({\r\n left: 0,\r\n top: 0,\r\n width: 600,\r\n height: 50,\r\n }, text)\r\n }\r\n\r\n /**\r\n * 解析剪贴板内容,根据解析结果选择合适的粘贴方式\r\n * @param text 剪贴板内容\r\n * @param options 配置项:onlySlide -- 仅处理页面粘贴;onlyElements -- 仅处理元素粘贴;\r\n */\r\n const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {\r\n const onlySlide = options?.onlySlide || false\r\n const onlyElements = options?.onlyElements || false\r\n\r\n let clipboardData\r\n try {\r\n clipboardData = JSON.parse(decrypt(text))\r\n }\r\n catch {\r\n clipboardData = text\r\n }\r\n\r\n // 元素或页面\r\n if (typeof clipboardData === 'object') {\r\n const { type, data } = clipboardData\r\n\r\n if (type === 'elements' && !onlySlide) pasteElement(data)\r\n else if (type === 'slide' && !onlyElements) pasteSlide(data)\r\n }\r\n\r\n // 普通文本\r\n else if (!onlyElements && !onlySlide) pasteText(clipboardData)\r\n }\r\n\r\n return {\r\n pasteTextClipboardData,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { copyText, readClipboard } from '@/utils/clipboard'\r\nimport { encrypt } from '@/utils/crypto'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { message } from 'ant-design-vue'\r\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n const theme = computed(() => store.state.theme)\r\n const slidesLength = computed(() => store.state.slides.length)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { pasteTextClipboardData } = usePasteTextClipboardData()\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n /**\r\n * 移动页面焦点\r\n * @param command 移动页面焦点命令:上移、下移\r\n */\r\n const updateSlideIndex = (command: string) => {\r\n let targetIndex = 0\r\n if (command === KEYS.UP && slideIndex.value > 0) {\r\n targetIndex = slideIndex.value - 1\r\n }\r\n else if (command === KEYS.DOWN && slideIndex.value < slidesLength.value - 1) {\r\n targetIndex = slideIndex.value + 1\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)\r\n }\r\n\r\n // 将当前页面数据加密后复制到剪贴板\r\n const copySlide = () => {\r\n const text = encrypt(JSON.stringify({\r\n type: 'slide',\r\n data: currentSlide.value,\r\n }))\r\n\r\n copyText(text).then(() => {\r\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, true)\r\n })\r\n }\r\n\r\n // 尝试将剪贴板页面数据解密后添加到下一页(粘贴)\r\n const pasteSlide = () => {\r\n readClipboard().then(text => {\r\n pasteTextClipboardData(text, { onlySlide: true })\r\n }).catch(err => message.warning(err))\r\n }\r\n\r\n // 创建一页空白页并添加到下一页\r\n const createSlide = () => {\r\n const emptySlide = {\r\n id: createRandomCode(8),\r\n elements: [],\r\n background: {\r\n type: 'solid',\r\n color: theme.value.backgroundColor,\r\n },\r\n }\r\n store.commit(MutationTypes.ADD_SLIDE, emptySlide)\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将当前页复制一份到下一页\r\n const copyAndPasteSlide = () => {\r\n store.commit(MutationTypes.ADD_SLIDE, {\r\n ...currentSlide.value,\r\n id: createRandomCode(8),\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 删除当前页\r\n const deleteSlide = () => {\r\n if (slidesLength.value === 1) return message.warning('无法继续删除')\r\n \r\n store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将当前页复制后删除(剪切)\r\n const cutSlide = () => {\r\n copySlide()\r\n deleteSlide()\r\n }\r\n\r\n return {\r\n updateSlideIndex,\r\n copySlide,\r\n pasteSlide,\r\n createSlide,\r\n copyAndPasteSlide,\r\n deleteSlide,\r\n cutSlide,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 锁定选中的元素,并清空选中元素状态\r\n const lockElement = () => {\r\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n \r\n for (const element of newElementList) {\r\n if (activeElementIdList.value.includes(element.id)) element.lock = true\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n addHistorySnapshot()\r\n }\r\n\r\n /**\r\n * 解除元素的锁定状态,并将其设置为当前选择元素\r\n * @param handleElement 需要解锁的元素\r\n */\r\n const unlockElement = (handleElement: PPTElement) => {\r\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n\r\n if (handleElement.groupId) {\r\n for (const element of newElementList) {\r\n if (element.groupId === handleElement.groupId) element.lock = false\r\n }\r\n return newElementList\r\n }\r\n \r\n for (const element of newElementList) {\r\n if (element.id === handleElement.id) {\r\n element.lock = false\r\n break\r\n }\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [handleElement.id])\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n lockElement,\r\n unlockElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 删除全部选中元素\r\n const deleteElement = () => {\r\n if (!activeElementIdList.value.length) return\r\n const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id))\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 删除内面内全部元素(无论是否选中)\r\n const deleteAllElements = () => {\r\n if (!currentSlide.value.elements.length) return\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n deleteElement,\r\n deleteAllElements,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n /**\r\n * 组合当前选中的元素:给当前选中的元素赋予一个相同的分组ID\r\n */\r\n const combineElements = () => {\r\n if (!activeElementList.value.length) return\r\n\r\n // 生成一个新元素列表进行后续操作\r\n let newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n\r\n // 生成分组ID\r\n const groupId = createRandomCode()\r\n\r\n // 收集需要组合的元素列表,并赋上唯一分组ID\r\n const combineElementList: PPTElement[] = []\r\n for (const element of newElementList) {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n element.groupId = groupId\r\n combineElementList.push(element)\r\n }\r\n }\r\n\r\n // 确保该组合内所有元素成员的层级是连续的,具体操作方法为:\r\n // 先获取到该组合内最上层元素的层级,将本次需要组合的元素从新元素列表中移除,\r\n // 再根据最上层元素的层级位置,将上面收集到的需要组合的元素列表一起插入到新元素列表中合适的位置\r\n const combineElementMaxLevel = newElementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id)\r\n const combineElementIdList = combineElementList.map(_element => _element.id)\r\n newElementList = newElementList.filter(_element => !combineElementIdList.includes(_element.id))\r\n\r\n const insertLevel = combineElementMaxLevel - combineElementList.length + 1\r\n newElementList.splice(insertLevel, 0, ...combineElementList)\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n /**\r\n * 取消组合元素:移除选中元素的分组ID\r\n */\r\n const uncombineElements = () => {\r\n if (!activeElementList.value.length) return\r\n const hasElementInGroup = activeElementList.value.some(item => item.groupId)\r\n if (!hasElementInGroup) return\r\n \r\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n for (const element of newElementList) {\r\n if (activeElementIdList.value.includes(element.id) && element.groupId) delete element.groupId\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n\r\n // 取消组合后,需要重置激活元素状态\r\n // 默认重置为当前正在操作的元素,如果不存在则重置为空\r\n const handleElementIdList = handleElementId.value ? [handleElementId.value] : []\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, handleElementIdList)\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n combineElements,\r\n uncombineElements,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { copyText, readClipboard } from '@/utils/clipboard'\r\nimport { encrypt } from '@/utils/crypto'\r\nimport { message } from 'ant-design-vue'\r\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\r\nimport useDeleteElement from './useDeleteElement'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)\r\n\r\n const { pasteTextClipboardData } = usePasteTextClipboardData()\r\n const { deleteElement } = useDeleteElement()\r\n\r\n // 将选中元素数据加密后复制到剪贴板\r\n const copyElement = () => {\r\n if (!activeElementIdList.value.length) return\r\n\r\n const text = encrypt(JSON.stringify({\r\n type: 'elements',\r\n data: activeElementList.value,\r\n }))\r\n\r\n copyText(text).then(() => {\r\n store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\r\n })\r\n }\r\n\r\n // 将选中元素复制后删除(剪切)\r\n const cutElement = () => {\r\n copyElement()\r\n deleteElement()\r\n }\r\n\r\n // 尝试将剪贴板元素数据解密后进行粘贴\r\n const pasteElement = () => {\r\n readClipboard().then(text => {\r\n pasteTextClipboardData(text)\r\n }).catch(err => message.warning(err))\r\n }\r\n\r\n // 将选中元素复制后立刻粘贴\r\n const quickCopyElement = () => {\r\n copyElement()\r\n pasteElement()\r\n }\r\n\r\n return {\r\n copyElement,\r\n cutElement,\r\n pasteElement,\r\n quickCopyElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n // 将当前页面全部元素设置为被选择状态\r\n const selectAllElement = () => {\r\n const unlockedElements = currentSlide.value.elements.filter(el => !el.lock)\r\n const newActiveElementIdList = unlockedElements.map(el => el.id)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\r\n }\r\n\r\n return {\r\n selectAllElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n /**\r\n * 将元素向指定方向移动指定的距离\r\n * @param command 移动方向\r\n * @param step 移动距离\r\n */\r\n const moveElement = (command: string, step = 1) => {\r\n const newElementList = currentSlide.value.elements.map(el => {\r\n if (activeElementIdList.value.includes(el.id)) {\r\n let { left, top } = el\r\n switch (command) {\r\n case KEYS.LEFT: \r\n left = left - step\r\n break\r\n case KEYS.RIGHT: \r\n left = left + step\r\n break\r\n case KEYS.UP: \r\n top = top - step\r\n break\r\n case KEYS.DOWN: \r\n top = top + step\r\n break\r\n default: break\r\n }\r\n return { ...el, left, top }\r\n }\r\n return el\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n moveElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n /**\r\n * 获取组合元素层级范围\r\n * @param elementList 本页所有元素列表\r\n * @param combineElementList 组合元素列表\r\n */\r\n const getCombineElementLevelRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {\r\n return {\r\n minLevel: elementList.findIndex(_element => _element.id === combineElementList[0].id),\r\n maxLevel: elementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id),\r\n }\r\n }\r\n\r\n /**\r\n * 上移一层\r\n * @param elementList 本页所有元素列表\r\n * @param element 当前操作的元素\r\n */\r\n const moveUpElement = (elementList: PPTElement[], element: PPTElement) => {\r\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\r\n\r\n // 如果被操作的元素是组合元素成员,需要将该组合全部成员一起进行移动\r\n if (element.groupId) {\r\n\r\n // 获取到该组合全部成员,以及所有成员的层级范围\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\r\n const { minLevel, maxLevel } = getCombineElementLevelRange(elementList, combineElementList)\r\n\r\n // 已经处在顶层,无法继续移动\r\n if (maxLevel === elementList.length - 1) return\r\n\r\n // 通过组合成员范围的最大值,获取到该组合上一层的元素,然后将该组合元素从元素列表中移除(并缓存被移除的元素列表)\r\n // 若上层元素处在另一个组合中,则将上述被移除的组合元素插入到该上层组合上方\r\n // 若上层元素不处于任何分组中,则将上述被移除的组合元素插入到该上层元素上方\r\n const nextElement = copyOfElementList[maxLevel + 1]\r\n const movedElementList = copyOfElementList.splice(minLevel, combineElementList.length)\r\n\r\n if (nextElement.groupId) {\r\n const nextCombineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\r\n copyOfElementList.splice(minLevel + nextCombineElementList.length, 0, ...movedElementList)\r\n }\r\n else copyOfElementList.splice(minLevel + 1, 0, ...movedElementList)\r\n }\r\n\r\n // 如果被操作的元素不是组合元素成员\r\n else {\r\n\r\n // 获取该元素在列表中的层级\r\n const level = elementList.findIndex(item => item.id === element.id)\r\n\r\n // 已经处在顶层,无法继续移动\r\n if (level === elementList.length - 1) return\r\n\r\n // 获取到该组合上一层的元素,然后将该组合元素从元素列表中移除(并缓存被移除的元素列表)\r\n const nextElement = copyOfElementList[level + 1]\r\n const movedElement = copyOfElementList.splice(level, 1)[0]\r\n\r\n // 通过组合成员范围的最大值,获取到该组合上一层的元素,然后将该组合元素从元素列表中移除(并缓存被移除的元素列表)\r\n // 若上层元素处在另一个组合中,则将上述被移除的组合元素插入到该上层组合上方\r\n // 若上层元素不处于任何分组中,则将上述被移除的组合元素插入到该上层元素上方\r\n if (nextElement.groupId) {\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\r\n copyOfElementList.splice(level + combineElementList.length, 0, movedElement)\r\n }\r\n else copyOfElementList.splice(level + 1, 0, movedElement)\r\n }\r\n\r\n return copyOfElementList\r\n }\r\n\r\n /**\r\n * 下移一层,操作方式同上移\r\n * @param elementList 本页所有元素列表\r\n * @param element 当前操作的元素\r\n */\r\n const moveDownElement = (elementList: PPTElement[], element: PPTElement) => {\r\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\r\n\r\n if (element.groupId) {\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\r\n const { minLevel } = getCombineElementLevelRange(elementList, combineElementList)\r\n if (minLevel === 0) return\r\n\r\n const prevElement = copyOfElementList[minLevel - 1]\r\n const movedElementList = copyOfElementList.splice(minLevel, combineElementList.length)\r\n\r\n if (prevElement.groupId) {\r\n const prevCombineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\r\n copyOfElementList.splice(minLevel - prevCombineElementList.length, 0, ...movedElementList)\r\n }\r\n else copyOfElementList.splice(minLevel - 1, 0, ...movedElementList)\r\n }\r\n\r\n else {\r\n const level = elementList.findIndex(item => item.id === element.id)\r\n if (level === 0) return\r\n\r\n const prevElement = copyOfElementList[level - 1]\r\n const movedElement = copyOfElementList.splice(level, 1)[0]\r\n\r\n if (prevElement.groupId) {\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\r\n copyOfElementList.splice(level - combineElementList.length, 0, movedElement)\r\n }\r\n else copyOfElementList.splice(level - 1, 0, movedElement)\r\n }\r\n\r\n return copyOfElementList\r\n }\r\n\r\n /**\r\n * 置顶层\r\n * @param elementList 本页所有元素列表\r\n * @param element 当前操作的元素\r\n */\r\n const moveTopElement = (elementList: PPTElement[], element: PPTElement) => {\r\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\r\n\r\n // 如果被操作的元素是组合元素成员,需要将该组合全部成员一起进行移动\r\n if (element.groupId) {\r\n\r\n // 获取到该组合全部成员,以及所有成员的层级范围\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\r\n const { minLevel, maxLevel } = getCombineElementLevelRange(elementList, combineElementList)\r\n\r\n // 已经处在顶层,无法继续移动\r\n if (maxLevel === elementList.length - 1) return null\r\n\r\n // 将该组合元素从元素列表中移除,然后将被移除的元素添加到元素列表顶部\r\n const movedElementList = copyOfElementList.splice(minLevel, combineElementList.length)\r\n copyOfElementList.push(...movedElementList)\r\n }\r\n\r\n // 如果被操作的元素不是组合元素成员\r\n else {\r\n\r\n // 获取该元素在列表中的层级\r\n const level = elementList.findIndex(item => item.id === element.id)\r\n\r\n // 已经处在顶层,无法继续移动\r\n if (level === elementList.length - 1) return null\r\n\r\n // 将该组合元素从元素列表中移除,然后将被移除的元素添加到元素列表底部\r\n copyOfElementList.splice(level, 1)\r\n copyOfElementList.push(element)\r\n }\r\n\r\n return copyOfElementList\r\n }\r\n\r\n /**\r\n * 置底层,操作方式同置顶\r\n * @param elementList 本页所有元素列表\r\n * @param element 当前操作的元素\r\n */\r\n const moveBottomElement = (elementList: PPTElement[], element: PPTElement) => {\r\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\r\n\r\n if (element.groupId) {\r\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\r\n const { minLevel } = getCombineElementLevelRange(elementList, combineElementList)\r\n if (minLevel === 0) return\r\n\r\n const movedElementList = copyOfElementList.splice(minLevel, combineElementList.length)\r\n copyOfElementList.unshift(...movedElementList)\r\n }\r\n\r\n else {\r\n const level = elementList.findIndex(item => item.id === element.id)\r\n if (level === 0) return\r\n\r\n copyOfElementList.splice(level, 1)\r\n copyOfElementList.unshift(element)\r\n }\r\n\r\n return copyOfElementList\r\n }\r\n\r\n /**\r\n * 调整元素层级\r\n * @param element 需要调整层级的元素\r\n * @param command 调整命令:上移、下移、置顶、置底\r\n */\r\n const orderElement = (element: PPTElement, command: ElementOrderCommand) => {\r\n let newElementList\r\n \r\n if (command === ElementOrderCommands.UP) newElementList = moveUpElement(currentSlide.value.elements, element)\r\n else if (command === ElementOrderCommands.DOWN) newElementList = moveDownElement(currentSlide.value.elements, element)\r\n else if (command === ElementOrderCommands.TOP) newElementList = moveTopElement(currentSlide.value.elements, element)\r\n else if (command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)\r\n\r\n if (!newElementList) return\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n orderElement,\r\n }\r\n}","// 进入全屏\r\nexport const enterFullscreen = () => {\r\n const docElm = document.documentElement\r\n if (docElm.requestFullscreen) docElm.requestFullscreen() \r\n else if (docElm.mozRequestFullScreen) docElm.mozRequestFullScreen() \r\n else if (docElm.webkitRequestFullScreen) docElm.webkitRequestFullScreen()\r\n}\r\n\r\n// 退出全屏\r\nexport const exitFullscreen = () => {\r\n if (document.exitFullscreen) document.exitFullscreen()\r\n else if (document.mozCancelFullScreen) document.mozCancelFullScreen()\r\n else if (document.webkitCancelFullScreen) document.webkitCancelFullScreen()\r\n}\r\n\r\n// 判断是否全屏\r\nexport const isFullscreen = () => (\r\n document.mozFullScreen || \r\n document.webkitIsFullScreen || \r\n document.webkitFullScreen\r\n)","import { MutationTypes, useStore } from '@/store'\r\nimport { enterFullscreen, exitFullscreen, isFullscreen } from '@/utils/fullscreen'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n\r\n // 进入放映状态(从当前页开始)\r\n const enterScreening = () => {\r\n enterFullscreen()\r\n store.commit(MutationTypes.SET_SCREENING, true)\r\n }\r\n\r\n // 进入放映状态(从第一页开始)\r\n const enterScreeningFromStart = () => {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)\r\n enterScreening()\r\n }\r\n\r\n // 退出放映状态\r\n const exitScreening = () => {\r\n store.commit(MutationTypes.SET_SCREENING, false)\r\n if (isFullscreen()) exitFullscreen()\r\n }\r\n\r\n return {\r\n enterScreening,\r\n enterScreeningFromStart,\r\n exitScreening,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const canvasPercentage = computed(() => store.state.canvasPercentage)\r\n\r\n /**\r\n * 缩放画布百分比\r\n * @param command 缩放命令:放大、缩小\r\n */\r\n const scaleCanvas = (command: '+' | '-') => {\r\n let percentage = canvasPercentage.value\r\n const step = 5\r\n const max = 120\r\n const min = 60\r\n if (command === '+' && percentage <= max) percentage += step\r\n if (command === '-' && percentage >= min) percentage -= step\r\n \r\n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\r\n }\r\n\r\n /**\r\n * 设置画笔百分比\r\n * @param percentage 百分比(小数形式,如0.8)\r\n */\r\n const setCanvasPercentage = (percentage: number) => {\r\n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\r\n }\r\n \r\n return {\r\n scaleCanvas,\r\n setCanvasPercentage,\r\n }\r\n}","import { computed, onMounted, onUnmounted } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { KEYS } from '@/configs/hotkey'\r\n\r\nimport useSlideHandler from './useSlideHandler'\r\nimport useLockElement from './useLockElement'\r\nimport useDeleteElement from './useDeleteElement'\r\nimport useCombineElement from './useCombineElement'\r\nimport useCopyAndPasteElement from './useCopyAndPasteElement'\r\nimport useSelectAllElement from './useSelectAllElement'\r\nimport useMoveElement from './useMoveElement'\r\nimport useOrderElement from './useOrderElement'\r\nimport useHistorySnapshot from './useHistorySnapshot'\r\nimport useScreening from './useScreening'\r\nimport useScaleCanvas from './useScaleCanvas'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n\r\n const ctrlKeyActive = computed(() => store.state.ctrlKeyState)\r\n const shiftKeyActive = computed(() => store.state.shiftKeyState)\r\n const disableHotkeys = computed(() => store.state.disableHotkeys)\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\r\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\r\n\r\n const {\r\n updateSlideIndex,\r\n copySlide,\r\n createSlide,\r\n deleteSlide,\r\n cutSlide,\r\n copyAndPasteSlide,\r\n } = useSlideHandler()\r\n\r\n const { combineElements, uncombineElements } = useCombineElement()\r\n const { deleteElement } = useDeleteElement()\r\n const { lockElement } = useLockElement()\r\n const { copyElement, cutElement, quickCopyElement } = useCopyAndPasteElement()\r\n const { selectAllElement } = useSelectAllElement()\r\n const { moveElement } = useMoveElement()\r\n const { orderElement } = useOrderElement()\r\n const { redo, undo } = useHistorySnapshot()\r\n const { enterScreening } = useScreening()\r\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\r\n\r\n const copy = () => {\r\n if (activeElementIdList.value.length) copyElement()\r\n else if (thumbnailsFocus.value) copySlide()\r\n }\r\n\r\n const cut = () => {\r\n if (activeElementIdList.value.length) cutElement()\r\n else if (thumbnailsFocus.value) cutSlide()\r\n }\r\n\r\n const quickCopy = () => {\r\n if (activeElementIdList.value.length) quickCopyElement()\r\n else if (thumbnailsFocus.value) copyAndPasteSlide()\r\n }\r\n\r\n const selectAll = () => {\r\n if (!editorAreaFocus.value) return\r\n selectAllElement()\r\n }\r\n\r\n const lock = () => {\r\n if (!editorAreaFocus.value) return\r\n lockElement()\r\n }\r\n const combine = () => {\r\n if (!editorAreaFocus.value) return\r\n combineElements()\r\n }\r\n\r\n const uncombine = () => {\r\n if (!editorAreaFocus.value) return\r\n uncombineElements()\r\n }\r\n\r\n const remove = () => {\r\n if (activeElementIdList.value.length) deleteElement()\r\n else if (thumbnailsFocus.value) deleteSlide()\r\n }\r\n\r\n const move = (key: string) => {\r\n if (activeElementIdList.value.length) moveElement(key)\r\n else if (key === KEYS.UP || key === KEYS.DOWN) updateSlideIndex(key)\r\n }\r\n\r\n const order = (command: ElementOrderCommand) => {\r\n if (!handleElement.value) return\r\n orderElement(handleElement.value, command)\r\n }\r\n\r\n const create = () => {\r\n if (!thumbnailsFocus.value) return\r\n createSlide()\r\n }\r\n\r\n const keydownListener = (e: KeyboardEvent) => {\r\n const { ctrlKey, shiftKey, altKey, metaKey } = e\r\n\r\n const key = e.key.toUpperCase()\r\n\r\n if (ctrlKey && !ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, true)\r\n if (shiftKey && !shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, true)\r\n\r\n if (ctrlKey && key === KEYS.F) {\r\n e.preventDefault()\r\n enterScreening()\r\n store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\r\n }\r\n \r\n if (!editorAreaFocus.value && !thumbnailsFocus.value) return \r\n\r\n if ((ctrlKey || metaKey) && key === KEYS.C) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n copy()\r\n }\r\n if (ctrlKey && key === KEYS.X) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n cut()\r\n }\r\n if (ctrlKey && key === KEYS.D) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n quickCopy()\r\n }\r\n if (ctrlKey && key === KEYS.Z) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n undo()\r\n }\r\n if (ctrlKey && key === KEYS.Y) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n redo()\r\n }\r\n if (ctrlKey && key === KEYS.A) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n selectAll()\r\n }\r\n if (ctrlKey && key === KEYS.L) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n lock()\r\n }\r\n if (!shiftKey && ctrlKey && key === KEYS.G) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n combine()\r\n }\r\n if (shiftKey && ctrlKey && key === KEYS.G) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n uncombine()\r\n }\r\n if (altKey && key === KEYS.F) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n order(ElementOrderCommands.TOP)\r\n }\r\n if (altKey && key === KEYS.B) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n order(ElementOrderCommands.BOTTOM)\r\n }\r\n if (key === KEYS.DELETE || key === KEYS.BACKSPACE) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n remove()\r\n }\r\n if (key === KEYS.UP) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n move(KEYS.UP)\r\n }\r\n if (key === KEYS.DOWN) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n move(KEYS.DOWN)\r\n }\r\n if (key === KEYS.LEFT) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n move(KEYS.LEFT)\r\n }\r\n if (key === KEYS.RIGHT) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n move(KEYS.RIGHT)\r\n }\r\n if (key === KEYS.ENTER) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n create()\r\n }\r\n if (key === KEYS.MINUS) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n scaleCanvas('-')\r\n }\r\n if (key === KEYS.EQUAL) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n scaleCanvas('+')\r\n }\r\n if (key === KEYS.DIGIT_0) {\r\n if (disableHotkeys.value) return\r\n e.preventDefault()\r\n setCanvasPercentage(90)\r\n }\r\n }\r\n \r\n const keyupListener = () => {\r\n if (ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\r\n if (shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, false)\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('keydown', keydownListener)\r\n document.addEventListener('keyup', keyupListener)\r\n window.addEventListener('blur', keyupListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keydownListener)\r\n document.removeEventListener('keyup', keyupListener)\r\n window.removeEventListener('blur', keyupListener)\r\n })\r\n}","import { computed, onMounted, onUnmounted } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport usePasteTextClipboardData from './usePasteTextClipboardData'\r\nimport useCreateElement from './useCreateElement'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\r\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\r\n const disableHotkeys = computed(() => store.state.disableHotkeys)\r\n\r\n const { pasteTextClipboardData } = usePasteTextClipboardData()\r\n const { createImageElement } = useCreateElement()\r\n\r\n // 粘贴图片到幻灯片元素\r\n const pasteImageFile = (imageFile: File) => {\r\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\r\n }\r\n\r\n /**\r\n * 粘贴事件监听\r\n * @param e ClipboardEvent\r\n */\r\n const pasteListener = (e: ClipboardEvent) => {\r\n if (!editorAreaFocus.value && !thumbnailsFocus.value) return\r\n if (disableHotkeys.value) return\r\n\r\n if (!e.clipboardData) return\r\n\r\n const clipboardDataItems = e.clipboardData.items\r\n const clipboardDataFirstItem = clipboardDataItems[0]\r\n\r\n if (!clipboardDataFirstItem) return\r\n\r\n // 如果剪贴板内有图片,优先尝试读取图片\r\n for (const item of clipboardDataItems) {\r\n if (item.kind === 'file' && item.type.indexOf('image') !== -1) {\r\n const imageFile = item.getAsFile()\r\n if (imageFile) pasteImageFile(imageFile)\r\n return\r\n }\r\n }\r\n \r\n // 如果剪贴板内没有图片,但有文字内容,尝试解析文字内容\r\n if (clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\r\n clipboardDataFirstItem.getAsString(text => pasteTextClipboardData(text))\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('paste', pasteListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('paste', pasteListener)\r\n })\r\n}","<template>\r\n <div class=\"editor-header\">\r\n <div class=\"left\">\r\n <Dropdown :trigger=\"['click']\">\r\n <div class=\"menu-item\"><IconEdit /> <span class=\"text\">编辑</span></div>\r\n <template #overlay>\r\n <Menu>\r\n <MenuItem @click=\"undo()\">撤销</MenuItem>\r\n <MenuItem @click=\"redo()\">重做</MenuItem>\r\n <MenuItem @click=\"createSlide()\">添加页面</MenuItem>\r\n <MenuItem @click=\"deleteSlide()\">删除页面</MenuItem>\r\n <MenuItem @click=\"toggleGridLines()\">{{ showGridLines ? '关闭网格线' : '打开网格线' }}</MenuItem>\r\n <MenuItem @click=\"resetSlides()\">重置幻灯片</MenuItem>\r\n </Menu>\r\n </template>\r\n </Dropdown>\r\n <Dropdown :trigger=\"['click']\">\r\n <div class=\"menu-item\"><IconPpt /> <span class=\"text\">演示</span></div>\r\n <template #overlay>\r\n <Menu>\r\n <MenuItem @click=\"enterScreeningFromStart()\">从头开始</MenuItem>\r\n <MenuItem @click=\"enterScreening()\">从当前页开始</MenuItem>\r\n </Menu>\r\n </template>\r\n </Dropdown>\r\n <Dropdown :trigger=\"['click']\">\r\n <div class=\"menu-item\"><IconHelpcenter /> <span class=\"text\">帮助</span></div>\r\n <template #overlay>\r\n <Menu>\r\n <MenuItem @click=\"openDoc()\">开发文档</MenuItem>\r\n <MenuItem @click=\"hotkeyDrawerVisible = true\">快捷键</MenuItem>\r\n </Menu>\r\n </template>\r\n </Dropdown>\r\n </div>\r\n\r\n <div class=\"right\">\r\n <Tooltip :mouseLeaveDelay=\"0\" title=\"幻灯片放映\">\r\n <div class=\"menu-item\" @click=\"enterScreening()\">\r\n <IconPpt size=\"18\" fill=\"#666\" style=\"margin-top: 2px;\" />\r\n </div>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" title=\"Github 仓库\">\r\n <a href=\"https://github.com/pipipi-pikachu/PPTist\" target=\"_blank\">\r\n <div class=\"menu-item\"><IconGithub size=\"18\" fill=\"#666\" /></div>\r\n </a>\r\n </Tooltip>\r\n </div>\r\n\r\n <Drawer\r\n width=\"320\"\r\n placement=\"right\"\r\n :visible=\"hotkeyDrawerVisible\"\r\n @close=\"hotkeyDrawerVisible = false\"\r\n >\r\n <HotkeyDoc />\r\n </Drawer>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useScreening from '@/hooks/useScreening'\r\nimport useSlideHandler from '@/hooks/useSlideHandler'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport HotkeyDoc from './HotkeyDoc.vue'\r\nimport { message } from 'ant-design-vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor-header',\r\n components: {\r\n HotkeyDoc,\r\n },\r\n setup() {\r\n const store = useStore()\r\n\r\n const { enterScreening, enterScreeningFromStart } = useScreening()\r\n const { createSlide, deleteSlide } = useSlideHandler()\r\n const { redo, undo } = useHistorySnapshot()\r\n\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const toggleGridLines = () => {\r\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\r\n }\r\n\r\n const resetSlides = () => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n store.commit(MutationTypes.SET_SLIDES, [{\r\n id: createRandomCode(),\r\n elements: [],\r\n }])\r\n }\r\n\r\n const openDoc = () => {\r\n message.warning('作者努力编写中...')\r\n }\r\n\r\n const hotkeyDrawerVisible = ref(false)\r\n\r\n return {\r\n enterScreening,\r\n enterScreeningFromStart,\r\n createSlide,\r\n deleteSlide,\r\n redo,\r\n undo,\r\n toggleGridLines,\r\n showGridLines,\r\n resetSlides,\r\n openDoc,\r\n hotkeyDrawerVisible,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editor-header {\r\n background-color: #fff;\r\n user-select: none;\r\n border-bottom: 1px solid $borderColor;\r\n display: flex;\r\n justify-content: space-between;\r\n padding: 0 10px;\r\n}\r\n.left, .right {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n.menu-item {\r\n height: 70%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n font-size: 13px;\r\n margin: 0 10px;\r\n cursor: pointer;\r\n\r\n .text {\r\n margin-left: 4px;\r\n }\r\n}\r\n</style>","<template>\r\n <div class=\"hotkey-doc\">\r\n <template v-for=\"item in hotkeys\" :key=\"item.type\">\r\n <div class=\"title\">{{item.type}}</div>\r\n <div class=\"hotkey-item\" v-for=\"hotkey in item.children\" :key=\"hotkey.label\">\r\n <div class=\"label\">{{hotkey.label}}</div>\r\n <div class=\"value\">{{hotkey.value}}</div>\r\n </div>\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport { defineComponent } from 'vue'\r\nimport { HOTKEY_DOC } from '@/configs/hotkey'\r\n\r\nconst hotkeys = HOTKEY_DOC\r\n\r\nexport default defineComponent({\r\n name: 'hotkey-doc',\r\n setup() {\r\n return {\r\n hotkeys,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.hotkey-doc {\r\n height: 100%;\r\n overflow: auto;\r\n font-size: 12px;\r\n}\r\n.title {\r\n font-size: 14px;\r\n font-weight: 700;\r\n border-bottom: 1px solid #e5e5e5;\r\n padding: 15px 0 5px 0;\r\n}\r\n.hotkey-item {\r\n border-bottom: 1px solid #e5e5e5;\r\n padding: 15px 0 5px 0;\r\n display: flex;\r\n align-items: center;\r\n}\r\n.label {\r\n width: 140px;\r\n\r\n @include ellipsis-oneline();\r\n}\r\n</style>","import { render } from \"./HotkeyDoc.vue?vue&type=template&id=47d0351b&scoped=true\"\nimport script from \"./HotkeyDoc.vue?vue&type=script&lang=js\"\nexport * from \"./HotkeyDoc.vue?vue&type=script&lang=js\"\n\nimport \"./HotkeyDoc.vue?vue&type=style&index=0&id=47d0351b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-47d0351b\"\n\nexport default script","\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useScreening from '@/hooks/useScreening'\r\nimport useSlideHandler from '@/hooks/useSlideHandler'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport HotkeyDoc from './HotkeyDoc.vue'\r\nimport { message } from 'ant-design-vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor-header',\r\n components: {\r\n HotkeyDoc,\r\n },\r\n setup() {\r\n const store = useStore()\r\n\r\n const { enterScreening, enterScreeningFromStart } = useScreening()\r\n const { createSlide, deleteSlide } = useSlideHandler()\r\n const { redo, undo } = useHistorySnapshot()\r\n\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const toggleGridLines = () => {\r\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\r\n }\r\n\r\n const resetSlides = () => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n store.commit(MutationTypes.SET_SLIDES, [{\r\n id: createRandomCode(),\r\n elements: [],\r\n }])\r\n }\r\n\r\n const openDoc = () => {\r\n message.warning('作者努力编写中...')\r\n }\r\n\r\n const hotkeyDrawerVisible = ref(false)\r\n\r\n return {\r\n enterScreening,\r\n enterScreeningFromStart,\r\n createSlide,\r\n deleteSlide,\r\n redo,\r\n undo,\r\n toggleGridLines,\r\n showGridLines,\r\n resetSlides,\r\n openDoc,\r\n hotkeyDrawerVisible,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=23ee4d75&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=23ee4d75&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-23ee4d75\"\n\nexport default script","<template>\r\n <div \r\n class=\"canvas\" \r\n ref=\"canvasRef\"\r\n @mousewheel=\"$event => mousewheelScaleCanvas($event)\"\r\n @mousedown=\"$event => handleClickBlankArea($event)\"\r\n v-contextmenu=\"contextmenus\"\r\n v-click-outside=\"removeEditorAreaFocus\"\r\n >\r\n <ElementCreateSelection\r\n v-if=\"creatingElement\"\r\n @created=\"data => insertElementFromCreateSelection(data)\"\r\n />\r\n <div \r\n class=\"viewport-wrapper\"\r\n :style=\"{\r\n width: viewportStyles.width * canvasScale + 'px',\r\n height: viewportStyles.height * canvasScale + 'px',\r\n left: viewportStyles.left + 'px',\r\n top: viewportStyles.top + 'px',\r\n }\"\r\n >\r\n <div class=\"operates\">\r\n <AlignmentLine \r\n v-for=\"(line, index) in alignmentLines\" \r\n :key=\"index\" \r\n :type=\"line.type\" \r\n :axis=\"line.axis\" \r\n :length=\"line.length\"\r\n />\r\n <MultiSelectOperate \r\n v-if=\"activeElementIdList.length > 1\"\r\n :elementList=\"elementList\"\r\n :scaleMultiElement=\"scaleMultiElement\"\r\n />\r\n <Operate\r\n v-for=\"element in elementList\" \r\n :key=\"element.id\"\r\n :elementInfo=\"element\"\r\n :isSelected=\"activeElementIdList.includes(element.id)\"\r\n :isActive=\"handleElementId === element.id\"\r\n :isActiveGroupElement=\"activeGroupElementId === element.id\"\r\n :isMultiSelect=\"activeElementIdList.length > 1\"\r\n :rotateElement=\"rotateElement\"\r\n :scaleElement=\"scaleElement\"\r\n :dragLineElement=\"dragLineElement\"\r\n />\r\n <SlideBackground />\r\n </div>\r\n\r\n <div \r\n class=\"viewport\" \r\n ref=\"viewportRef\"\r\n :style=\"{ transform: `scale(${canvasScale})` }\"\r\n >\r\n <MouseSelection \r\n v-if=\"mouseSelectionState.isShow\"\r\n :top=\"mouseSelectionState.top\" \r\n :left=\"mouseSelectionState.left\" \r\n :width=\"mouseSelectionState.width\" \r\n :height=\"mouseSelectionState.height\" \r\n :quadrant=\"mouseSelectionState.quadrant\"\r\n /> \r\n <EditableElement \r\n v-for=\"(element, index) in elementList\" \r\n :key=\"element.id\"\r\n :elementInfo=\"element\"\r\n :elementIndex=\"index + 1\"\r\n :isMultiSelect=\"activeElementIdList.length > 1\"\r\n :selectElement=\"selectElement\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, provide, ref, watch, watchEffect } from 'vue'\r\nimport throttle from 'lodash/throttle'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { AlignmentLineProps } from '@/types/edit'\r\nimport { removeAllRanges } from '@/utils/selection'\r\n\r\nimport useViewportSize from './hooks/useViewportSize'\r\nimport useMouseSelection from './hooks/useMouseSelection'\r\nimport useDropImageOrText from './hooks/useDropImageOrText'\r\nimport useRotateElement from './hooks/useRotateElement'\r\nimport useScaleElement from './hooks/useScaleElement'\r\nimport useSelectElement from './hooks/useSelectElement'\r\nimport useDragElement from './hooks/useDragElement'\r\nimport useDragLineElement from './hooks/useDragLineElement'\r\nimport useInsertFromCreateSelection from './hooks/useInsertFromCreateSelection'\r\n\r\nimport useDeleteElement from '@/hooks/useDeleteElement'\r\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\r\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\r\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport EditableElement from './EditableElement.vue'\r\nimport MouseSelection from './MouseSelection.vue'\r\nimport SlideBackground from './SlideBackground.vue'\r\nimport AlignmentLine from './AlignmentLine.vue'\r\nimport ElementCreateSelection from './ElementCreateSelection.vue'\r\nimport MultiSelectOperate from './Operate/MultiSelectOperate.vue'\r\nimport Operate from './Operate/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor-canvas',\r\n components: {\r\n EditableElement,\r\n MouseSelection,\r\n SlideBackground,\r\n AlignmentLine,\r\n ElementCreateSelection,\r\n MultiSelectOperate,\r\n Operate,\r\n },\r\n setup() {\r\n const store = useStore()\r\n\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\r\n const ctrlKeyState = computed(() => store.state.ctrlKeyState)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n\r\n const viewportRef = ref<HTMLElement>()\r\n const alignmentLines = ref<AlignmentLineProps[]>([])\r\n\r\n const activeGroupElementId = ref('')\r\n watch(handleElementId, () => activeGroupElementId.value = '')\r\n\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n const elementList = ref<PPTElement[]>([])\r\n const setLocalElementList = () => {\r\n elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []\r\n }\r\n watchEffect(setLocalElementList)\r\n\r\n const canvasRef = ref<HTMLElement>()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const { viewportStyles } = useViewportSize(canvasRef)\r\n\r\n useDropImageOrText(canvasRef)\r\n\r\n const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef)\r\n\r\n const { dragElement } = useDragElement(elementList, activeGroupElementId, alignmentLines)\r\n const { dragLineElement } = useDragLineElement(elementList)\r\n const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)\r\n const { scaleElement, scaleMultiElement } = useScaleElement(elementList, activeGroupElementId, alignmentLines)\r\n const { rotateElement } = useRotateElement(elementList, viewportRef)\r\n\r\n const { selectAllElement } = useSelectAllElement()\r\n const { deleteAllElements } = useDeleteElement()\r\n const { pasteElement } = useCopyAndPasteElement()\r\n const { enterScreening } = useScreening()\r\n\r\n // 点击画布的空白区域:清空焦点元素、设置画布焦点、清除文字选区\r\n const handleClickBlankArea = (e: MouseEvent) => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n if (!ctrlOrShiftKeyActive.value) updateMouseSelection(e)\r\n if (!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\r\n removeAllRanges()\r\n }\r\n\r\n // 移除画布编辑区域焦点\r\n const removeEditorAreaFocus = () => {\r\n if (editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)\r\n }\r\n\r\n // 按住Ctrl键滚动鼠标缩放画布\r\n const { scaleCanvas } = useScaleCanvas()\r\n const throttleScaleCanvas = throttle(scaleCanvas, 100, { leading: true, trailing: false })\r\n\r\n const mousewheelScaleCanvas = (e: WheelEvent) => {\r\n if (!ctrlKeyState.value) return\r\n\r\n e.preventDefault()\r\n if (e.deltaY > 0) throttleScaleCanvas('-')\r\n else if (e.deltaY < 0) throttleScaleCanvas('+')\r\n }\r\n\r\n // 开关网格线\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const toggleGridLines = () => {\r\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\r\n }\r\n\r\n // 在鼠标绘制的范围插入元素\r\n const creatingElement = computed(() => store.state.creatingElement)\r\n const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteElement,\r\n },\r\n {\r\n text: '全选',\r\n subText: 'Ctrl + A',\r\n handler: selectAllElement,\r\n },\r\n {\r\n text: '网格线',\r\n subText: showGridLines.value ? '√' : '',\r\n handler: toggleGridLines,\r\n },\r\n {\r\n text: '重置当前页',\r\n handler: deleteAllElements,\r\n },\r\n { divider: true },\r\n {\r\n text: '从当前页演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n provide('slideScale', canvasScale)\r\n\r\n return {\r\n elementList,\r\n activeElementIdList,\r\n handleElementId,\r\n activeGroupElementId,\r\n canvasRef,\r\n viewportRef,\r\n viewportStyles,\r\n canvasScale,\r\n mouseSelectionState,\r\n handleClickBlankArea,\r\n removeEditorAreaFocus,\r\n currentSlide,\r\n creatingElement,\r\n insertElementFromCreateSelection,\r\n alignmentLines,\r\n selectElement,\r\n rotateElement,\r\n scaleElement,\r\n dragLineElement,\r\n scaleMultiElement,\r\n mousewheelScaleCanvas,\r\n contextmenus,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.canvas {\r\n height: 100%;\r\n user-select: none;\r\n overflow: hidden;\r\n background-color: $lightGray;\r\n position: relative;\r\n}\r\n.viewport-wrapper {\r\n position: absolute;\r\n box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.1);\r\n}\r\n.viewport {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n transform-origin: 0 0;\r\n}\r\n</style>","import mitt, { Emitter } from 'mitt'\r\n\r\nexport const enum EmitterEvents {\r\n UPDATE_TEXT_STATE = 'UPDATE_TEXT_STATE',\r\n EXEC_TEXT_COMMAND = 'EXEC_TEXT_COMMAND',\r\n UPDATE_TABLE_SELECTED_CELL = 'UPDATE_TABLE_SELECTED_CELL',\r\n SCALE_ELEMENT_STATE = 'SCALE_ELEMENT_STATE',\r\n}\r\n\r\nconst emitter: Emitter = mitt()\r\n\r\nexport default emitter","// 清除文字选区\r\nexport const removeAllRanges = () => {\r\n const selection = window.getSelection()\r\n selection && selection.removeAllRanges()\r\n}","import { ref, computed, onMounted, onUnmounted, Ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\n\r\nexport default (canvasRef: Ref<HTMLElement | undefined>) => {\r\n const viewportLeft = ref(0)\r\n const viewportTop = ref(0)\r\n\r\n const store = useStore()\r\n const canvasPercentage = computed(() => store.state.canvasPercentage)\r\n\r\n // 计算画布可视区域的位置\r\n const setViewportPosition = () => {\r\n if (!canvasRef.value) return\r\n const canvasWidth = canvasRef.value.clientWidth\r\n const canvasHeight = canvasRef.value.clientHeight\r\n\r\n if (canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {\r\n const viewportActualWidth = canvasWidth * (canvasPercentage.value / 100)\r\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualWidth / VIEWPORT_SIZE)\r\n viewportLeft.value = (canvasWidth - viewportActualWidth) / 2\r\n viewportTop.value = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2\r\n }\r\n else {\r\n const viewportActualHeight = canvasHeight * (canvasPercentage.value / 100)\r\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO))\r\n viewportLeft.value = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2\r\n viewportTop.value = (canvasHeight - viewportActualHeight) / 2\r\n }\r\n }\r\n\r\n // 可视区域缩放时,更新可视区域的位置\r\n watch(canvasPercentage, setViewportPosition)\r\n\r\n // 画布可视区域位置和大小的样式\r\n const viewportStyles = computed(() => ({\r\n width: VIEWPORT_SIZE,\r\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\r\n left: viewportLeft.value,\r\n top: viewportTop.value,\r\n }))\r\n\r\n // 监听画布尺寸发生变化时,更新可视区域的位置\r\n const resizeObserver = new ResizeObserver(setViewportPosition)\r\n\r\n onMounted(() => {\r\n if (canvasRef.value) resizeObserver.observe(canvasRef.value)\r\n })\r\n onUnmounted(() => {\r\n if (canvasRef.value) resizeObserver.unobserve(canvasRef.value)\r\n })\r\n\r\n return {\r\n viewportStyles,\r\n }\r\n}","import { PPTElement } from '@/types/slides'\r\n\r\ninterface RotatedElementData {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n rotate: number;\r\n}\r\n\r\n/**\r\n * 计算元素在画布中的矩形范围旋转后的新位置范围\r\n * @param element 元素的位置大小和旋转角度信息\r\n */\r\nexport const getRectRotatedRange = (element: RotatedElementData) => {\r\n const { left, top, width, height, rotate = 0 } = element\r\n\r\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\r\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\r\n\r\n const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180\r\n const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180\r\n\r\n const middleLeft = left + width / 2\r\n const middleTop = top + height / 2\r\n\r\n const xAxis = [\r\n middleLeft + radius * Math.cos(tlbraRadian),\r\n middleLeft + radius * Math.cos(trblaRadian),\r\n middleLeft - radius * Math.cos(tlbraRadian),\r\n middleLeft - radius * Math.cos(trblaRadian),\r\n ]\r\n const yAxis = [\r\n middleTop - radius * Math.sin(tlbraRadian),\r\n middleTop - radius * Math.sin(trblaRadian),\r\n middleTop + radius * Math.sin(tlbraRadian),\r\n middleTop + radius * Math.sin(trblaRadian),\r\n ]\r\n\r\n return {\r\n xRange: [Math.min(...xAxis), Math.max(...xAxis)],\r\n yRange: [Math.min(...yAxis), Math.max(...yAxis)],\r\n }\r\n}\r\n\r\n/**\r\n * 计算元素在画布中的位置范围\r\n * @param element 元素信息\r\n */\r\nexport const getElementRange = (element: PPTElement) => {\r\n let minX, maxX, minY, maxY\r\n\r\n if (element.type === 'line') {\r\n minX = element.left\r\n maxX = element.left + Math.max(element.start[0], element.end[0])\r\n minY = element.top\r\n maxY = element.top + Math.max(element.start[1], element.end[1])\r\n }\r\n else if ('rotate' in element && element.rotate) {\r\n const { left, top, width, height, rotate } = element\r\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\r\n minX = xRange[0]\r\n maxX = xRange[1]\r\n minY = yRange[0]\r\n maxY = yRange[1]\r\n }\r\n else {\r\n minX = element.left\r\n maxX = element.left + element.width\r\n minY = element.top\r\n maxY = element.top + element.height\r\n }\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\n/**\r\n * 计算一组元素在画布中的位置范围\r\n * @param elementList 一组元素信息\r\n */\r\nexport const getElementListRange = (elementList: PPTElement[]) => {\r\n const leftValues: number[] = []\r\n const topValues: number[] = []\r\n const rightValues: number[] = []\r\n const bottomValues: number[] = []\r\n\r\n elementList.forEach(element => {\r\n const { minX, maxX, minY, maxY } = getElementRange(element)\r\n leftValues.push(minX)\r\n topValues.push(minY)\r\n rightValues.push(maxX)\r\n bottomValues.push(maxY)\r\n })\r\n\r\n const minX = Math.min(...leftValues)\r\n const maxX = Math.max(...rightValues)\r\n const minY = Math.min(...topValues)\r\n const maxY = Math.max(...bottomValues)\r\n\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\nexport interface AlignLine {\r\n value: number;\r\n range: [number, number];\r\n}\r\n\r\n/**\r\n * 将一组对齐吸附线进行去重:同位置的的多条对齐吸附线仅留下一条,取该位置所有对齐吸附线的最大值和最小值为新的范围\r\n * @param lines 一组对齐吸附线信息\r\n */\r\nexport const uniqAlignLines = (lines: AlignLine[]) => {\r\n const uniqLines: AlignLine[] = []\r\n lines.forEach(line => {\r\n const index = uniqLines.findIndex(_line => _line.value === line.value)\r\n if (index === -1) uniqLines.push(line)\r\n else {\r\n const uniqLine = uniqLines[index]\r\n const rangeMin = Math.min(uniqLine.range[0], line.range[0])\r\n const rangeMax = Math.max(uniqLine.range[1], line.range[1])\r\n const range: [number, number] = [rangeMin, rangeMax]\r\n const _line = { value: line.value, range }\r\n uniqLines[index] = _line\r\n }\r\n })\r\n return uniqLines\r\n}","import { Ref, reactive, computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { getElementRange } from '@/utils/element'\r\n\r\nexport default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | undefined>) => {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const mouseSelectionState = reactive({\r\n isShow: false,\r\n top: 0,\r\n left: 0,\r\n width: 0,\r\n height: 0,\r\n quadrant: 1,\r\n })\r\n\r\n // 更新鼠标框选范围\r\n const updateMouseSelection = (e: MouseEvent) => {\r\n if (!viewportRef.value) return\r\n\r\n let isMouseDown = true\r\n const viewportRect = viewportRef.value.getBoundingClientRect()\r\n\r\n const minSelectionRange = 5\r\n \r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n const left = (startPageX - viewportRect.x) / canvasScale.value\r\n const top = (startPageY - viewportRect.y) / canvasScale.value\r\n\r\n // 确定框选的起始位置和其他默认值初始化\r\n mouseSelectionState.isShow = false\r\n mouseSelectionState.quadrant = 4\r\n mouseSelectionState.top = top\r\n mouseSelectionState.left = left\r\n mouseSelectionState.width = 0\r\n mouseSelectionState.height = 0\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const offsetWidth = (currentPageX - startPageX) / canvasScale.value\r\n const offsetHeight = (currentPageY - startPageY) / canvasScale.value\r\n\r\n const width = Math.abs(offsetWidth)\r\n const height = Math.abs(offsetHeight)\r\n\r\n if ( width < minSelectionRange || height < minSelectionRange ) return\r\n \r\n // 计算鼠标框选(移动)的方向\r\n // 按四个象限的位置区分,如右下角为第四象限\r\n let quadrant = 0\r\n if ( offsetWidth > 0 && offsetHeight > 0 ) quadrant = 4\r\n else if ( offsetWidth < 0 && offsetHeight < 0 ) quadrant = 1\r\n else if ( offsetWidth > 0 && offsetHeight < 0 ) quadrant = 2\r\n else if ( offsetWidth < 0 && offsetHeight > 0 ) quadrant = 3\r\n\r\n // 更新框选范围\r\n mouseSelectionState.isShow = true\r\n mouseSelectionState.quadrant = quadrant\r\n mouseSelectionState.width = width\r\n mouseSelectionState.height = height\r\n }\r\n\r\n document.onmouseup = () => {\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n isMouseDown = false\r\n\r\n // 计算画布中的元素是否处在鼠标选择范围中,处在范围中的元素设置为被选中状态\r\n let inRangeElementList: PPTElement[] = []\r\n for (let i = 0; i < elementList.value.length; i++) {\r\n const element = elementList.value[i]\r\n const mouseSelectionLeft = mouseSelectionState.left\r\n const mouseSelectionTop = mouseSelectionState.top\r\n const mouseSelectionWidth = mouseSelectionState.width\r\n const mouseSelectionHeight = mouseSelectionState.height\r\n\r\n const quadrant = mouseSelectionState.quadrant\r\n\r\n const { minX, maxX, minY, maxY } = getElementRange(element)\r\n\r\n // 计算元素是否处在框选范围内时,四个框选方向的计算方式有差异\r\n let isInclude = false\r\n if (quadrant === 4) {\r\n isInclude = minX > mouseSelectionLeft && \r\n maxX < mouseSelectionLeft + mouseSelectionWidth && \r\n minY > mouseSelectionTop && \r\n maxY < mouseSelectionTop + mouseSelectionHeight\r\n }\r\n else if (quadrant === 1) {\r\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \r\n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \r\n minY > (mouseSelectionTop - mouseSelectionHeight) && \r\n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\r\n }\r\n else if (quadrant === 2) {\r\n isInclude = minX > mouseSelectionLeft && \r\n maxX < mouseSelectionLeft + mouseSelectionWidth && \r\n minY > (mouseSelectionTop - mouseSelectionHeight) && \r\n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\r\n }\r\n else if (quadrant === 3) {\r\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \r\n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \r\n minY > mouseSelectionTop && \r\n maxY < mouseSelectionTop + mouseSelectionHeight\r\n }\r\n\r\n // 被锁定的元素即使在范围内,也不需要设置为选中状态\r\n if (isInclude && !element.lock) inRangeElementList.push(element)\r\n }\r\n\r\n // 如果范围内有组合元素的成员,需要该组全部成员都处在范围内,才会被设置为选中状态\r\n inRangeElementList = inRangeElementList.filter(inRangeElement => {\r\n if (inRangeElement.groupId) {\r\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\r\n const groupElementList = elementList.value.filter(element => element.groupId === inRangeElement.groupId)\r\n return groupElementList.every(groupElement => inRangeElementIdList.includes(groupElement.id))\r\n }\r\n return true\r\n })\r\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\r\n if (inRangeElementIdList.length) store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, inRangeElementIdList)\r\n\r\n mouseSelectionState.isShow = false\r\n }\r\n }\r\n\r\n return {\r\n mouseSelectionState,\r\n updateMouseSelection,\r\n }\r\n}","import { computed, onMounted, onUnmounted, Ref } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport useCreateElement from '@/hooks/useCreateElement'\r\n\r\nexport default (elementRef: Ref<HTMLElement | undefined>) => {\r\n const store = useStore()\r\n const disableHotkeys = computed(() => store.state.disableHotkeys)\r\n\r\n const { createImageElement, createTextElement } = useCreateElement()\r\n\r\n // 拖拽元素到画布中\r\n const handleDrop = (e: DragEvent) => {\r\n if (!e.dataTransfer) return\r\n const dataTransferItem = e.dataTransfer.items[0]\r\n\r\n // 检查事件对象中是否存在图片,存在则插入图片,否则继续检查是否存在文字,存在则插入文字\r\n if (dataTransferItem.kind === 'file' && dataTransferItem.type.indexOf('image') !== -1) {\r\n const imageFile = dataTransferItem.getAsFile()\r\n if (imageFile) {\r\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\r\n }\r\n }\r\n else if (dataTransferItem.kind === 'string' && dataTransferItem.type === 'text/plain') {\r\n dataTransferItem.getAsString(text => {\r\n if (disableHotkeys.value) return\r\n createTextElement({\r\n left: 0,\r\n top: 0,\r\n width: 600,\r\n height: 50,\r\n }, text)\r\n })\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n elementRef.value && elementRef.value.addEventListener('drop', handleDrop)\r\n\r\n document.ondragleave = e => e.preventDefault()\r\n document.ondrop = e => e.preventDefault()\r\n document.ondragenter = e => e.preventDefault()\r\n document.ondragover = e => e.preventDefault()\r\n })\r\n onUnmounted(() => {\r\n elementRef.value && elementRef.value.removeEventListener('drop', handleDrop)\r\n\r\n document.ondragleave = null\r\n document.ondrop = null\r\n document.ondragenter = null\r\n document.ondragover = null\r\n })\r\n}","import { Ref, computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\n/**\r\n * 计算给定坐标到原点连线的弧度\r\n * @param x 坐标x\r\n * @param y 坐标y\r\n */\r\nconst getAngleFromCoordinate = (x: number, y: number) => {\r\n const radian = Math.atan2(x, y)\r\n const angle = 180 / Math.PI * radian\r\n return angle\r\n}\r\n\r\nexport default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | undefined>) => {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 旋转元素\r\n const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {\r\n let isMouseDown = true\r\n let angle = 0\r\n const elOriginRotate = element.rotate || 0\r\n\r\n const elLeft = element.left\r\n const elTop = element.top\r\n const elWidth = element.width\r\n const elHeight = element.height\r\n\r\n // 元素中心点(旋转中心点)\r\n const centerX = elLeft + elWidth / 2\r\n const centerY = elTop + elHeight / 2\r\n\r\n if (!viewportRef.value) return\r\n const viewportRect = viewportRef.value.getBoundingClientRect()\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n \r\n // 计算当前鼠标位置相对元素中心点连线的角度(弧度)\r\n const mouseX = (e.pageX - viewportRect.left) / canvasScale.value\r\n const mouseY = (e.pageY - viewportRect.top) / canvasScale.value\r\n const x = mouseX - centerX\r\n const y = centerY - mouseY\r\n\r\n angle = getAngleFromCoordinate(x, y)\r\n\r\n // 靠近45倍数的角度时有吸附效果\r\n const sorptionRange = 5\r\n if ( Math.abs(angle) <= sorptionRange ) angle = 0\r\n else if ( angle > 0 && Math.abs(angle - 45) <= sorptionRange ) angle -= (angle - 45)\r\n else if ( angle < 0 && Math.abs(angle + 45) <= sorptionRange ) angle -= (angle + 45)\r\n else if ( angle > 0 && Math.abs(angle - 90) <= sorptionRange ) angle -= (angle - 90)\r\n else if ( angle < 0 && Math.abs(angle + 90) <= sorptionRange ) angle -= (angle + 90)\r\n else if ( angle > 0 && Math.abs(angle - 135) <= sorptionRange ) angle -= (angle - 135)\r\n else if ( angle < 0 && Math.abs(angle + 135) <= sorptionRange ) angle -= (angle + 135)\r\n else if ( angle > 0 && Math.abs(angle - 180) <= sorptionRange ) angle -= (angle - 180)\r\n else if ( angle < 0 && Math.abs(angle + 180) <= sorptionRange ) angle -= (angle + 180)\r\n\r\n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, rotate: angle } : el)\r\n }\r\n\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n if (elOriginRotate === angle) return\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\r\n addHistorySnapshot()\r\n }\r\n }\r\n\r\n return {\r\n rotateElement,\r\n }\r\n}","export const ELEMENT_TYPE_ZH = {\r\n text: '文本',\r\n image: '图片',\r\n shape: '形状',\r\n line: '线条',\r\n chart: '图表',\r\n table: '表格',\r\n}\r\n\r\nexport const MIN_SIZE = {\r\n text: 20,\r\n image: 20,\r\n shape: 15,\r\n chart: 200,\r\n table: 20,\r\n}","import { computed, Ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'\r\nimport { OperateResizeHandlers, AlignmentLineProps, MultiSelectRange } from '@/types/edit'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport { MIN_SIZE } from '@/configs/element'\r\nimport { AlignLine, uniqAlignLines } from '@/utils/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\ninterface RotateElementData {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/**\r\n * 计算旋转后的元素八个缩放点的位置\r\n * @param element 元素原始位置大小信息\r\n * @param angle 旋转角度\r\n */\r\nconst getRotateElementPoints = (element: RotateElementData, angle: number) => {\r\n const { left, top, width, height } = element\r\n\r\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\r\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\r\n\r\n const tlbraRadian = (180 - angle - auxiliaryAngle) * Math.PI / 180\r\n const trblaRadian = (auxiliaryAngle - angle) * Math.PI / 180\r\n const taRadian = (90 - angle) * Math.PI / 180\r\n const raRadian = angle * Math.PI / 180\r\n\r\n const halfWidth = width / 2\r\n const halfHeight = height / 2\r\n\r\n const middleLeft = left + halfWidth\r\n const middleTop = top + halfHeight\r\n\r\n const leftTopPoint = {\r\n left: middleLeft + radius * Math.cos(tlbraRadian),\r\n top: middleTop - radius * Math.sin(tlbraRadian),\r\n }\r\n const topPoint = {\r\n left: middleLeft + halfHeight * Math.cos(taRadian),\r\n top: middleTop - halfHeight * Math.sin(taRadian),\r\n }\r\n const rightTopPoint = {\r\n left: middleLeft + radius * Math.cos(trblaRadian),\r\n top: middleTop - radius * Math.sin(trblaRadian),\r\n }\r\n const rightPoint = {\r\n left: middleLeft + halfWidth * Math.cos(raRadian),\r\n top: middleTop + halfWidth * Math.sin(raRadian),\r\n }\r\n const rightBottomPoint = {\r\n left: middleLeft - radius * Math.cos(tlbraRadian),\r\n top: middleTop + radius * Math.sin(tlbraRadian),\r\n }\r\n const bottomPoint = {\r\n left: middleLeft - halfHeight * Math.sin(raRadian),\r\n top: middleTop + halfHeight * Math.cos(raRadian),\r\n }\r\n const leftBottomPoint = {\r\n left: middleLeft - radius * Math.cos(trblaRadian),\r\n top: middleTop + radius * Math.sin(trblaRadian),\r\n }\r\n const leftPoint = {\r\n left: middleLeft - halfWidth * Math.cos(raRadian),\r\n top: middleTop - halfWidth * Math.sin(raRadian),\r\n }\r\n\r\n return { leftTopPoint, topPoint, rightTopPoint, rightPoint, rightBottomPoint, bottomPoint, leftBottomPoint, leftPoint }\r\n}\r\n\r\n/**\r\n * 获取元素某缩放点相对的另一个点的位置,如:【上】对应【下】、【左上】对应【右下】\r\n * @param direction 当前操作的缩放点\r\n * @param points 旋转后的元素八个缩放点的位置\r\n */\r\nconst getOppositePoint = (direction: string, points: ReturnType<typeof getRotateElementPoints>): { left: number; top: number } => {\r\n const oppositeMap = {\r\n [OperateResizeHandlers.RIGHT_BOTTOM]: points.leftTopPoint,\r\n [OperateResizeHandlers.LEFT_BOTTOM]: points.rightTopPoint,\r\n [OperateResizeHandlers.LEFT_TOP]: points.rightBottomPoint,\r\n [OperateResizeHandlers.RIGHT_TOP]: points.leftBottomPoint,\r\n [OperateResizeHandlers.TOP]: points.bottomPoint,\r\n [OperateResizeHandlers.BOTTOM]: points.topPoint,\r\n [OperateResizeHandlers.LEFT]: points.rightPoint,\r\n [OperateResizeHandlers.RIGHT]: points.leftPoint,\r\n }\r\n return oppositeMap[direction]\r\n}\r\n\r\nexport default (\r\n elementList: Ref<PPTElement[]>,\r\n activeGroupElementId: Ref<string>,\r\n alignmentLines: Ref<AlignmentLineProps[]>,\r\n) => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 缩放元素\r\n const scaleElement = (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: OperateResizeHandlers) => {\r\n let isMouseDown = true\r\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, true)\r\n\r\n const elOriginLeft = element.left\r\n const elOriginTop = element.top\r\n const elOriginWidth = element.width\r\n const elOriginHeight = element.height\r\n \r\n const elRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\r\n const rotateRadian = Math.PI * elRotate / 180\r\n\r\n const fixedRatio = ctrlOrShiftKeyActive.value || ('fixedRatio' in element && element.fixedRatio)\r\n const aspectRatio = elOriginWidth / elOriginHeight\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n // 元素最小缩放限制\r\n const minSize = MIN_SIZE[element.type] || 20\r\n const getSizeWithinRange = (size: number) => size < minSize ? minSize : size\r\n\r\n let points: ReturnType<typeof getRotateElementPoints>\r\n let baseLeft = 0\r\n let baseTop = 0\r\n let horizontalLines: AlignLine[] = []\r\n let verticalLines: AlignLine[] = []\r\n\r\n // 旋转后的元素进行缩放时,引入基点的概念,以当前操作的缩放点相对的点为基点\r\n // 例如拖动右下角缩放时,左上角为基点,需要保持左上角不变然后修改其他的点的位置来达到所放的效果\r\n if ('rotate' in element && element.rotate) {\r\n const { left, top, width, height } = element\r\n points = getRotateElementPoints({ left, top, width, height }, elRotate)\r\n const oppositePoint = getOppositePoint(command, points)\r\n\r\n baseLeft = oppositePoint.left\r\n baseTop = oppositePoint.top\r\n }\r\n\r\n // 未旋转的元素具有缩放时的对齐吸附功能,在这处收集对齐对齐吸附线\r\n // 包括页面内除目标元素外的其他元素在画布中的各个可吸附对齐位置:上下左右四边\r\n // 其中线条和被旋转过的元素不参与吸附对齐\r\n else {\r\n const edgeWidth = VIEWPORT_SIZE\r\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n const isActiveGroupElement = element.id === activeGroupElementId.value\r\n \r\n for (const el of elementList.value) {\r\n if ('rotate' in el && el.rotate) continue\r\n if (el.type === 'line') continue\r\n if (isActiveGroupElement && el.id === element.id) continue\r\n if (!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\r\n\r\n const left = el.left\r\n const top = el.top\r\n const width = el.width\r\n const height = el.height\r\n const right = left + width\r\n const bottom = top + height\r\n\r\n const topLine: AlignLine = { value: top, range: [left, right] }\r\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\r\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\r\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\r\n\r\n horizontalLines.push(topLine, bottomLine)\r\n verticalLines.push(leftLine, rightLine)\r\n }\r\n\r\n // 画布可视区域的四个边界、水平中心、垂直中心\r\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\r\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\r\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\r\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\r\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\r\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\r\n\r\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\r\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\r\n \r\n horizontalLines = uniqAlignLines(horizontalLines)\r\n verticalLines = uniqAlignLines(verticalLines)\r\n }\r\n \r\n // 对齐吸附方法\r\n // 将收集到的对齐吸附线与计算的目标元素当前的位置大小相关数据做对比,差值小于设定的值时执行自动缩放校正\r\n // 水平和垂直两个方向需要分开计算\r\n const alignedAdsorption = (currentX: number | null, currentY: number | null) => {\r\n const sorptionRange = 5\r\n\r\n const _alignmentLines: AlignmentLineProps[] = []\r\n let isVerticalAdsorbed = false\r\n let isHorizontalAdsorbed = false\r\n const correctionVal = { offsetX: 0, offsetY: 0 }\r\n \r\n if (currentY || currentY === 0) {\r\n for (let i = 0; i < horizontalLines.length; i++) {\r\n const { value, range } = horizontalLines[i]\r\n const min = Math.min(...range, currentX || 0)\r\n const max = Math.max(...range, currentX || 0)\r\n \r\n if (Math.abs(currentY - value) < sorptionRange && !isHorizontalAdsorbed) {\r\n correctionVal.offsetY = currentY - value\r\n isHorizontalAdsorbed = true\r\n _alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })\r\n }\r\n }\r\n }\r\n if (currentX || currentX === 0) {\r\n for (let i = 0; i < verticalLines.length; i++) {\r\n const { value, range } = verticalLines[i]\r\n const min = Math.min(...range, (currentY || 0))\r\n const max = Math.max(...range, (currentY || 0))\r\n\r\n if (Math.abs(currentX - value) < sorptionRange && !isVerticalAdsorbed) {\r\n correctionVal.offsetX = currentX - value\r\n isVerticalAdsorbed = true\r\n _alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })\r\n }\r\n }\r\n }\r\n alignmentLines.value = _alignmentLines\r\n return correctionVal\r\n }\r\n\r\n // 开始缩放\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const x = currentPageX - startPageX\r\n const y = currentPageY - startPageY\r\n\r\n let width = elOriginWidth\r\n let height = elOriginHeight\r\n let left = elOriginLeft\r\n let top = elOriginTop\r\n \r\n // 元素被旋转的情况下,需要根据元素旋转的角度,重新计算需要缩放的距离(鼠标按下后移动的距离)\r\n if (elRotate) {\r\n const revisedX = (Math.cos(rotateRadian) * x + Math.sin(rotateRadian) * y) / canvasScale.value\r\n let revisedY = (Math.cos(rotateRadian) * y - Math.sin(rotateRadian) * x) / canvasScale.value\r\n\r\n // 锁定宽高比例(仅四个角可能触发,四条边不会触发)\r\n // 以水平方向上缩放的距离为基础,计算垂直方向上的缩放距离,保持二者具有相同的缩放比例\r\n if (fixedRatio) {\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) revisedY = revisedX / aspectRatio\r\n if (command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) revisedY = -revisedX / aspectRatio\r\n }\r\n\r\n // 根据不同的操作点分别计算元素缩放后的大小和位置\r\n // 需要注意:\r\n // 此处计算的位置需要在后面重新进行校正,因为旋转后再缩放事实上会改变元素基点的位置(虽然视觉上基点保持不动,但这是【旋转】+【移动】共同作用的结果)\r\n // 但此处计算的大小不需要重新校正,因为前面已经重新计算需要缩放的距离,相当于大小已经经过了校正\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM) {\r\n width = getSizeWithinRange(elOriginWidth + revisedX)\r\n height = getSizeWithinRange(elOriginHeight + revisedY)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_BOTTOM) {\r\n width = getSizeWithinRange(elOriginWidth - revisedX)\r\n height = getSizeWithinRange(elOriginHeight + revisedY)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_TOP) {\r\n width = getSizeWithinRange(elOriginWidth - revisedX)\r\n height = getSizeWithinRange(elOriginHeight - revisedY)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT_TOP) {\r\n width = getSizeWithinRange(elOriginWidth + revisedX)\r\n height = getSizeWithinRange(elOriginHeight - revisedY)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.TOP) {\r\n height = getSizeWithinRange(elOriginHeight - revisedY)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.BOTTOM) {\r\n height = getSizeWithinRange(elOriginHeight + revisedY)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT) {\r\n width = getSizeWithinRange(elOriginWidth - revisedX)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT) {\r\n width = getSizeWithinRange(elOriginWidth + revisedX)\r\n }\r\n\r\n // 获取当前元素的基点坐标,与初始状态时的基点坐标进行对比,并计算差值进行元素位置的校正\r\n const currentPoints = getRotateElementPoints({ width, height, left, top }, elRotate)\r\n const currentOppositePoint = getOppositePoint(command, currentPoints)\r\n const currentBaseLeft = currentOppositePoint.left\r\n const currentBaseTop = currentOppositePoint.top\r\n\r\n const offsetX = currentBaseLeft - baseLeft\r\n const offsetY = currentBaseTop - baseTop\r\n\r\n left = left - offsetX\r\n top = top - offsetY\r\n }\r\n\r\n // 元素未被旋转的情况下,正常计算新的位置大小即可,无需复杂的校正等工作\r\n // 额外需要处理对齐吸附相关的操作\r\n // 锁定宽高比例相关的操作同上,不再赘述\r\n else {\r\n let moveX = x / canvasScale.value\r\n let moveY = y / canvasScale.value\r\n\r\n if (fixedRatio) {\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) moveY = moveX / aspectRatio\r\n if (command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) moveY = -moveX / aspectRatio\r\n }\r\n\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM) {\r\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + elOriginHeight + moveY)\r\n moveX = moveX - offsetX\r\n moveY = moveY - offsetY\r\n if (fixedRatio) {\r\n if (offsetY) moveX = moveY * aspectRatio\r\n else moveY = moveX / aspectRatio\r\n }\r\n width = getSizeWithinRange(elOriginWidth + moveX)\r\n height = getSizeWithinRange(elOriginHeight + moveY)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_BOTTOM) {\r\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + elOriginHeight + moveY)\r\n moveX = moveX - offsetX\r\n moveY = moveY - offsetY\r\n if (fixedRatio) {\r\n if (offsetY) moveX = -moveY * aspectRatio\r\n else moveY = -moveX / aspectRatio\r\n }\r\n width = getSizeWithinRange(elOriginWidth - moveX)\r\n height = getSizeWithinRange(elOriginHeight + moveY)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_TOP) {\r\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + moveY)\r\n moveX = moveX - offsetX\r\n moveY = moveY - offsetY\r\n if (fixedRatio) {\r\n if (offsetY) moveX = moveY * aspectRatio\r\n else moveY = moveX / aspectRatio\r\n }\r\n width = getSizeWithinRange(elOriginWidth - moveX)\r\n height = getSizeWithinRange(elOriginHeight - moveY)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT_TOP) {\r\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + moveY)\r\n moveX = moveX - offsetX\r\n moveY = moveY - offsetY\r\n if (fixedRatio) {\r\n if (offsetY) moveX = -moveY * aspectRatio\r\n else moveY = -moveX / aspectRatio\r\n }\r\n width = getSizeWithinRange(elOriginWidth + moveX)\r\n height = getSizeWithinRange(elOriginHeight - moveY)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.LEFT) {\r\n const { offsetX } = alignedAdsorption(elOriginLeft + moveX, null)\r\n moveX = moveX - offsetX\r\n width = getSizeWithinRange(elOriginWidth - moveX)\r\n left = elOriginLeft - (width - elOriginWidth)\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT) {\r\n const { offsetX } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, null)\r\n moveX = moveX - offsetX\r\n width = getSizeWithinRange(elOriginWidth + moveX)\r\n }\r\n else if (command === OperateResizeHandlers.TOP) {\r\n const { offsetY } = alignedAdsorption(null, elOriginTop + moveY)\r\n moveY = moveY - offsetY\r\n height = getSizeWithinRange(elOriginHeight - moveY)\r\n top = elOriginTop - (height - elOriginHeight)\r\n }\r\n else if (command === OperateResizeHandlers.BOTTOM) {\r\n const { offsetY } = alignedAdsorption(null, elOriginTop + elOriginHeight + moveY)\r\n moveY = moveY - offsetY\r\n height = getSizeWithinRange(elOriginHeight + moveY)\r\n }\r\n }\r\n \r\n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, left, top, width, height } : el)\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n alignmentLines.value = []\r\n \r\n if (startPageX === e.pageX && startPageY === e.pageY) return\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\r\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, false)\r\n \r\n addHistorySnapshot()\r\n }\r\n }\r\n\r\n // 多选元素缩放\r\n const scaleMultiElement = (e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandlers) => {\r\n let isMouseDown = true\r\n \r\n const { minX, maxX, minY, maxY } = range\r\n const operateWidth = maxX - minX\r\n const operateHeight = maxY - minY\r\n const aspectRatio = operateWidth / operateHeight\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n \r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const x = (currentPageX - startPageX) / canvasScale.value\r\n let y = (currentPageY - startPageY) / canvasScale.value\r\n\r\n // 锁定宽高比例,逻辑同上\r\n if (ctrlOrShiftKeyActive.value) {\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) y = x / aspectRatio\r\n if (command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) y = -x / aspectRatio\r\n }\r\n\r\n // 所有选中元素的整体范围\r\n let currentMinX = minX\r\n let currentMaxX = maxX\r\n let currentMinY = minY\r\n let currentMaxY = maxY\r\n\r\n if (command === OperateResizeHandlers.RIGHT_BOTTOM) {\r\n currentMaxX = maxX + x\r\n currentMaxY = maxY + y\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_BOTTOM) {\r\n currentMinX = minX + x\r\n currentMaxY = maxY + y\r\n }\r\n else if (command === OperateResizeHandlers.LEFT_TOP) {\r\n currentMinX = minX + x\r\n currentMinY = minY + y\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT_TOP) {\r\n currentMaxX = maxX + x\r\n currentMinY = minY + y\r\n }\r\n else if (command === OperateResizeHandlers.TOP) {\r\n currentMinY = minY + y\r\n }\r\n else if (command === OperateResizeHandlers.BOTTOM) {\r\n currentMaxY = maxY + y\r\n }\r\n else if (command === OperateResizeHandlers.LEFT) {\r\n currentMinX = minX + x\r\n }\r\n else if (command === OperateResizeHandlers.RIGHT) {\r\n currentMaxX = maxX + x\r\n }\r\n\r\n // 所有选中元素的整体宽高\r\n const currentOppositeWidth = currentMaxX - currentMinX\r\n const currentOppositeHeight = currentMaxY - currentMinY\r\n\r\n // 当前正在操作元素宽高占所有选中元素的整体宽高的比例\r\n let widthScale = currentOppositeWidth / operateWidth\r\n let heightScale = currentOppositeHeight / operateHeight\r\n\r\n if (widthScale <= 0) widthScale = 0\r\n if (heightScale <= 0) heightScale = 0\r\n \r\n // 根据前面计算的比例,计算并修改所有选中元素的位置大小\r\n elementList.value = elementList.value.map(el => {\r\n if ((el.type === 'image' || el.type === 'shape') && activeElementIdList.value.includes(el.id)) {\r\n const originElement = originElementList.find(originEl => originEl.id === el.id) as PPTImageElement | PPTShapeElement\r\n return {\r\n ...el,\r\n width: originElement.width * widthScale,\r\n height: originElement.height * heightScale,\r\n left: currentMinX + (originElement.left - minX) * widthScale,\r\n top: currentMinY + (originElement.top - minY) * heightScale,\r\n }\r\n }\r\n return el\r\n })\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n if (startPageX === e.pageX && startPageY === e.pageY) return\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\r\n addHistorySnapshot()\r\n }\r\n }\r\n\r\n return {\r\n scaleElement,\r\n scaleMultiElement,\r\n }\r\n}","import { Ref, computed } from 'vue'\r\nimport uniq from 'lodash/uniq'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\n\r\nexport default (\r\n elementList: Ref<PPTElement[]>,\r\n activeGroupElementId: Ref<string>,\r\n moveElement: (e: MouseEvent, element: PPTElement) => void,\r\n) => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n\r\n // 选中元素\r\n const selectElement = (e: MouseEvent, element: PPTElement, canMove = true) => {\r\n if (!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\r\n\r\n // 如果目标元素当前未被选中,则将他设为选中状态\r\n // 此时如果按下Ctrl键或Shift键,则进入多选状态,将当前已选中的元素和目标元素一桶设置为选中状态,否则仅将目标元素设置为选中状态\r\n // 如果目标元素是分组成员,需要将该组合的其他元素一起设置为选中状态\r\n if (!activeElementIdList.value.includes(element.id)) {\r\n let newActiveIdList: string[] = []\r\n\r\n if (ctrlOrShiftKeyActive.value) {\r\n newActiveIdList = [...activeElementIdList.value, element.id]\r\n }\r\n else newActiveIdList = [element.id]\r\n \r\n if (element.groupId) {\r\n const groupMembersId: string[] = []\r\n elementList.value.forEach((el: PPTElement) => {\r\n if (el.groupId === element.groupId) groupMembersId.push(el.id)\r\n })\r\n newActiveIdList = [...newActiveIdList, ...groupMembersId]\r\n }\r\n\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, uniq(newActiveIdList))\r\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\r\n }\r\n\r\n // 如果目标元素已被选中,且按下了Ctrl键或Shift键,则取消其被选中状态\r\n // 除非目标元素是最后的一个被选中元素,或者目标元素所在的组合是最后一组选中组合\r\n // 如果目标元素是分组成员,需要将该组合的其他元素一起取消选中状态\r\n else if (ctrlOrShiftKeyActive.value) {\r\n let newActiveIdList: string[] = []\r\n\r\n if (element.groupId) {\r\n const groupMembersId: string[] = []\r\n elementList.value.forEach((el: PPTElement) => {\r\n if (el.groupId === element.groupId) groupMembersId.push(el.id)\r\n })\r\n newActiveIdList = activeElementIdList.value.filter(id => !groupMembersId.includes(id))\r\n }\r\n else {\r\n newActiveIdList = activeElementIdList.value.filter(id => id !== element.id)\r\n }\r\n\r\n if (newActiveIdList.length > 0) {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveIdList)\r\n }\r\n }\r\n\r\n // 如果目标元素已被选中,同时目标元素不是当前操作元素,则将其设置为当前操作元素\r\n else if (handleElementId.value !== element.id) {\r\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\r\n }\r\n\r\n // 如果目标元素已被选中,同时也是当前操作元素,那么当目标元素在该状态下再次被点击时,将被设置为多选元素中的激活成员\r\n else if (activeGroupElementId.value !== element.id) {\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n ;(e.target as HTMLElement).onmouseup = (e: MouseEvent) => {\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n if (startPageX === currentPageX && startPageY === currentPageY) {\r\n activeGroupElementId.value = element.id\r\n ;(e.target as HTMLElement).onmouseup = null\r\n }\r\n }\r\n }\r\n\r\n if (canMove) moveElement(e, element)\r\n }\r\n\r\n // 选中页面内的全部元素\r\n const selectAllElement = () => {\r\n const unlockedElements = elementList.value.filter(el => !el.lock)\r\n const newActiveElementIdList = unlockedElements.map(el => el.id)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\r\n }\r\n\r\n return {\r\n selectElement,\r\n selectAllElement,\r\n }\r\n}","import { Ref, computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { AlignmentLineProps } from '@/types/edit'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default (\r\n elementList: Ref<PPTElement[]>,\r\n activeGroupElementId: Ref<string>,\r\n alignmentLines: Ref<AlignmentLineProps[]>,\r\n) => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const dragElement = (e: MouseEvent, element: PPTElement) => {\r\n if (!activeElementIdList.value.includes(element.id)) return\r\n let isMouseDown = true\r\n\r\n const edgeWidth = VIEWPORT_SIZE\r\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n \r\n const sorptionRange = 5\r\n\r\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\r\n const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))\r\n \r\n const elOriginLeft = element.left\r\n const elOriginTop = element.top\r\n const elOriginWidth = element.width\r\n const elOriginHeight = ('height' in element && element.height) ? element.height : 0\r\n const elOriginRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\r\n \r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n let isMisoperation: boolean | null = null\r\n\r\n const isActiveGroupElement = element.id === activeGroupElementId.value\r\n\r\n // 收集对齐对齐吸附线\r\n // 包括页面内除目标元素外的其他元素在画布中的各个可吸附对齐位置:上下左右四边,水平中心、垂直中心\r\n // 其中线条和被旋转过的元素需要重新计算他们在画布中的中心点位置的范围\r\n let horizontalLines: AlignLine[] = []\r\n let verticalLines: AlignLine[] = []\r\n\r\n for (const el of elementList.value) {\r\n if (el.type === 'line') continue\r\n if (isActiveGroupElement && el.id === element.id) continue\r\n if (!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\r\n\r\n let left, top, width, height\r\n if ('rotate' in el && el.rotate) {\r\n const { xRange, yRange } = getRectRotatedRange({\r\n left: el.left,\r\n top: el.top,\r\n width: el.width,\r\n height: el.height,\r\n rotate: el.rotate,\r\n })\r\n left = xRange[0]\r\n top = yRange[0]\r\n width = xRange[1] - xRange[0]\r\n height = yRange[1] - yRange[0]\r\n }\r\n else {\r\n left = el.left\r\n top = el.top\r\n width = el.width\r\n height = el.height\r\n }\r\n \r\n const right = left + width\r\n const bottom = top + height\r\n const centerX = top + height / 2\r\n const centerY = left + width / 2\r\n\r\n const topLine: AlignLine = { value: top, range: [left, right] }\r\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\r\n const horizontalCenterLine: AlignLine = { value: centerX, range: [left, right] }\r\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\r\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\r\n const verticalCenterLine: AlignLine = { value: centerY, range: [top, bottom] }\r\n\r\n horizontalLines.push(topLine, bottomLine, horizontalCenterLine)\r\n verticalLines.push(leftLine, rightLine, verticalCenterLine)\r\n }\r\n\r\n // 画布可视区域的四个边界、水平中心、垂直中心\r\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\r\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\r\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\r\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\r\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\r\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\r\n\r\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\r\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\r\n \r\n // 对齐吸附线去重\r\n horizontalLines = uniqAlignLines(horizontalLines)\r\n verticalLines = uniqAlignLines(verticalLines)\r\n\r\n // 开始移动\r\n document.onmousemove = e => {\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n // 如果鼠标滑动距离过小,则将操作判定为误操作:\r\n // 如果误操作标记为null,表示是第一次触发移动,需要计算当前是否是误操作\r\n // 如果误操作标记为true,表示当前还处在误操作范围内,但仍然需要继续计算检查后续操作是否还处于误操作\r\n // 如果误操作标记为false,表示已经脱离了误操作范围,不需要再次计算\r\n if (isMisoperation !== false) {\r\n isMisoperation = Math.abs(startPageX - currentPageX) < sorptionRange && \r\n Math.abs(startPageY - currentPageY) < sorptionRange\r\n }\r\n if (!isMouseDown || isMisoperation) return\r\n\r\n const moveX = (currentPageX - startPageX) / canvasScale.value\r\n const moveY = (currentPageY - startPageY) / canvasScale.value\r\n\r\n // 基础目标位置\r\n let targetLeft = elOriginLeft + moveX\r\n let targetTop = elOriginTop + moveY\r\n\r\n // 计算目标元素在画布中的位置范围,用于吸附对齐\r\n // 需要区分单选和多选两种情况,其中多选状态下需要计算多选元素的整体范围;单选状态下需要继续区分线条、普通元素、旋转后的普通元素三种情况\r\n let targetMinX: number, targetMaxX: number, targetMinY: number, targetMaxY: number\r\n\r\n if (activeElementIdList.value.length === 1 || isActiveGroupElement) {\r\n if (elOriginRotate) {\r\n const { xRange, yRange } = getRectRotatedRange({\r\n left: targetLeft,\r\n top: targetTop,\r\n width: elOriginWidth,\r\n height: elOriginHeight,\r\n rotate: elOriginRotate,\r\n })\r\n targetMinX = xRange[0]\r\n targetMaxX = xRange[1]\r\n targetMinY = yRange[0]\r\n targetMaxY = yRange[1]\r\n }\r\n else if (element.type === 'line') {\r\n targetMinX = targetLeft\r\n targetMaxX = targetLeft + Math.max(element.start[0], element.end[0])\r\n targetMinY = targetTop\r\n targetMaxY = targetTop + Math.max(element.start[1], element.end[1])\r\n }\r\n else {\r\n targetMinX = targetLeft\r\n targetMaxX = targetLeft + elOriginWidth\r\n targetMinY = targetTop\r\n targetMaxY = targetTop + elOriginHeight\r\n }\r\n }\r\n else {\r\n const leftValues = []\r\n const topValues = []\r\n const rightValues = []\r\n const bottomValues = []\r\n \r\n for (let i = 0; i < originActiveElementList.length; i++) {\r\n const element = originActiveElementList[i]\r\n const left = element.left + moveX\r\n const top = element.top + moveY\r\n const width = element.width\r\n const height = ('height' in element && element.height) ? element.height : 0\r\n const rotate = ('rotate' in element && element.rotate) ? element.rotate : 0\r\n\r\n if ('rotate' in element && element.rotate) {\r\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\r\n leftValues.push(xRange[0])\r\n topValues.push(yRange[0])\r\n rightValues.push(xRange[1])\r\n bottomValues.push(yRange[1])\r\n }\r\n else if (element.type === 'line') {\r\n leftValues.push(left)\r\n topValues.push(top)\r\n rightValues.push(left + Math.max(element.start[0], element.end[0]))\r\n bottomValues.push(top + Math.max(element.start[1], element.end[1]))\r\n }\r\n else {\r\n leftValues.push(left)\r\n topValues.push(top)\r\n rightValues.push(left + width)\r\n bottomValues.push(top + height)\r\n }\r\n }\r\n\r\n targetMinX = Math.min(...leftValues)\r\n targetMaxX = Math.max(...rightValues)\r\n targetMinY = Math.min(...topValues)\r\n targetMaxY = Math.max(...bottomValues)\r\n }\r\n \r\n const targetCenterX = targetMinX + (targetMaxX - targetMinX) / 2\r\n const targetCenterY = targetMinY + (targetMaxY - targetMinY) / 2\r\n\r\n // 将收集到的对齐吸附线与计算的目标元素位置范围做对比,二者的差小于设定的值时执行自动对齐校正\r\n // 水平和垂直两个方向需要分开计算\r\n const _alignmentLines: AlignmentLineProps[] = []\r\n let isVerticalAdsorbed = false\r\n let isHorizontalAdsorbed = false\r\n for (let i = 0; i < horizontalLines.length; i++) {\r\n const { value, range } = horizontalLines[i]\r\n const min = Math.min(...range, targetMinX, targetMaxX)\r\n const max = Math.max(...range, targetMinX, targetMaxX)\r\n \r\n if (Math.abs(targetMinY - value) < sorptionRange && !isHorizontalAdsorbed) {\r\n targetTop = targetTop - (targetMinY - value)\r\n isHorizontalAdsorbed = true\r\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\r\n }\r\n if (Math.abs(targetMaxY - value) < sorptionRange && !isHorizontalAdsorbed) {\r\n targetTop = targetTop - (targetMaxY - value)\r\n isHorizontalAdsorbed = true\r\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\r\n }\r\n if (Math.abs(targetCenterY - value) < sorptionRange && !isHorizontalAdsorbed) {\r\n targetTop = targetTop - (targetCenterY - value)\r\n isHorizontalAdsorbed = true\r\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\r\n }\r\n }\r\n for (let i = 0; i < verticalLines.length; i++) {\r\n const { value, range } = verticalLines[i]\r\n const min = Math.min(...range, targetMinY, targetMaxY)\r\n const max = Math.max(...range, targetMinY, targetMaxY)\r\n\r\n if (Math.abs(targetMinX - value) < sorptionRange && !isVerticalAdsorbed) {\r\n targetLeft = targetLeft - (targetMinX - value)\r\n isVerticalAdsorbed = true\r\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\r\n }\r\n if (Math.abs(targetMaxX - value) < sorptionRange && !isVerticalAdsorbed) {\r\n targetLeft = targetLeft - (targetMaxX - value)\r\n isVerticalAdsorbed = true\r\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\r\n }\r\n if (Math.abs(targetCenterX - value) < sorptionRange && !isVerticalAdsorbed) {\r\n targetLeft = targetLeft - (targetCenterX - value)\r\n isVerticalAdsorbed = true\r\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\r\n }\r\n }\r\n alignmentLines.value = _alignmentLines\r\n \r\n // 单选状态下,或者当前选中的多个元素中存在正在操作的元素时,仅修改正在操作的元素的位置\r\n if (activeElementIdList.value.length === 1 || isActiveGroupElement) {\r\n elementList.value = elementList.value.map(el => {\r\n return el.id === element.id ? { ...el, left: targetLeft, top: targetTop } : el\r\n })\r\n }\r\n\r\n // 多选状态下,除了修改正在操作的元素的位置,其他被选中的元素也需要修改位置信息\r\n // 其他被选中的元素的位置信息通过正在操作的元素的移动偏移量来进行计算\r\n else {\r\n const handleElement = elementList.value.find(el => el.id === element.id)\r\n if (!handleElement) return\r\n\r\n elementList.value = elementList.value.map(el => {\r\n if (activeElementIdList.value.includes(el.id)) {\r\n if (el.id === element.id) {\r\n return {\r\n ...el,\r\n left: targetLeft,\r\n top: targetTop,\r\n }\r\n }\r\n return {\r\n ...el,\r\n left: el.left + (targetLeft - handleElement.left),\r\n top: el.top + (targetTop - handleElement.top),\r\n }\r\n }\r\n return el\r\n })\r\n }\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n alignmentLines.value = []\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n if (startPageX === currentPageX && startPageY === currentPageY) return\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\r\n addHistorySnapshot()\r\n }\r\n }\r\n\r\n return {\r\n dragElement,\r\n }\r\n}","import { Ref, computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTLineElement } from '@/types/slides'\r\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\ninterface AdsorptionPoint {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport default (elementList: Ref<PPTElement[]>) => {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 拖拽线条端点\r\n const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {\r\n let isMouseDown = true\r\n\r\n const sorptionRange = 8\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n const adsorptionPoints: AdsorptionPoint[] = []\r\n\r\n // 获取所有线条以外的未旋转的元素的8个缩放点作为吸附位置\r\n for (let i = 0; i < elementList.value.length; i++) {\r\n const _element = elementList.value[i]\r\n if (_element.type === 'line' || ('rotate' in _element && _element.rotate)) continue\r\n\r\n const left = _element.left\r\n const top = _element.top\r\n const width = _element.width\r\n const height = _element.height\r\n \r\n const right = left + width\r\n const bottom = top + height\r\n const centerX = top + height / 2\r\n const centerY = left + width / 2\r\n\r\n const topPoint = { x: centerY, y: top }\r\n const bottomPoint = { x: centerY, y: bottom }\r\n const leftPoint = { x: left, y: centerX }\r\n const rightPoint = { x: right, y: centerX }\r\n\r\n const leftTopPoint = { x: left, y: top }\r\n const rightTopPoint = { x: right, y: top }\r\n const leftBottomPoint = { x: left, y: bottom }\r\n const rightBottomPoint = { x: right, y: bottom }\r\n\r\n adsorptionPoints.push(\r\n topPoint,\r\n bottomPoint,\r\n leftPoint,\r\n rightPoint,\r\n leftTopPoint,\r\n rightTopPoint,\r\n leftBottomPoint,\r\n rightBottomPoint,\r\n )\r\n }\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const moveX = (currentPageX - startPageX) / canvasScale.value\r\n const moveY = (currentPageY - startPageY) / canvasScale.value\r\n \r\n // 线条起点和终点在编辑区域中的位置\r\n let startX = element.left + element.start[0]\r\n let startY = element.top + element.start[1]\r\n let endX = element.left + element.end[0]\r\n let endY = element.top + element.end[1]\r\n\r\n // 拖拽起点或终点的位置\r\n // 水平和垂直方向上有吸附\r\n if (command === OperateLineHandlers.START) {\r\n startX = startX + moveX\r\n startY = startY + moveY\r\n\r\n if (Math.abs(startX - endX) < sorptionRange) startX = endX\r\n if (Math.abs(startY - endY) < sorptionRange) startY = endY\r\n\r\n for (const adsorptionPoint of adsorptionPoints) {\r\n const { x, y } = adsorptionPoint\r\n if (Math.abs(x - startX) < sorptionRange && Math.abs(y - startY) < sorptionRange) {\r\n startX = x\r\n startY = y\r\n break\r\n }\r\n }\r\n }\r\n else {\r\n endX = endX + moveX\r\n endY = endY + moveY\r\n\r\n if (Math.abs(startX - endX) < sorptionRange) endX = startX\r\n if (Math.abs(startY - endY) < sorptionRange) endY = startY\r\n\r\n for (const adsorptionPoint of adsorptionPoints) {\r\n const { x, y } = adsorptionPoint\r\n if (Math.abs(x - endX) < sorptionRange && Math.abs(y - endY) < sorptionRange) {\r\n endX = x\r\n endY = y\r\n break\r\n }\r\n }\r\n }\r\n\r\n // 计算更新起点和终点基于自身元素位置的坐标\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const start: [number, number] = [0, 0]\r\n const end: [number, number] = [maxX - minX, maxY - minY]\r\n if (startX > endX) {\r\n start[0] = maxX - minX\r\n end[0] = 0\r\n }\r\n if (startY > endY) {\r\n start[1] = maxY - minY\r\n end[1] = 0\r\n }\r\n\r\n elementList.value = elementList.value.map(el => {\r\n if (el.id === element.id) {\r\n return {\r\n ...el,\r\n left: minX,\r\n top: minY,\r\n start: start,\r\n end: end,\r\n }\r\n }\r\n return el\r\n })\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n if (startPageX === currentPageX && startPageY === currentPageY) return\r\n\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\r\n addHistorySnapshot()\r\n }\r\n }\r\n\r\n return {\r\n dragLineElement,\r\n }\r\n}","import { computed, Ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { CreateElementSelectionData, CreatingLineElement, CreatingShapeElement } from '@/types/edit'\r\nimport useCreateElement from '@/hooks/useCreateElement'\r\n\r\nexport default (viewportRef: Ref<HTMLElement | undefined>) => {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const creatingElement = computed(() => store.state.creatingElement)\r\n\r\n // 通过鼠标框选时的起点和终点,计算选区的位置大小\r\n const formatCreateSelection = (selectionData: CreateElementSelectionData) => {\r\n const { start, end } = selectionData\r\n\r\n if (!viewportRef.value) return\r\n const viewportRect = viewportRef.value.getBoundingClientRect()\r\n\r\n const [startX, startY] = start\r\n const [endX, endY] = end\r\n const minX = Math.min(startX, endX)\r\n const maxX = Math.max(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const left = (minX - viewportRect.x) / canvasScale.value\r\n const top = (minY - viewportRect.y) / canvasScale.value\r\n const width = (maxX - minX) / canvasScale.value\r\n const height = (maxY - minY) / canvasScale.value\r\n\r\n return { left, top, width, height }\r\n }\r\n\r\n // 通过鼠标框选时的起点和终点,计算线条在画布中的位置和起点终点\r\n const formatCreateSelectionForLine = (selectionData: CreateElementSelectionData) => {\r\n const { start, end } = selectionData\r\n\r\n if (!viewportRef.value) return\r\n const viewportRect = viewportRef.value.getBoundingClientRect()\r\n\r\n const [startX, startY] = start\r\n const [endX, endY] = end\r\n const minX = Math.min(startX, endX)\r\n const maxX = Math.max(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const left = (minX - viewportRect.x) / canvasScale.value\r\n const top = (minY - viewportRect.y) / canvasScale.value\r\n const width = (maxX - minX) / canvasScale.value\r\n const height = (maxY - minY) / canvasScale.value\r\n\r\n const _start: [number, number] = [\r\n startX === minX ? 0 : width,\r\n startY === minY ? 0 : height,\r\n ]\r\n const _end: [number, number] = [\r\n endX === minX ? 0 : width,\r\n endY === minY ? 0 : height,\r\n ]\r\n\r\n return {\r\n left,\r\n top,\r\n start: _start,\r\n end: _end,\r\n }\r\n }\r\n\r\n const { createTextElement, createShapeElement, createLineElement } = useCreateElement()\r\n\r\n // 根据鼠标选区的位置大小插入元素\r\n const insertElementFromCreateSelection = (selectionData: CreateElementSelectionData) => {\r\n if (!creatingElement.value) return\r\n\r\n const type = creatingElement.value.type\r\n if (type === 'text') {\r\n const position = formatCreateSelection(selectionData)\r\n position && createTextElement(position)\r\n }\r\n else if (type === 'shape') {\r\n const position = formatCreateSelection(selectionData)\r\n position && createShapeElement(position, (creatingElement.value as CreatingShapeElement).data)\r\n }\r\n else if (type === 'line') {\r\n const position = formatCreateSelectionForLine(selectionData)\r\n position && createLineElement(position, (creatingElement.value as CreatingLineElement).data)\r\n }\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\r\n }\r\n\r\n return {\r\n insertElementFromCreateSelection,\r\n }\r\n}","<template>\r\n <div \r\n class=\"editable-element\"\r\n ref=\"elementRef\"\r\n :id=\"'editable-element-' + elementInfo.id\"\r\n :style=\"{\r\n zIndex: elementIndex,\r\n color: theme.fontColor,\r\n fontFamily: theme.fontName,\r\n }\"\r\n >\r\n <component\r\n :is=\"currentElementComponent\"\r\n :elementInfo=\"elementInfo\"\r\n :selectElement=\"selectElement\"\r\n :contextmenus=\"contextmenus\"\r\n ></component>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport useLockElement from '@/hooks/useLockElement'\r\nimport useDeleteElement from '@/hooks/useDeleteElement'\r\nimport useCombineElement from '@/hooks/useCombineElement'\r\nimport useOrderElement from '@/hooks/useOrderElement'\r\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\r\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\r\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\r\n\r\nimport { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'\r\n\r\nimport ImageElement from '@/views/components/element/ImageElement/index.vue'\r\nimport TextElement from '@/views/components/element/TextElement/index.vue'\r\nimport ShapeElement from '@/views/components/element/ShapeElement/index.vue'\r\nimport LineElement from '@/views/components/element/LineElement/index.vue'\r\nimport ChartElement from '@/views/components/element/ChartElement/index.vue'\r\nimport TableElement from '@/views/components/element/TableElement/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElement,\r\n [ElementTypes.TEXT]: TextElement,\r\n [ElementTypes.SHAPE]: ShapeElement,\r\n [ElementTypes.LINE]: LineElement,\r\n [ElementTypes.CHART]: ChartElement,\r\n [ElementTypes.TABLE]: TableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const { orderElement } = useOrderElement()\r\n const { alignElementToCanvas } = useAlignElementToCanvas()\r\n const { combineElements, uncombineElements } = useCombineElement()\r\n const { deleteElement } = useDeleteElement()\r\n const { lockElement, unlockElement } = useLockElement()\r\n const { copyElement, pasteElement, cutElement } = useCopyAndPasteElement()\r\n const { selectAllElement } = useSelectAllElement()\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n if (props.elementInfo.lock) {\r\n return [{\r\n text: '解锁', \r\n handler: () => unlockElement(props.elementInfo),\r\n }]\r\n }\r\n\r\n return [\r\n {\r\n text: '剪切',\r\n subText: 'Ctrl + X',\r\n handler: cutElement,\r\n },\r\n {\r\n text: '复制',\r\n subText: 'Ctrl + C',\r\n handler: copyElement,\r\n },\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteElement,\r\n },\r\n { divider: true },\r\n {\r\n text: '对齐方式',\r\n children: [\r\n { text: '水平垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.CENTER) },\r\n { divider: true },\r\n { text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },\r\n { text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },\r\n { text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },\r\n { divider: true },\r\n { text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },\r\n { text: '顶部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },\r\n { text: '底部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },\r\n ],\r\n },\r\n {\r\n text: '层级排序',\r\n disable: props.isMultiSelect && !props.elementInfo.groupId,\r\n children: [\r\n { text: '置顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },\r\n { text: '置底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },\r\n { divider: true },\r\n { text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },\r\n { text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },\r\n ],\r\n },\r\n { divider: true },\r\n {\r\n text: props.elementInfo.groupId ? '取消组合' : '组合',\r\n subText: 'Ctrl + G',\r\n handler: props.elementInfo.groupId ? uncombineElements : combineElements,\r\n hide: !props.isMultiSelect,\r\n },\r\n {\r\n text: '全选',\r\n subText: 'Ctrl + A',\r\n handler: selectAllElement,\r\n },\r\n {\r\n text: '锁定',\r\n subText: 'Ctrl + L',\r\n handler: lockElement,\r\n },\r\n {\r\n text: '删除',\r\n subText: 'Delete',\r\n handler: deleteElement,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n currentElementComponent,\r\n contextmenus,\r\n theme,\r\n }\r\n },\r\n})\r\n</script>","import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\r\n\r\nexport interface PPTElementShadow {\r\n h: number;\r\n v: number;\r\n blur: number;\r\n color: string;\r\n}\r\n\r\nexport const enum ElementTypes {\r\n TEXT = 'text',\r\n IMAGE = 'image',\r\n SHAPE = 'shape',\r\n LINE = 'line',\r\n CHART = 'chart',\r\n TABLE = 'table',\r\n}\r\n\r\nexport interface PPTElementOutline {\r\n style?: 'dashed' | 'solid';\r\n width?: number;\r\n color?: string;\r\n}\r\n\r\nexport interface PPTTextElement {\r\n type: 'text';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n width: number;\r\n height: number;\r\n content: string;\r\n rotate?: number;\r\n outline?: PPTElementOutline;\r\n fill?: string;\r\n lineHeight?: number;\r\n wordSpace?: number;\r\n opacity?: number;\r\n shadow?: PPTElementShadow;\r\n}\r\n\r\nexport interface ImageOrShapeFlip {\r\n x?: number;\r\n y?: number;\r\n}\r\nexport interface ImageElementFilters {\r\n 'blur'?: string;\r\n 'brightness'?: string;\r\n 'contrast'?: string;\r\n 'grayscale'?: string;\r\n 'saturate'?: string;\r\n 'hue-rotate'?: string;\r\n 'opacity'?: string;\r\n}\r\nexport interface ImageElementClip {\r\n range: [[number, number], [number, number]];\r\n shape: string;\r\n}\r\nexport interface PPTImageElement {\r\n type: 'image';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n width: number;\r\n height: number;\r\n fixedRatio: boolean;\r\n src: string;\r\n rotate?: number;\r\n outline?: PPTElementOutline;\r\n filters?: ImageElementFilters;\r\n clip?: ImageElementClip;\r\n flip?: ImageOrShapeFlip;\r\n shadow?: PPTElementShadow;\r\n}\r\n\r\nexport interface ShapeGradient {\r\n type: 'linear' | 'radial';\r\n color: [string, string];\r\n rotate: number;\r\n}\r\nexport interface PPTShapeElement {\r\n type: 'shape';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n width: number;\r\n height: number;\r\n viewBox: number;\r\n path: string;\r\n fixedRatio: boolean;\r\n fill: string;\r\n gradient?: ShapeGradient;\r\n rotate?: number;\r\n outline?: PPTElementOutline;\r\n opacity?: number;\r\n flip?: ImageOrShapeFlip;\r\n shadow?: PPTElementShadow;\r\n}\r\n\r\nexport interface PPTLineElement {\r\n type: 'line';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n start: [number, number];\r\n end: [number, number];\r\n width: number;\r\n style: string;\r\n color: string;\r\n points: [string, string];\r\n shadow?: PPTElementShadow;\r\n}\r\n\r\nexport type ChartType = 'bar' | 'line' | 'pie'\r\nexport interface ChartData {\r\n labels: string[];\r\n series: number[][];\r\n}\r\nexport interface PPTChartElement {\r\n type: 'chart';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n width: number;\r\n height: number;\r\n fill?: string;\r\n chartType: ChartType;\r\n data: ChartData;\r\n options?: ILineChartOptions & IBarChartOptions & IPieChartOptions;\r\n outline?: PPTElementOutline;\r\n themeColor: string;\r\n gridColor?: string;\r\n}\r\n\r\nexport interface TableCellStyle {\r\n bold?: boolean;\r\n em?: boolean;\r\n underline?: boolean;\r\n strikethrough?: boolean;\r\n color?: string;\r\n backcolor?: string;\r\n fontsize?: string;\r\n fontname?: string;\r\n align?: string;\r\n}\r\nexport interface TableCell {\r\n id: string;\r\n colspan: number;\r\n rowspan: number;\r\n text: string;\r\n style?: TableCellStyle;\r\n}\r\nexport interface TableTheme {\r\n color: string;\r\n rowHeader: boolean;\r\n rowFooter: boolean;\r\n colHeader: boolean;\r\n colFooter: boolean;\r\n} \r\nexport interface PPTTableElement {\r\n type: 'table';\r\n id: string;\r\n left: number;\r\n top: number;\r\n lock?: boolean;\r\n groupId?: string;\r\n width: number;\r\n height: number;\r\n outline: PPTElementOutline;\r\n theme?: TableTheme;\r\n colWidths: number[];\r\n data: TableCell[][];\r\n}\r\n\r\nexport type PPTElement = PPTTextElement | PPTImageElement | PPTShapeElement | PPTLineElement | PPTChartElement | PPTTableElement\r\n\r\nexport interface PPTAnimation {\r\n elId: string;\r\n type: string;\r\n duration: number;\r\n}\r\n\r\nexport interface SlideBackground {\r\n type: 'solid' | 'image' | 'gradient';\r\n color?: string;\r\n image?: string;\r\n imageSize?: 'cover' | 'contain' | 'repeat' | 'initial';\r\n gradientType?: 'linear' | 'radial';\r\n gradientColor?: [string, string];\r\n gradientRotate?: number;\r\n}\r\n\r\nexport interface Slide {\r\n id: string;\r\n elements: PPTElement[];\r\n background?: SlideBackground;\r\n animations?: PPTAnimation[];\r\n turningMode?: 'no' | 'fade' | 'slideX' | 'slideY';\r\n}\r\n\r\nexport interface SlideTheme {\r\n backgroundColor: string;\r\n themeColor: string;\r\n fontColor: string;\r\n fontName: string;\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\r\nimport { getElementListRange } from '@/utils/element'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport useHistorySnapshot from './useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n /**\r\n * 将所有选中的元素对齐到画布\r\n * @param command 对齐方向\r\n */\r\n const alignElementToCanvas = (command: ElementAlignCommand) => {\r\n const viewportWidth = VIEWPORT_SIZE\r\n const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\r\n \r\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n for (const element of newElementList) {\r\n if (!activeElementIdList.value.includes(element.id)) continue\r\n \r\n // 水平垂直居中\r\n if (command === ElementAlignCommands.CENTER) {\r\n const offsetY = minY + (maxY - minY) / 2 - viewportHeight / 2\r\n const offsetX = minX + (maxX - minX) / 2 - viewportWidth / 2\r\n element.top = element.top - offsetY \r\n element.left = element.left - offsetX \r\n }\r\n\r\n // 顶部对齐\r\n if (command === ElementAlignCommands.TOP) {\r\n const offsetY = minY - 0\r\n element.top = element.top - offsetY \r\n }\r\n\r\n // 垂直居中\r\n else if (command === ElementAlignCommands.VERTICAL) {\r\n const offsetY = minY + (maxY - minY) / 2 - viewportHeight / 2\r\n element.top = element.top - offsetY \r\n }\r\n\r\n // 底部对齐\r\n else if (command === ElementAlignCommands.BOTTOM) {\r\n const offsetY = maxY - viewportHeight\r\n element.top = element.top - offsetY \r\n }\r\n \r\n // 左侧对齐\r\n else if (command === ElementAlignCommands.LEFT) {\r\n const offsetX = minX - 0\r\n element.left = element.left - offsetX \r\n }\r\n\r\n // 水平居中\r\n else if (command === ElementAlignCommands.HORIZONTAL) {\r\n const offsetX = minX + (maxX - minX) / 2 - viewportWidth / 2\r\n element.left = element.left - offsetX \r\n }\r\n\r\n // 右侧对齐\r\n else if (command === ElementAlignCommands.RIGHT) {\r\n const offsetX = maxX - viewportWidth\r\n element.left = element.left - offsetX \r\n }\r\n }\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n alignElementToCanvas,\r\n }\r\n}","export const enum ClipPathTypes {\r\n RECT = 'rect',\r\n ELLIPSE = 'ellipse',\r\n POLYGON = 'polygon',\r\n}\r\n\r\nexport const enum ClipPaths {\r\n RECT = 'rect',\r\n ROUNDRECT = 'roundRect',\r\n ELLIPSE = 'ellipse',\r\n TRIANGLE = 'triangle',\r\n PENTAGON = 'pentagon',\r\n RHOMBUS = 'rhombus',\r\n STAR = 'star',\r\n}\r\n\r\nexport const CLIPPATHS = {\r\n rect: {\r\n name: '矩形',\r\n type: ClipPathTypes.RECT,\r\n radius: '0',\r\n style: '',\r\n },\r\n rect2: {\r\n name: '矩形2',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 0 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L 0 ${height} Z`\r\n },\r\n },\r\n rect3: {\r\n name: '矩形3',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 20% 100%, 0% 80%)',\r\n createPath: (width: number, height: number) => {\r\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.8} Z`\r\n },\r\n },\r\n roundRect: {\r\n name: '圆角矩形',\r\n type: ClipPathTypes.RECT,\r\n radius: '10%',\r\n style: 'inset(0 0 0 0 round 10% 10% 10% 10%)',\r\n },\r\n ellipse: {\r\n name: '圆形',\r\n type: ClipPathTypes.ELLIPSE,\r\n style: 'ellipse(50% 50% at 50% 50%)',\r\n },\r\n triangle: {\r\n name: '三角形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(50% 0%, 0% 100%, 100% 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.5} 0 L 0 ${height} L ${width} ${height} Z`\r\n },\r\n },\r\n triangle2: {\r\n name: '三角形2',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(50% 100%, 0% 0%, 100% 0%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.5} ${height} L 0 0 L ${width} 0 Z`\r\n },\r\n },\r\n triangle3: {\r\n name: '三角形3',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(0% 0%, 0% 100%, 100% 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M 0 0 L 0 ${height} L ${width} ${height} Z`\r\n },\r\n },\r\n rhombus: {\r\n name: '菱形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.5} 0 L ${width} ${height * 0.5} L ${width * 0.5} ${height} L 0 ${height * 0.5} Z`\r\n },\r\n },\r\n hexagon: {\r\n name: '六边形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.2} 0 L ${width * 0.8} 0 L ${width} ${height * 0.5} L ${width * 0.8} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.5} Z`\r\n },\r\n },\r\n pentagon: {\r\n name: '五边形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.5} 0 L ${width} ${0.38 * height} L ${0.82 * width} ${height} L ${0.18 * width} ${height} L 0 ${0.38 * height} Z`\r\n },\r\n },\r\n parallelogram: {\r\n name: '平行四边形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(30% 0%, 100% 0%, 70% 100%, 0% 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.3} 0 L ${width} 0 L ${width * 0.7} ${height} L 0 ${height} Z`\r\n },\r\n },\r\n parallelogram2: {\r\n name: '平行四边形2',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(30% 100%, 100% 100%, 70% 0%, 0% 0%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.3} ${height} L ${width} ${height} L ${width * 0.7} 0 L 0 0 Z`\r\n },\r\n },\r\n trapezoid: {\r\n name: '梯形',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(25% 0%, 75% 0%, 100% 100%, 0% 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M ${width * 0.25} 0 L ${width * 0.75} 0 L ${width} ${height} L 0 ${height} Z`\r\n },\r\n },\r\n trapezoid2: {\r\n name: '梯形2',\r\n type: ClipPathTypes.POLYGON,\r\n style: 'polygon(0% 0%, 100% 0%, 75% 100%, 25% 100%)',\r\n createPath: (width: number, height: number) => {\r\n return `M 0 0 L ${width} 0 L ${width * 0.75} ${height} L ${width * 0.25} ${height} Z`\r\n },\r\n },\r\n}","<template>\r\n <div \r\n class=\"editable-element-image\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n @mousedown=\"$event => handleSelectElement($event)\" \r\n >\r\n <ImageClipHandler\r\n v-if=\"isCliping\"\r\n :src=\"elementInfo.src\"\r\n :clipData=\"elementInfo.clip\"\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :top=\"elementInfo.top\"\r\n :left=\"elementInfo.left\"\r\n :clipPath=\"clipShape.style\"\r\n @clip=\"range => handleClip(range)\"\r\n />\r\n <div \r\n class=\"element-content\"\r\n v-else\r\n v-contextmenu=\"contextmenus\"\r\n :style=\"{\r\n filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',\r\n transform: flipStyle,\r\n }\"\r\n >\r\n <ImageOutline :elementInfo=\"elementInfo\" />\r\n\r\n <div class=\"image-content\" :style=\"{ clipPath: clipShape.style }\">\r\n <img \r\n :src=\"elementInfo.src\" \r\n :draggable=\"false\" \r\n :style=\"{\r\n top: imgPosition.top,\r\n left: imgPosition.left,\r\n width: imgPosition.width,\r\n height: imgPosition.height,\r\n filter: filter,\r\n }\" \r\n alt=\"\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { ImageClipedEmitData } from '@/types/edit'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\nimport useClipImage from './useClipImage'\r\nimport useFilter from './useFilter'\r\n\r\nimport ImageOutline from './ImageOutline/index.vue'\r\nimport ImageClipHandler from './ImageClipHandler.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-image',\r\n components: {\r\n ImageOutline,\r\n ImageClipHandler,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape, imgPosition } = useClipImage(clip)\r\n\r\n const filters = computed(() => props.elementInfo.filters)\r\n const { filter } = useFilter(filters)\r\n\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n const handleClip = (data: ImageClipedEmitData) => {\r\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, '')\r\n \r\n if (!data) return\r\n\r\n const { range, position } = data\r\n const originClip = props.elementInfo.clip || {}\r\n \r\n const _props = {\r\n clip: { ...originClip, range },\r\n left: props.elementInfo.left + position.left,\r\n top: props.elementInfo.top + position.top,\r\n width: props.elementInfo.width + position.width,\r\n height: props.elementInfo.height + position.height,\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: props.elementInfo.id, props: _props })\r\n }\r\n\r\n return {\r\n isCliping,\r\n handleClip,\r\n clipingImageElementId,\r\n shadowStyle,\r\n handleSelectElement,\r\n clipShape,\r\n imgPosition,\r\n filter,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-image {\r\n position: absolute;\r\n\r\n &.lock .element-content {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n cursor: move;\r\n\r\n .image-content {\r\n width: 100%;\r\n height: 100%;\r\n overflow: hidden;\r\n position: relative;\r\n }\r\n img {\r\n position: absolute;\r\n }\r\n}\r\n</style>\r\n","import { computed, Ref } from 'vue'\r\nimport { PPTElementShadow } from '@/types/slides'\r\n\r\n// 计算元素的阴影样式\r\nexport default (shadow: Ref<PPTElementShadow | undefined>) => {\r\n const shadowStyle = computed(() => {\r\n if (shadow.value) {\r\n const { h, v, blur, color } = shadow.value\r\n return `${h}px ${v}px ${blur}px ${color}`\r\n }\r\n return ''\r\n })\r\n\r\n return {\r\n shadowStyle,\r\n }\r\n}","import { computed, Ref } from 'vue'\r\nimport { ImageOrShapeFlip } from '@/types/slides'\r\n\r\n// 计算元素的翻转样式\r\nexport default (flip: Ref<ImageOrShapeFlip | undefined>) => {\r\n const flipStyle = computed(() => {\r\n if (flip.value) {\r\n let style = ''\r\n \r\n const { x, y } = flip.value\r\n if (x && y) style = `rotateX(${x}deg) rotateY(${y}deg)`\r\n else if (x) style = `rotateX(${x}deg)`\r\n else if (y) style = `rotateY(${y}deg)`\r\n\r\n return style\r\n }\r\n return ''\r\n })\r\n\r\n return {\r\n flipStyle,\r\n }\r\n}","import { computed, Ref } from 'vue'\r\nimport { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'\r\nimport { ImageElementClip } from '@/types/slides'\r\n\r\nexport default (clip: Ref<ImageElementClip | undefined>) => {\r\n const clipShape = computed(() => {\r\n if (!clip.value) return CLIPPATHS.rect\r\n const shape = clip.value.shape || ClipPathTypes.RECT\r\n\r\n return CLIPPATHS[shape]\r\n })\r\n\r\n const imgPosition = computed(() => {\r\n if (!clip.value) {\r\n return {\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n }\r\n }\r\n\r\n const [start, end] = clip.value.range\r\n\r\n const widthScale = (end[0] - start[0]) / 100\r\n const heightScale = (end[1] - start[1]) / 100\r\n const left = start[0] / widthScale\r\n const top = start[1] / heightScale\r\n\r\n return {\r\n left: -left + '%',\r\n top: -top + '%',\r\n width: 100 / widthScale + '%',\r\n height: 100 / heightScale + '%',\r\n }\r\n })\r\n\r\n return {\r\n clipShape,\r\n imgPosition,\r\n }\r\n}","import { computed, Ref } from 'vue'\r\nimport { ImageElementFilters } from '@/types/slides'\r\n\r\nexport default (filters: Ref<ImageElementFilters | undefined>) => {\r\n const filter = computed(() => {\r\n if (!filters.value) return ''\r\n let filter = ''\r\n for (const key of Object.keys(filters.value)) {\r\n filter += `${key}(${filters.value[key]}) `\r\n }\r\n return filter\r\n })\r\n\r\n return {\r\n filter,\r\n }\r\n}","<template>\r\n <div class=\"image-outline\">\r\n <ImageRectOutline\r\n v-if=\"clipShape.type === 'rect'\"\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :radius=\"clipShape.radius\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <ImageEllipseOutline\r\n v-else-if=\"clipShape.type === 'ellipse'\"\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <ImagePolygonOutline\r\n v-else-if=\"clipShape.type === 'polygon'\"\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n :createPath=\"clipShape.createPath\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport useClipImage from '../useClipImage'\r\n\r\nimport ImageRectOutline from './ImageRectOutline.vue'\r\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\r\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-outline',\r\n components: {\r\n ImageRectOutline,\r\n ImageEllipseOutline,\r\n ImagePolygonOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape } = useClipImage(clip)\r\n\r\n return {\r\n clipShape,\r\n }\r\n },\r\n})\r\n</script>","<template>\r\n <SvgWrapper \r\n class=\"image-rect-outline\" \r\n v-if=\"outline\"\r\n overflow=\"visible\" \r\n :width=\"width\"\r\n :height=\"height\"\r\n >\r\n <rect \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin\r\n fill=\"transparent\"\r\n :rx=\"radius\" \r\n :ry=\"radius\"\r\n :width=\"width\"\r\n :height=\"height\"\r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 6' : '0 0'\" \r\n ></rect>\r\n\t</SvgWrapper>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-rect-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n radius: {\r\n type: String,\r\n default: '0',\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\nsvg {\r\n overflow: visible;\r\n position: absolute;\r\n z-index: 2;\r\n top: 0;\r\n left: 0;\r\n}\r\n</style>","import { computed, Ref } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\n\r\n// 计算边框相关属性值,主要是对默认值的处理\r\nexport default (outline: Ref<PPTElementOutline | undefined>) => {\r\n const outlineWidth = computed(() => outline.value?.width ?? 0)\r\n const outlineStyle = computed(() => outline.value?.style || 'solid')\r\n const outlineColor = computed(() => outline.value?.color || '#d14424')\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n}","\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-rect-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n radius: {\r\n type: String,\r\n default: '0',\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageRectOutline.vue?vue&type=template&id=4126ab7f&scoped=true\"\nimport script from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageRectOutline.vue?vue&type=style&index=0&id=4126ab7f&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4126ab7f\"\n\nexport default script","<template>\r\n <SvgWrapper \r\n class=\"image-ellipse-outline\"\r\n v-if=\"outline\"\r\n overflow=\"visible\" \r\n :width=\"width\"\r\n :height=\"height\"\r\n >\r\n <ellipse \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin\r\n fill=\"transparent\"\r\n :cx=\"width / 2\" \r\n :cy=\"height / 2\"\r\n :rx=\"width / 2\" \r\n :ry=\"height / 2\"\r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 6' : '0 0'\" \r\n ></ellipse>\r\n\t</SvgWrapper>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-ellipse-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\nsvg {\r\n overflow: visible;\r\n position: absolute;\r\n z-index: 2;\r\n top: 0;\r\n left: 0;\r\n}\r\n</style>","\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-ellipse-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageEllipseOutline.vue?vue&type=template&id=6655f0f0&scoped=true\"\nimport script from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageEllipseOutline.vue?vue&type=style&index=0&id=6655f0f0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6655f0f0\"\n\nexport default script","<template>\r\n <SvgWrapper \r\n class=\"image-polygon-outline\" \r\n v-if=\"outline\"\r\n overflow=\"visible\" \r\n :width=\"width\"\r\n :height=\"height\"\r\n >\r\n <path \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin\r\n fill=\"transparent\"\r\n :d=\"createPath(width, height)\"\r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 6' : '0 0'\" \r\n ></path>\r\n\t</SvgWrapper>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-polygon-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n createPath: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\nsvg {\r\n overflow: visible;\r\n position: absolute;\r\n z-index: 2;\r\n top: 0;\r\n left: 0;\r\n}\r\n</style>","\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'image-polygon-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n createPath: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImagePolygonOutline.vue?vue&type=template&id=8d85e878&scoped=true\"\nimport script from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImagePolygonOutline.vue?vue&type=style&index=0&id=8d85e878&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-8d85e878\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport useClipImage from '../useClipImage'\r\n\r\nimport ImageRectOutline from './ImageRectOutline.vue'\r\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\r\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-outline',\r\n components: {\r\n ImageRectOutline,\r\n ImageEllipseOutline,\r\n ImagePolygonOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape } = useClipImage(clip)\r\n\r\n return {\r\n clipShape,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=6b56be7d\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div \r\n class=\"image-clip-handler\" \r\n :style=\"clipWrapperPositionStyle\" \r\n v-click-outside=\"handleClip\"\r\n >\r\n <img \r\n class=\"bottom-img\" \r\n :src=\"src\" \r\n :draggable=\"false\" \r\n alt=\"\" \r\n :style=\"bottomImgPositionStyle\" \r\n />\r\n\r\n <div \r\n class=\"top-image-content\" \r\n :style=\"{\r\n ...topImgWrapperPositionStyle,\r\n clipPath,\r\n }\"\r\n >\r\n <img \r\n class=\"top-img\" \r\n :src=\"src\" \r\n :draggable=\"false\" \r\n alt=\"\" \r\n :style=\"topImgPositionStyle\" \r\n />\r\n </div>\r\n\r\n <div \r\n class=\"operate\" \r\n :style=\"topImgWrapperPositionStyle\" \r\n @mousedown.stop=\"$event => moveClipRange($event)\"\r\n >\r\n <div \r\n :class=\"['clip-point', point]\" \r\n v-for=\"point in ['t-l', 't-r', 'b-l', 'b-r']\" \r\n :key=\"point\" \r\n @mousedown.stop=\"$event => scaleClipRange($event, point)\"\r\n >\r\n <SvgWrapper width=\"16\" height=\"16\" fill=\"#fff\" stroke=\"#333\">\r\n <path\r\n stroke-width=\"0.3\" \r\n shape-rendering=\"crispEdges\"\r\n d=\"M 16 0 L 0 0 L 0 16 L 4 16 L 4 4 L 16 4 L 16 0 Z\"\r\n ></path>\r\n </SvgWrapper>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { ImageClipData, ImageClipDataRange, ImageClipedEmitData } from '@/types/edit'\r\n\r\ntype ScaleClipRangeType = 't-l' | 't-r' | 'b-l' | 'b-r'\r\n\r\nexport default defineComponent({\r\n name: 'image-clip-handler',\r\n props: {\r\n src: {\r\n type: String,\r\n required: true,\r\n },\r\n clipData: {\r\n type: Object as PropType<ImageClipData>,\r\n },\r\n clipPath: {\r\n type: String,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n top: {\r\n type: Number,\r\n required: true,\r\n },\r\n left: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n\r\n const clipWrapperPositionStyle = reactive({\r\n top: '0',\r\n left: '0',\r\n })\r\n const isSettingClipRange = ref(false)\r\n const currentRange = ref<ImageClipDataRange | null>(null)\r\n\r\n // 获取裁剪区域信息(裁剪区域占原图的宽高比例,处在原图中的位置)\r\n const getClipDataTransformInfo = () => {\r\n const [start, end] = props.clipData ? props.clipData.range : [[0, 0], [100, 100]]\r\n\r\n const widthScale = (end[0] - start[0]) / 100\r\n const heightScale = (end[1] - start[1]) / 100\r\n const left = start[0] / widthScale\r\n const top = start[1] / heightScale\r\n\r\n return { widthScale, heightScale, left, top }\r\n }\r\n \r\n // 底层图片位置大小(遮罩区域图片)\r\n const imgPosition = computed(() => {\r\n const { widthScale, heightScale, left, top } = getClipDataTransformInfo()\r\n return {\r\n left: -left,\r\n top: -top,\r\n width: 100 / widthScale,\r\n height: 100 / heightScale,\r\n }\r\n })\r\n\r\n // 底层图片位置大小样式(遮罩区域图片)\r\n const bottomImgPositionStyle = computed(() => {\r\n return {\r\n top: imgPosition.value.top + '%',\r\n left: imgPosition.value.left + '%',\r\n width: imgPosition.value.width + '%',\r\n height: imgPosition.value.height + '%',\r\n }\r\n })\r\n\r\n // 顶层图片容器位置大小(裁剪高亮区域)\r\n const topImgWrapperPosition = reactive({\r\n top: 0,\r\n left: 0,\r\n width: 0,\r\n height: 0,\r\n })\r\n\r\n // 顶层图片容器位置大小样式(裁剪高亮区域)\r\n const topImgWrapperPositionStyle = computed(() => {\r\n return {\r\n top: topImgWrapperPosition.top + '%',\r\n left: topImgWrapperPosition.left + '%',\r\n width: topImgWrapperPosition.width + '%',\r\n height: topImgWrapperPosition.height + '%',\r\n }\r\n })\r\n\r\n // 顶层图片位置大小样式(裁剪区域图片)\r\n const topImgPositionStyle = computed(() => {\r\n const bottomWidth = imgPosition.value.width\r\n const bottomHeight = imgPosition.value.height\r\n \r\n const topLeft = topImgWrapperPosition.left\r\n const topTop = topImgWrapperPosition.top\r\n const topWidth = topImgWrapperPosition.width\r\n const topHeight = topImgWrapperPosition.height\r\n \r\n return {\r\n left: -topLeft * (100 / topWidth) + '%',\r\n top: -topTop * (100 / topHeight) + '%',\r\n width: bottomWidth / topWidth * 100 + '%',\r\n height: bottomHeight / topHeight * 100 + '%',\r\n }\r\n })\r\n\r\n // 初始化裁剪位置信息\r\n const initClipPosition = () => {\r\n const { left, top } = getClipDataTransformInfo()\r\n topImgWrapperPosition.left = left\r\n topImgWrapperPosition.top = top\r\n topImgWrapperPosition.width = 100\r\n topImgWrapperPosition.height = 100\r\n \r\n clipWrapperPositionStyle.top = -top + '%'\r\n clipWrapperPositionStyle.left = -left + '%'\r\n }\r\n\r\n // 执行裁剪:计算裁剪后的图片位置大小和裁剪信息,并将数据同步出去\r\n const handleClip = () => {\r\n if (isSettingClipRange.value) return\r\n\r\n if (!currentRange.value) {\r\n emit('clip', null)\r\n return\r\n }\r\n\r\n const { left, top } = getClipDataTransformInfo()\r\n\r\n const position = {\r\n left: (topImgWrapperPosition.left - left) / 100 * props.width,\r\n top: (topImgWrapperPosition.top - top) / 100 * props.height,\r\n width: (topImgWrapperPosition.width - 100) / 100 * props.width,\r\n height: (topImgWrapperPosition.height - 100) / 100 * props.height,\r\n }\r\n\r\n const clipedEmitData: ImageClipedEmitData = {\r\n range: currentRange.value,\r\n position,\r\n }\r\n emit('clip', clipedEmitData)\r\n }\r\n\r\n // 快捷键监听:回车确认裁剪\r\n const keyboardListener = (e: KeyboardEvent) => {\r\n const key = e.key.toUpperCase()\r\n if (key === KEYS.ENTER) handleClip()\r\n }\r\n\r\n onMounted(() => {\r\n initClipPosition()\r\n document.addEventListener('keydown', keyboardListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keyboardListener)\r\n })\r\n\r\n // 计算并更新裁剪区域范围数据\r\n const updateRange = () => {\r\n const retPosition = {\r\n left: parseInt(topImgPositionStyle.value.left),\r\n top: parseInt(topImgPositionStyle.value.top),\r\n width: parseInt(topImgPositionStyle.value.width),\r\n height: parseInt(topImgPositionStyle.value.height),\r\n }\r\n\r\n const widthScale = 100 / retPosition.width\r\n const heightScale = 100 / retPosition.height\r\n\r\n const start: [number, number] = [\r\n -retPosition.left * widthScale,\r\n -retPosition.top * heightScale,\r\n ]\r\n const end: [number, number] = [\r\n widthScale * 100 + start[0],\r\n heightScale * 100 + start[1],\r\n ]\r\n\r\n currentRange.value = [start, end]\r\n }\r\n\r\n // 移动裁剪区域\r\n const moveClipRange = (e: MouseEvent) => {\r\n isSettingClipRange.value = true\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n const bottomPosition = imgPosition.value\r\n const originPositopn = {\r\n left: topImgWrapperPosition.left,\r\n top: topImgWrapperPosition.top,\r\n width: topImgWrapperPosition.width,\r\n height: topImgWrapperPosition.height,\r\n }\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\r\n const moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\r\n\r\n let targetLeft = originPositopn.left + moveX\r\n let targetTop = originPositopn.top + moveY\r\n\r\n if (targetLeft < 0) targetLeft = 0\r\n else if (targetLeft + originPositopn.width > bottomPosition.width) {\r\n targetLeft = bottomPosition.width - originPositopn.width\r\n }\r\n if (targetTop < 0) targetTop = 0\r\n else if (targetTop + originPositopn.height > bottomPosition.height) {\r\n targetTop = bottomPosition.height - originPositopn.height\r\n }\r\n \r\n topImgWrapperPosition.left = targetLeft\r\n topImgWrapperPosition.top = targetTop\r\n }\r\n\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n updateRange()\r\n\r\n setTimeout(() => {\r\n isSettingClipRange.value = false\r\n }, 0)\r\n }\r\n }\r\n\r\n // 缩放裁剪区域\r\n const scaleClipRange = (e: MouseEvent, type: ScaleClipRangeType) => {\r\n isSettingClipRange.value = true\r\n let isMouseDown = true\r\n\r\n const minWidth = 50 / props.width * 100\r\n const minHeight = 50 / props.height * 100\r\n \r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n const bottomPosition = imgPosition.value\r\n const originPositopn = {\r\n left: topImgWrapperPosition.left,\r\n top: topImgWrapperPosition.top,\r\n width: topImgWrapperPosition.width,\r\n height: topImgWrapperPosition.height,\r\n }\r\n\r\n const aspectRatio = topImgWrapperPosition.width / topImgWrapperPosition.height\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n let moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\r\n let moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\r\n\r\n if (ctrlOrShiftKeyActive.value) {\r\n if (type === 'b-r' || type === 't-l') moveY = moveX / aspectRatio\r\n if (type === 'b-l' || type === 't-r') moveY = -moveX / aspectRatio\r\n }\r\n\r\n let targetLeft, targetTop, targetWidth, targetHeight\r\n\r\n if (type === 't-l') {\r\n if (originPositopn.left + moveX < 0) {\r\n moveX = -originPositopn.left\r\n }\r\n if (originPositopn.top + moveY < 0) {\r\n moveY = -originPositopn.top\r\n }\r\n if (originPositopn.width - moveX < minWidth) {\r\n moveX = originPositopn.width - minWidth\r\n }\r\n if (originPositopn.height - moveY < minHeight) {\r\n moveY = originPositopn.height - minHeight\r\n }\r\n targetWidth = originPositopn.width - moveX\r\n targetHeight = originPositopn.height - moveY\r\n targetLeft = originPositopn.left + moveX\r\n targetTop = originPositopn.top + moveY\r\n }\r\n else if (type === 't-r') {\r\n if (originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\r\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\r\n }\r\n if (originPositopn.top + moveY < 0) {\r\n moveY = -originPositopn.top\r\n }\r\n if (originPositopn.width + moveX < minWidth) {\r\n moveX = minWidth - originPositopn.width\r\n }\r\n if (originPositopn.height - moveY < minHeight) {\r\n moveY = originPositopn.height - minHeight\r\n }\r\n targetWidth = originPositopn.width + moveX\r\n targetHeight = originPositopn.height - moveY\r\n targetLeft = originPositopn.left\r\n targetTop = originPositopn.top + moveY\r\n }\r\n else if (type === 'b-l') {\r\n if (originPositopn.left + moveX < 0) {\r\n moveX = -originPositopn.left\r\n }\r\n if (originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\r\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\r\n }\r\n if (originPositopn.width - moveX < minWidth) {\r\n moveX = originPositopn.width - minWidth\r\n }\r\n if (originPositopn.height + moveY < minHeight) {\r\n moveY = minHeight - originPositopn.height\r\n }\r\n targetWidth = originPositopn.width - moveX\r\n targetHeight = originPositopn.height + moveY\r\n targetLeft = originPositopn.left + moveX\r\n targetTop = originPositopn.top\r\n }\r\n else {\r\n if (originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\r\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\r\n }\r\n if (originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\r\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\r\n }\r\n if (originPositopn.width + moveX < minWidth) {\r\n moveX = minWidth - originPositopn.width\r\n }\r\n if (originPositopn.height + moveY < minHeight) {\r\n moveY = minHeight - originPositopn.height\r\n }\r\n targetWidth = originPositopn.width + moveX\r\n targetHeight = originPositopn.height + moveY\r\n targetLeft = originPositopn.left\r\n targetTop = originPositopn.top\r\n }\r\n \r\n topImgWrapperPosition.left = targetLeft\r\n topImgWrapperPosition.top = targetTop\r\n topImgWrapperPosition.width = targetWidth\r\n topImgWrapperPosition.height = targetHeight\r\n }\r\n\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n updateRange()\r\n\r\n setTimeout(() => isSettingClipRange.value = false, 0)\r\n }\r\n }\r\n\r\n return {\r\n clipWrapperPositionStyle,\r\n bottomImgPositionStyle,\r\n topImgWrapperPositionStyle,\r\n topImgPositionStyle,\r\n handleClip,\r\n moveClipRange,\r\n scaleClipRange,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.image-clip-handler {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n .bottom-img {\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: .5;\r\n }\r\n\r\n img {\r\n width: 100%;\r\n height: 100%;\r\n }\r\n\r\n .top-image-content {\r\n position: absolute;\r\n overflow: hidden;\r\n\r\n img {\r\n position: absolute;\r\n }\r\n }\r\n}\r\n\r\n.operate {\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n top: 0;\r\n left: 0;\r\n cursor: move;\r\n}\r\n\r\n.clip-point {\r\n position: absolute;\r\n width: 16px;\r\n height: 16px;\r\n left: 0;\r\n top: 0;\r\n transform-origin: 0 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n\r\n svg {\r\n overflow: visible;\r\n }\r\n\r\n &.t-l {\r\n left: 0;\r\n top: 0;\r\n cursor: nwse-resize;\r\n }\r\n &.t-r {\r\n left: 100%;\r\n top: 0;\r\n transform: rotate(90deg);\r\n cursor: nesw-resize;\r\n }\r\n &.b-l {\r\n left: 0;\r\n top: 100%;\r\n transform: rotate(-90deg);\r\n cursor: nesw-resize;\r\n }\r\n &.b-r {\r\n left: 100%;\r\n top: 100%;\r\n transform: rotate(180deg);\r\n cursor: nwse-resize;\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { ImageClipData, ImageClipDataRange, ImageClipedEmitData } from '@/types/edit'\r\n\r\ntype ScaleClipRangeType = 't-l' | 't-r' | 'b-l' | 'b-r'\r\n\r\nexport default defineComponent({\r\n name: 'image-clip-handler',\r\n props: {\r\n src: {\r\n type: String,\r\n required: true,\r\n },\r\n clipData: {\r\n type: Object as PropType<ImageClipData>,\r\n },\r\n clipPath: {\r\n type: String,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n top: {\r\n type: Number,\r\n required: true,\r\n },\r\n left: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n\r\n const clipWrapperPositionStyle = reactive({\r\n top: '0',\r\n left: '0',\r\n })\r\n const isSettingClipRange = ref(false)\r\n const currentRange = ref<ImageClipDataRange | null>(null)\r\n\r\n // 获取裁剪区域信息(裁剪区域占原图的宽高比例,处在原图中的位置)\r\n const getClipDataTransformInfo = () => {\r\n const [start, end] = props.clipData ? props.clipData.range : [[0, 0], [100, 100]]\r\n\r\n const widthScale = (end[0] - start[0]) / 100\r\n const heightScale = (end[1] - start[1]) / 100\r\n const left = start[0] / widthScale\r\n const top = start[1] / heightScale\r\n\r\n return { widthScale, heightScale, left, top }\r\n }\r\n \r\n // 底层图片位置大小(遮罩区域图片)\r\n const imgPosition = computed(() => {\r\n const { widthScale, heightScale, left, top } = getClipDataTransformInfo()\r\n return {\r\n left: -left,\r\n top: -top,\r\n width: 100 / widthScale,\r\n height: 100 / heightScale,\r\n }\r\n })\r\n\r\n // 底层图片位置大小样式(遮罩区域图片)\r\n const bottomImgPositionStyle = computed(() => {\r\n return {\r\n top: imgPosition.value.top + '%',\r\n left: imgPosition.value.left + '%',\r\n width: imgPosition.value.width + '%',\r\n height: imgPosition.value.height + '%',\r\n }\r\n })\r\n\r\n // 顶层图片容器位置大小(裁剪高亮区域)\r\n const topImgWrapperPosition = reactive({\r\n top: 0,\r\n left: 0,\r\n width: 0,\r\n height: 0,\r\n })\r\n\r\n // 顶层图片容器位置大小样式(裁剪高亮区域)\r\n const topImgWrapperPositionStyle = computed(() => {\r\n return {\r\n top: topImgWrapperPosition.top + '%',\r\n left: topImgWrapperPosition.left + '%',\r\n width: topImgWrapperPosition.width + '%',\r\n height: topImgWrapperPosition.height + '%',\r\n }\r\n })\r\n\r\n // 顶层图片位置大小样式(裁剪区域图片)\r\n const topImgPositionStyle = computed(() => {\r\n const bottomWidth = imgPosition.value.width\r\n const bottomHeight = imgPosition.value.height\r\n \r\n const topLeft = topImgWrapperPosition.left\r\n const topTop = topImgWrapperPosition.top\r\n const topWidth = topImgWrapperPosition.width\r\n const topHeight = topImgWrapperPosition.height\r\n \r\n return {\r\n left: -topLeft * (100 / topWidth) + '%',\r\n top: -topTop * (100 / topHeight) + '%',\r\n width: bottomWidth / topWidth * 100 + '%',\r\n height: bottomHeight / topHeight * 100 + '%',\r\n }\r\n })\r\n\r\n // 初始化裁剪位置信息\r\n const initClipPosition = () => {\r\n const { left, top } = getClipDataTransformInfo()\r\n topImgWrapperPosition.left = left\r\n topImgWrapperPosition.top = top\r\n topImgWrapperPosition.width = 100\r\n topImgWrapperPosition.height = 100\r\n \r\n clipWrapperPositionStyle.top = -top + '%'\r\n clipWrapperPositionStyle.left = -left + '%'\r\n }\r\n\r\n // 执行裁剪:计算裁剪后的图片位置大小和裁剪信息,并将数据同步出去\r\n const handleClip = () => {\r\n if (isSettingClipRange.value) return\r\n\r\n if (!currentRange.value) {\r\n emit('clip', null)\r\n return\r\n }\r\n\r\n const { left, top } = getClipDataTransformInfo()\r\n\r\n const position = {\r\n left: (topImgWrapperPosition.left - left) / 100 * props.width,\r\n top: (topImgWrapperPosition.top - top) / 100 * props.height,\r\n width: (topImgWrapperPosition.width - 100) / 100 * props.width,\r\n height: (topImgWrapperPosition.height - 100) / 100 * props.height,\r\n }\r\n\r\n const clipedEmitData: ImageClipedEmitData = {\r\n range: currentRange.value,\r\n position,\r\n }\r\n emit('clip', clipedEmitData)\r\n }\r\n\r\n // 快捷键监听:回车确认裁剪\r\n const keyboardListener = (e: KeyboardEvent) => {\r\n const key = e.key.toUpperCase()\r\n if (key === KEYS.ENTER) handleClip()\r\n }\r\n\r\n onMounted(() => {\r\n initClipPosition()\r\n document.addEventListener('keydown', keyboardListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keyboardListener)\r\n })\r\n\r\n // 计算并更新裁剪区域范围数据\r\n const updateRange = () => {\r\n const retPosition = {\r\n left: parseInt(topImgPositionStyle.value.left),\r\n top: parseInt(topImgPositionStyle.value.top),\r\n width: parseInt(topImgPositionStyle.value.width),\r\n height: parseInt(topImgPositionStyle.value.height),\r\n }\r\n\r\n const widthScale = 100 / retPosition.width\r\n const heightScale = 100 / retPosition.height\r\n\r\n const start: [number, number] = [\r\n -retPosition.left * widthScale,\r\n -retPosition.top * heightScale,\r\n ]\r\n const end: [number, number] = [\r\n widthScale * 100 + start[0],\r\n heightScale * 100 + start[1],\r\n ]\r\n\r\n currentRange.value = [start, end]\r\n }\r\n\r\n // 移动裁剪区域\r\n const moveClipRange = (e: MouseEvent) => {\r\n isSettingClipRange.value = true\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n const bottomPosition = imgPosition.value\r\n const originPositopn = {\r\n left: topImgWrapperPosition.left,\r\n top: topImgWrapperPosition.top,\r\n width: topImgWrapperPosition.width,\r\n height: topImgWrapperPosition.height,\r\n }\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\r\n const moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\r\n\r\n let targetLeft = originPositopn.left + moveX\r\n let targetTop = originPositopn.top + moveY\r\n\r\n if (targetLeft < 0) targetLeft = 0\r\n else if (targetLeft + originPositopn.width > bottomPosition.width) {\r\n targetLeft = bottomPosition.width - originPositopn.width\r\n }\r\n if (targetTop < 0) targetTop = 0\r\n else if (targetTop + originPositopn.height > bottomPosition.height) {\r\n targetTop = bottomPosition.height - originPositopn.height\r\n }\r\n \r\n topImgWrapperPosition.left = targetLeft\r\n topImgWrapperPosition.top = targetTop\r\n }\r\n\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n updateRange()\r\n\r\n setTimeout(() => {\r\n isSettingClipRange.value = false\r\n }, 0)\r\n }\r\n }\r\n\r\n // 缩放裁剪区域\r\n const scaleClipRange = (e: MouseEvent, type: ScaleClipRangeType) => {\r\n isSettingClipRange.value = true\r\n let isMouseDown = true\r\n\r\n const minWidth = 50 / props.width * 100\r\n const minHeight = 50 / props.height * 100\r\n \r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n const bottomPosition = imgPosition.value\r\n const originPositopn = {\r\n left: topImgWrapperPosition.left,\r\n top: topImgWrapperPosition.top,\r\n width: topImgWrapperPosition.width,\r\n height: topImgWrapperPosition.height,\r\n }\r\n\r\n const aspectRatio = topImgWrapperPosition.width / topImgWrapperPosition.height\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n let moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\r\n let moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\r\n\r\n if (ctrlOrShiftKeyActive.value) {\r\n if (type === 'b-r' || type === 't-l') moveY = moveX / aspectRatio\r\n if (type === 'b-l' || type === 't-r') moveY = -moveX / aspectRatio\r\n }\r\n\r\n let targetLeft, targetTop, targetWidth, targetHeight\r\n\r\n if (type === 't-l') {\r\n if (originPositopn.left + moveX < 0) {\r\n moveX = -originPositopn.left\r\n }\r\n if (originPositopn.top + moveY < 0) {\r\n moveY = -originPositopn.top\r\n }\r\n if (originPositopn.width - moveX < minWidth) {\r\n moveX = originPositopn.width - minWidth\r\n }\r\n if (originPositopn.height - moveY < minHeight) {\r\n moveY = originPositopn.height - minHeight\r\n }\r\n targetWidth = originPositopn.width - moveX\r\n targetHeight = originPositopn.height - moveY\r\n targetLeft = originPositopn.left + moveX\r\n targetTop = originPositopn.top + moveY\r\n }\r\n else if (type === 't-r') {\r\n if (originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\r\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\r\n }\r\n if (originPositopn.top + moveY < 0) {\r\n moveY = -originPositopn.top\r\n }\r\n if (originPositopn.width + moveX < minWidth) {\r\n moveX = minWidth - originPositopn.width\r\n }\r\n if (originPositopn.height - moveY < minHeight) {\r\n moveY = originPositopn.height - minHeight\r\n }\r\n targetWidth = originPositopn.width + moveX\r\n targetHeight = originPositopn.height - moveY\r\n targetLeft = originPositopn.left\r\n targetTop = originPositopn.top + moveY\r\n }\r\n else if (type === 'b-l') {\r\n if (originPositopn.left + moveX < 0) {\r\n moveX = -originPositopn.left\r\n }\r\n if (originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\r\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\r\n }\r\n if (originPositopn.width - moveX < minWidth) {\r\n moveX = originPositopn.width - minWidth\r\n }\r\n if (originPositopn.height + moveY < minHeight) {\r\n moveY = minHeight - originPositopn.height\r\n }\r\n targetWidth = originPositopn.width - moveX\r\n targetHeight = originPositopn.height + moveY\r\n targetLeft = originPositopn.left + moveX\r\n targetTop = originPositopn.top\r\n }\r\n else {\r\n if (originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\r\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\r\n }\r\n if (originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\r\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\r\n }\r\n if (originPositopn.width + moveX < minWidth) {\r\n moveX = minWidth - originPositopn.width\r\n }\r\n if (originPositopn.height + moveY < minHeight) {\r\n moveY = minHeight - originPositopn.height\r\n }\r\n targetWidth = originPositopn.width + moveX\r\n targetHeight = originPositopn.height + moveY\r\n targetLeft = originPositopn.left\r\n targetTop = originPositopn.top\r\n }\r\n \r\n topImgWrapperPosition.left = targetLeft\r\n topImgWrapperPosition.top = targetTop\r\n topImgWrapperPosition.width = targetWidth\r\n topImgWrapperPosition.height = targetHeight\r\n }\r\n\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n updateRange()\r\n\r\n setTimeout(() => isSettingClipRange.value = false, 0)\r\n }\r\n }\r\n\r\n return {\r\n clipWrapperPositionStyle,\r\n bottomImgPositionStyle,\r\n topImgWrapperPositionStyle,\r\n topImgPositionStyle,\r\n handleClip,\r\n moveClipRange,\r\n scaleClipRange,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageClipHandler.vue?vue&type=template&id=1d9b5032&scoped=true\"\nimport script from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageClipHandler.vue?vue&type=style&index=0&id=1d9b5032&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1d9b5032\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { ImageClipedEmitData } from '@/types/edit'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\nimport useClipImage from './useClipImage'\r\nimport useFilter from './useFilter'\r\n\r\nimport ImageOutline from './ImageOutline/index.vue'\r\nimport ImageClipHandler from './ImageClipHandler.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-image',\r\n components: {\r\n ImageOutline,\r\n ImageClipHandler,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape, imgPosition } = useClipImage(clip)\r\n\r\n const filters = computed(() => props.elementInfo.filters)\r\n const { filter } = useFilter(filters)\r\n\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n const handleClip = (data: ImageClipedEmitData) => {\r\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, '')\r\n \r\n if (!data) return\r\n\r\n const { range, position } = data\r\n const originClip = props.elementInfo.clip || {}\r\n \r\n const _props = {\r\n clip: { ...originClip, range },\r\n left: props.elementInfo.left + position.left,\r\n top: props.elementInfo.top + position.top,\r\n width: props.elementInfo.width + position.width,\r\n height: props.elementInfo.height + position.height,\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: props.elementInfo.id, props: _props })\r\n }\r\n\r\n return {\r\n isCliping,\r\n handleClip,\r\n clipingImageElementId,\r\n shadowStyle,\r\n handleSelectElement,\r\n clipShape,\r\n imgPosition,\r\n filter,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=5e75c7ca&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=5e75c7ca&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5e75c7ca\"\n\nexport default script","<template>\r\n <div \r\n class=\"editable-element-text\" \r\n ref=\"elementRef\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n @mousedown=\"$event => handleSelectElement($event)\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n backgroundColor: elementInfo.fill,\r\n opacity: elementInfo.opacity,\r\n textShadow: shadowStyle,\r\n lineHeight: elementInfo.lineHeight,\r\n letterSpacing: (elementInfo.wordSpace || 0) + 'px',\r\n }\"\r\n v-contextmenu=\"contextmenus\"\r\n >\r\n <ElementOutline\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <div \r\n class=\"text\"\r\n ref=\"editorViewRef\"\r\n @mousedown=\"$event => handleSelectElement($event, false)\"\r\n ></div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport debounce from 'lodash/debounce'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { EditorView } from 'prosemirror-view'\r\nimport { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { initProsemirrorEditor } from '@/prosemirror/'\r\nimport { getTextAttrs } from '@/prosemirror/utils'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport { alignmentCommand } from '@/prosemirror/commands/setTextAlign'\r\nimport { toggleList } from '@/prosemirror/commands/toggleList'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\ninterface CommandPayload {\r\n command: string;\r\n value?: string;\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-text',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const elementRef = ref<HTMLElement>()\r\n\r\n const isScaling = ref(false)\r\n const realHeightCache = ref(-1)\r\n\r\n const editorViewRef = ref<HTMLElement>()\r\n let editorView: EditorView\r\n\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n\r\n const handleSelectElement = (e: MouseEvent, canMove = true) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo, canMove)\r\n }\r\n\r\n // 监听文本元素的尺寸变化,当高度变化时,更新高度到vuex\r\n // 如果高度变化时正处在缩放操作中,则等待缩放操作结束后再更新\r\n const scaleElementStateListener = (state: boolean) => {\r\n isScaling.value = state\r\n\r\n if (!state && realHeightCache.value !== -1) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeightCache.value },\r\n })\r\n realHeightCache.value = -1\r\n }\r\n }\r\n\r\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n })\r\n\r\n const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {\r\n const contentRect = entries[0].contentRect\r\n if (!elementRef.value) return\r\n\r\n const realHeight = contentRect.height\r\n\r\n if (props.elementInfo.height !== realHeight) {\r\n if (!isScaling.value) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeight },\r\n })\r\n }\r\n else realHeightCache.value = realHeight\r\n }\r\n }\r\n const resizeObserver = new ResizeObserver(updateTextElementHeight)\r\n\r\n onMounted(() => {\r\n if (elementRef.value) resizeObserver.observe(elementRef.value)\r\n })\r\n onUnmounted(() => {\r\n if (elementRef.value) resizeObserver.unobserve(elementRef.value)\r\n })\r\n\r\n // 富文本的各种交互事件监听:\r\n // 聚焦时取消全局快捷键事件\r\n // 输入文字时同步数据到vuex\r\n // 点击鼠标和键盘时同步富文本状态到工具栏\r\n const handleFocus = () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, true)\r\n }\r\n const handleBlur = () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, false)\r\n }\r\n const handleInput = debounce(function() {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { content: editorView.dom.innerHTML },\r\n })\r\n addHistorySnapshot()\r\n }, 300, { trailing: true })\r\n\r\n const handleClick = debounce(function() {\r\n const attr = getTextAttrs(editorView)\r\n emitter.emit(EmitterEvents.UPDATE_TEXT_STATE, attr)\r\n }, 30, { trailing: true })\r\n\r\n const handleKeydown = () => {\r\n handleInput()\r\n handleClick()\r\n }\r\n\r\n // 将富文本内容同步到DOM\r\n const textContent = computed(() => props.elementInfo.content)\r\n watch(textContent, () => {\r\n if (!editorView) return\r\n if (editorView.hasFocus()) return\r\n editorView.dom.innerHTML = textContent.value\r\n })\r\n\r\n // 打开/关闭编辑器的编辑模式\r\n const editable = computed(() => !props.elementInfo.lock)\r\n watch(editable, () => {\r\n editorView.setProps({ editable: () => editable.value })\r\n })\r\n\r\n // Prosemirror编辑器的初始化和卸载\r\n onMounted(() => {\r\n editorView = initProsemirrorEditor((editorViewRef.value as Element), textContent.value, {\r\n handleDOMEvents: {\r\n focus: handleFocus,\r\n blur: handleBlur,\r\n keydown: handleKeydown,\r\n click: handleClick,\r\n },\r\n editable: () => editable.value,\r\n })\r\n })\r\n onUnmounted(() => {\r\n editorView && editorView.destroy()\r\n })\r\n \r\n // 执行富文本命令(可以是一个或多个)\r\n // 部分命令在执行前先判断当前选区是否为空,如果选区为空先进行全选操作\r\n const execCommand = (payload: CommandPayload | CommandPayload[]) => {\r\n if (handleElementId.value !== props.elementInfo.id) return\r\n\r\n const commands = ('command' in payload) ? [payload] : payload\r\n\r\n for (const item of commands) {\r\n if (item.command === 'fontname' && item.value) {\r\n const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'fontsize' && item.value) {\r\n const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'color' && item.value) {\r\n const mark = editorView.state.schema.marks.forecolor.create({ color: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'backcolor' && item.value) {\r\n const mark = editorView.state.schema.marks.backcolor.create({ backcolor: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'bold') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'em') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'underline') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'strikethrough') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'subscript') {\r\n toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'superscript') {\r\n toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'blockquote') {\r\n wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'code') {\r\n toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'align' && item.value) {\r\n alignmentCommand(editorView, item.value)\r\n }\r\n else if (item.command === 'bulletList') {\r\n const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes\r\n toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'orderedList') {\r\n const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes\r\n toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'clear') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))\r\n }\r\n }\r\n\r\n editorView.focus()\r\n handleInput()\r\n handleClick()\r\n }\r\n\r\n emitter.on(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\r\n })\r\n\r\n return {\r\n elementRef,\r\n editorViewRef,\r\n handleSelectElement,\r\n shadowStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-text {\r\n position: absolute;\r\n cursor: move;\r\n\r\n &.lock .element-content {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n position: relative;\r\n padding: 10px;\r\n line-height: 1.5;\r\n word-break: break-word;\r\n\r\n .text {\r\n position: relative;\r\n cursor: text;\r\n }\r\n}\r\n</style>\r\n","import { splitListItem, liftListItem, sinkListItem } from 'prosemirror-schema-list'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { undo, redo } from 'prosemirror-history'\r\nimport { undoInputRule } from 'prosemirror-inputrules'\r\nimport {\r\n toggleMark,\r\n selectParentNode,\r\n joinUp,\r\n joinDown,\r\n Command,\r\n} from 'prosemirror-commands'\r\n\r\nexport const buildKeymap = (schema: Schema) => {\r\n const keys = {}\r\n const bind = (key: string, cmd: Command) => keys[key] = cmd\r\n\r\n bind('Alt-ArrowUp', joinUp)\r\n bind('Alt-ArrowDown', joinDown)\r\n bind('Ctrl-z', undo)\r\n bind('Ctrl-y', redo)\r\n bind('Backspace', undoInputRule)\r\n bind('Escape', selectParentNode)\r\n bind('Ctrl-b', toggleMark(schema.marks.strong))\r\n bind('Ctrl-i', toggleMark(schema.marks.em))\r\n bind('Ctrl-u', toggleMark(schema.marks.underline))\r\n bind('Ctrl-d', toggleMark(schema.marks.strikethrough))\r\n\r\n bind('Enter', splitListItem(schema.nodes.list_item))\r\n bind('Mod-[', liftListItem(schema.nodes.list_item))\r\n bind('Mod-]', sinkListItem(schema.nodes.list_item))\r\n\r\n return keys\r\n}","import { NodeType, Schema } from 'prosemirror-model'\r\nimport {\r\n inputRules,\r\n wrappingInputRule,\r\n textblockTypeInputRule,\r\n smartQuotes,\r\n emDash,\r\n ellipsis,\r\n} from 'prosemirror-inputrules'\r\n\r\nconst blockQuoteRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*>\\s$/, nodeType)\r\n\r\nconst orderedListRule = (nodeType: NodeType) => (\r\n wrappingInputRule(\r\n /^(\\d+)\\.\\s$/, \r\n nodeType, \r\n match => ({order: +match[1]}),\r\n (match, node) => node.childCount + node.attrs.order === +match[1],\r\n )\r\n)\r\n\r\nconst bulletListRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*([-+*])\\s$/, nodeType)\r\n\r\nconst codeBlockRule = (nodeType: NodeType) => textblockTypeInputRule(/^```$/, nodeType)\r\n\r\nexport const buildInputRules = (schema: Schema) => {\r\n const rules = [\r\n ...smartQuotes,\r\n ellipsis,\r\n emDash,\r\n ]\r\n rules.push(blockQuoteRule(schema.nodes.blockquote))\r\n rules.push(orderedListRule(schema.nodes.ordered_list))\r\n rules.push(bulletListRule(schema.nodes.bullet_list))\r\n rules.push(codeBlockRule(schema.nodes.code_block))\r\n\r\n return inputRules({ rules })\r\n}","import { keymap } from 'prosemirror-keymap'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { history } from 'prosemirror-history'\r\nimport { baseKeymap } from 'prosemirror-commands'\r\nimport { dropCursor } from 'prosemirror-dropcursor'\r\nimport { gapCursor } from 'prosemirror-gapcursor'\r\n\r\nimport { buildKeymap } from './keymap'\r\nimport { buildInputRules } from './inputrules'\r\n\r\nexport const buildPlugins = (schema: Schema) => {\r\n return [\r\n buildInputRules(schema),\r\n keymap(buildKeymap(schema)),\r\n keymap(baseKeymap),\r\n dropCursor(),\r\n gapCursor(),\r\n history(),\r\n ]\r\n}","import { nodes } from 'prosemirror-schema-basic'\r\nimport { Node, NodeSpec } from 'prosemirror-model'\r\nimport { orderedList, bulletList, listItem } from 'prosemirror-schema-list'\r\n\r\nconst _orderedList: NodeSpec = {\r\n ...orderedList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _bulletList: NodeSpec = {\r\n ...bulletList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _listItem: NodeSpec = {\r\n ...listItem,\r\n content: 'paragraph block*',\r\n group: 'block',\r\n}\r\n\r\nconst paragraph: NodeSpec = {\r\n attrs: {\r\n align: {\r\n default: '',\r\n },\r\n },\r\n content: 'inline*',\r\n group: 'block',\r\n parseDOM: [\r\n {\r\n tag: 'p',\r\n getAttrs: dom => {\r\n const { textAlign } = (dom as HTMLElement).style\r\n let align = (dom as HTMLElement).getAttribute('align') || textAlign || ''\r\n align = /(left|right|center|justify)/.test(align) ? align : ''\r\n \r\n return { align }\r\n }\r\n }\r\n ],\r\n toDOM: (node: Node) => {\r\n const { align } = node.attrs\r\n let style = ''\r\n if (align && align !== 'left') style += `text-align: ${align};`\r\n\r\n return ['p', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...nodes,\r\n 'ordered_list': _orderedList,\r\n 'bullet_list': _bulletList,\r\n 'list_item': _listItem,\r\n paragraph,\r\n}\r\n","import { marks } from 'prosemirror-schema-basic'\r\nimport { MarkSpec } from 'prosemirror-model'\r\n\r\nconst subscript: MarkSpec = {\r\n excludes: 'subscript',\r\n parseDOM: [\r\n { tag: 'sub' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'sub' && null\r\n },\r\n ],\r\n toDOM: () => ['sub', 0],\r\n}\r\n\r\nconst superscript: MarkSpec = {\r\n excludes: 'superscript',\r\n parseDOM: [\r\n { tag: 'sup' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'super' && null\r\n },\r\n ],\r\n toDOM: () => ['sup', 0],\r\n}\r\n\r\nconst strikethrough: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'strike' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration-line: line-through' }, 0],\r\n}\r\n\r\nconst underline: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'u' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration: underline' }, 0],\r\n}\r\n\r\nconst forecolor: MarkSpec = {\r\n attrs: {\r\n color: {},\r\n },\r\n parseDOM: [\r\n {\r\n style: 'color',\r\n getAttrs: color => color ? { color } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { color } = mark.attrs\r\n let style = ''\r\n if (color) style += `color: ${color};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst backcolor: MarkSpec = {\r\n attrs: {\r\n backcolor: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n tag: 'span[style*=background-color]',\r\n getAttrs: backcolor => backcolor ? { backcolor } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { backcolor } = mark.attrs\r\n let style = ''\r\n if (backcolor) style += `background-color: ${backcolor};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontsize: MarkSpec = {\r\n attrs: {\r\n fontsize: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-size',\r\n getAttrs: fontsize => fontsize ? { fontsize } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontsize } = mark.attrs\r\n let style = ''\r\n if (fontsize) style += `font-size: ${fontsize}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontname: MarkSpec = {\r\n attrs: {\r\n fontname: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-family',\r\n getAttrs: fontname => {\r\n return { fontname: fontname && typeof fontname === 'string' ? fontname.replace(/[\\\"\\']/g, '') : '' }\r\n }\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontname } = mark.attrs\r\n let style = ''\r\n if (fontname) style += `font-family: ${fontname}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...marks,\r\n subscript,\r\n superscript,\r\n strikethrough,\r\n underline,\r\n forecolor,\r\n backcolor,\r\n fontsize,\r\n fontname,\r\n}","import nodes from './nodes'\r\nimport marks from './marks'\r\n\r\nexport const schemaNodes = nodes\r\nexport const schemaMarks = marks\r\n","import { EditorState } from 'prosemirror-state'\r\nimport { EditorView } from 'prosemirror-view'\r\nimport { Schema, DOMParser } from 'prosemirror-model'\r\n\r\nimport { buildPlugins } from './plugins/index'\r\nimport { schemaNodes, schemaMarks } from './schema/index'\r\n\r\nconst schema = new Schema({\r\n nodes: schemaNodes,\r\n marks: schemaMarks,\r\n})\r\n\r\nconst createDocument = (content: string) => {\r\n const htmlString = `<div>${content}</div>`\r\n const parser = new window.DOMParser()\r\n const element = parser.parseFromString(htmlString, 'text/html').body.firstElementChild\r\n return DOMParser.fromSchema(schema).parse(element as Element)\r\n}\r\n\r\nexport const initProsemirrorEditor = (dom: Element, content: string, props = {}) => {\r\n return new EditorView(dom, {\r\n state: EditorState.create({\r\n doc: createDocument(content),\r\n plugins: buildPlugins(schema),\r\n }),\r\n ...props,\r\n })\r\n}","import { Node, NodeType, ResolvedPos } from 'prosemirror-model'\r\nimport { EditorState, Selection } from 'prosemirror-state'\r\nimport { EditorView } from 'prosemirror-view'\r\n\r\nconst equalNodeType = (nodeType: NodeType, node: Node) => {\r\n return Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1 || node.type === nodeType\r\n}\r\n\r\nconst findParentNodeClosestToPos = ($pos: ResolvedPos, predicate: (node: Node) => boolean) => {\r\n for (let i = $pos.depth; i > 0; i--) {\r\n const node = $pos.node(i)\r\n if (predicate(node)) {\r\n return {\r\n pos: i > 0 ? $pos.before(i) : 0,\r\n start: $pos.start(i),\r\n depth: i,\r\n node,\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport const findParentNode = (predicate: (node: Node) => boolean) => {\r\n return (_ref: Selection) => findParentNodeClosestToPos(_ref.$from, predicate)\r\n}\r\n\r\nexport const findParentNodeOfType = (nodeType: NodeType) => {\r\n return (selection: Selection) => {\r\n return findParentNode((node: Node) => {\r\n return equalNodeType(nodeType, node)\r\n })(selection)\r\n }\r\n}\r\n\r\nexport const isActiveOfParentNodeType = (nodeType: string, state: EditorState) => {\r\n const node = state.schema.nodes[nodeType]\r\n return !!findParentNodeOfType(node)(state.selection)\r\n}\r\n\r\nexport const getMarkAttrs = (view: EditorView) => {\r\n const { selection, doc } = view.state\r\n const { from } = selection\r\n const node = doc.nodeAt(from)\r\n return node?.marks || []\r\n}\r\n\r\nexport const getAttrValue = (view: EditorView, markType: string, attr: string) => {\r\n const marks = getMarkAttrs(view)\r\n for (const mark of marks) {\r\n if (mark.type.name === markType && mark.attrs[attr]) return mark.attrs[attr]\r\n }\r\n return null\r\n}\r\n\r\nexport const isActiveMark = (view: EditorView, markType: string) => {\r\n const marks = getMarkAttrs(view)\r\n for (const mark of marks) {\r\n if (mark.type.name === markType) return true\r\n }\r\n return false\r\n}\r\n\r\nexport const getAttrValueInSelection = (view: EditorView, attr: string) => {\r\n const { selection, doc } = view.state\r\n const { from, to } = selection\r\n\r\n let keepChecking = true\r\n let value = ''\r\n doc.nodesBetween(from, to, node => {\r\n if (keepChecking && node.attrs[attr]) {\r\n keepChecking = false\r\n value = node.attrs[attr]\r\n }\r\n return keepChecking\r\n })\r\n return value\r\n}\r\n\r\nexport const getTextAttrs = (view: EditorView) => {\r\n const isBold = isActiveMark(view, 'strong')\r\n const isEm = isActiveMark(view, 'em')\r\n const isUnderline = isActiveMark(view, 'underline')\r\n const isStrikethrough = isActiveMark(view, 'strikethrough')\r\n const isSuperscript = isActiveMark(view, 'superscript')\r\n const isSubscript = isActiveMark(view, 'subscript')\r\n const isCode = isActiveMark(view, 'code')\r\n const color = getAttrValue(view, 'forecolor', 'color') || '#000'\r\n const backcolor = getAttrValue(view, 'backcolor', 'backcolor') || '#000'\r\n const fontsize = getAttrValue(view, 'fontsize', 'fontsize') || '20px'\r\n const fontname = getAttrValue(view, 'fontname', 'fontname') || '微软雅黑'\r\n const align = getAttrValueInSelection(view, 'align') || 'left'\r\n const isBulletList = isActiveOfParentNodeType('bullet_list', view.state)\r\n const isOrderedList = isActiveOfParentNodeType('ordered_list', view.state)\r\n const isBlockquote = isActiveOfParentNodeType('blockquote', view.state)\r\n\r\n return {\r\n bold: isBold,\r\n em: isEm,\r\n underline: isUnderline,\r\n strikethrough: isStrikethrough,\r\n superscript: isSuperscript,\r\n subscript: isSubscript,\r\n code: isCode,\r\n color: color,\r\n backcolor: backcolor,\r\n fontsize: fontsize,\r\n fontname: fontname,\r\n align: align,\r\n bulletList: isBulletList,\r\n orderedList: isOrderedList,\r\n blockquote: isBlockquote,\r\n }\r\n}\r\n\r\nexport type TextAttrs = ReturnType<typeof getTextAttrs>","import { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction } from 'prosemirror-state'\r\nimport { EditorView } from 'prosemirror-view'\r\n\r\nexport const setTextAlign = (tr: Transaction, schema: Schema, alignment: string) => {\r\n const { selection, doc } = tr\r\n if (!selection || !doc) return tr\r\n\r\n const { from, to } = selection\r\n const { nodes } = schema\r\n\r\n const blockquote = nodes.blockquote\r\n const listItem = nodes.list_item\r\n const paragraph = nodes.paragraph\r\n\r\n interface Task {\r\n node: Node;\r\n pos: number;\r\n nodeType: NodeType;\r\n }\r\n\r\n const tasks: Task[] = []\r\n alignment = alignment || ''\r\n\r\n const allowedNodeTypes = new Set([blockquote, listItem, paragraph])\r\n\r\n doc.nodesBetween(from, to, (node, pos) => {\r\n const nodeType = node.type\r\n const align = node.attrs.align || ''\r\n if (align !== alignment && allowedNodeTypes.has(nodeType)) {\r\n tasks.push({\r\n node,\r\n pos,\r\n nodeType,\r\n })\r\n }\r\n return true\r\n })\r\n\r\n if (!tasks.length) return tr\r\n\r\n tasks.forEach(task => {\r\n const { node, pos, nodeType } = task\r\n let { attrs } = node\r\n if (alignment) attrs = { ...attrs, align: alignment }\r\n else attrs = { ...attrs, align: null }\r\n tr = tr.setNodeMarkup(pos, nodeType, attrs, node.marks)\r\n })\r\n\r\n return tr\r\n}\r\n\r\nexport const alignmentCommand = (view: EditorView, alignment: string) => {\r\n const { state } = view\r\n const { schema, selection } = state\r\n const tr = setTextAlign(\r\n state.tr.setSelection(selection),\r\n schema,\r\n alignment,\r\n )\r\n view.dispatch(tr)\r\n}","import { wrapInList, liftListItem } from 'prosemirror-schema-list'\r\nimport { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction, EditorState } from 'prosemirror-state'\r\nimport { findParentNode } from '../utils'\r\n\r\nconst isList = (node: Node, schema: Schema) => {\r\n return (\r\n node.type === schema.nodes.bullet_list ||\r\n node.type === schema.nodes.ordered_list\r\n )\r\n}\r\n\r\nexport const toggleList = (listType: NodeType, itemType: NodeType) => {\r\n return (state: EditorState, dispatch: (tr: Transaction) => void) => {\r\n const { schema, selection } = state\r\n const { $from, $to } = selection\r\n const range = $from.blockRange($to)\r\n\r\n if (!range) return false\r\n\r\n const parentList = findParentNode((node: Node) => isList(node, schema))(selection)\r\n\r\n if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {\r\n if (parentList.node.type === listType) {\r\n return liftListItem(itemType)(state, dispatch)\r\n }\r\n\r\n if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {\r\n const { tr } = state\r\n tr.setNodeMarkup(parentList.pos, listType)\r\n\r\n if (dispatch) dispatch(tr)\r\n\r\n return false\r\n }\r\n }\r\n\r\n return wrapInList(listType)(state, dispatch)\r\n }\r\n}\r\n","<template>\r\n <SvgWrapper \r\n class=\"element-outline\"\r\n v-if=\"outline\"\r\n overflow=\"visible\" \r\n :width=\"width\"\r\n :height=\"height\"\r\n >\r\n <path \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin\r\n fill=\"transparent\"\r\n :d=\"`M0,0 L${width},0 L${width},${height} L0,${height} Z`\" \r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 6' : '0 0'\" \r\n ></path>\r\n\t</SvgWrapper>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'element-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\nsvg {\r\n overflow: visible;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n}\r\n</style>","\r\nimport { PropType, defineComponent, toRef } from 'vue'\r\nimport { PPTElementOutline } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\n\r\nexport default defineComponent({\r\n name: 'element-outline',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>\r\n },\r\n },\r\n setup(props) {\r\n const {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n } = useElementOutline(toRef(props, 'outline'))\r\n\r\n return {\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=2ddaa919&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=2ddaa919&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2ddaa919\"\n\nexport default script","\r\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport debounce from 'lodash/debounce'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { EditorView } from 'prosemirror-view'\r\nimport { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { initProsemirrorEditor } from '@/prosemirror/'\r\nimport { getTextAttrs } from '@/prosemirror/utils'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport { alignmentCommand } from '@/prosemirror/commands/setTextAlign'\r\nimport { toggleList } from '@/prosemirror/commands/toggleList'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\ninterface CommandPayload {\r\n command: string;\r\n value?: string;\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-text',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const elementRef = ref<HTMLElement>()\r\n\r\n const isScaling = ref(false)\r\n const realHeightCache = ref(-1)\r\n\r\n const editorViewRef = ref<HTMLElement>()\r\n let editorView: EditorView\r\n\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n\r\n const handleSelectElement = (e: MouseEvent, canMove = true) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo, canMove)\r\n }\r\n\r\n // 监听文本元素的尺寸变化,当高度变化时,更新高度到vuex\r\n // 如果高度变化时正处在缩放操作中,则等待缩放操作结束后再更新\r\n const scaleElementStateListener = (state: boolean) => {\r\n isScaling.value = state\r\n\r\n if (!state && realHeightCache.value !== -1) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeightCache.value },\r\n })\r\n realHeightCache.value = -1\r\n }\r\n }\r\n\r\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n })\r\n\r\n const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {\r\n const contentRect = entries[0].contentRect\r\n if (!elementRef.value) return\r\n\r\n const realHeight = contentRect.height\r\n\r\n if (props.elementInfo.height !== realHeight) {\r\n if (!isScaling.value) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeight },\r\n })\r\n }\r\n else realHeightCache.value = realHeight\r\n }\r\n }\r\n const resizeObserver = new ResizeObserver(updateTextElementHeight)\r\n\r\n onMounted(() => {\r\n if (elementRef.value) resizeObserver.observe(elementRef.value)\r\n })\r\n onUnmounted(() => {\r\n if (elementRef.value) resizeObserver.unobserve(elementRef.value)\r\n })\r\n\r\n // 富文本的各种交互事件监听:\r\n // 聚焦时取消全局快捷键事件\r\n // 输入文字时同步数据到vuex\r\n // 点击鼠标和键盘时同步富文本状态到工具栏\r\n const handleFocus = () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, true)\r\n }\r\n const handleBlur = () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, false)\r\n }\r\n const handleInput = debounce(function() {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { content: editorView.dom.innerHTML },\r\n })\r\n addHistorySnapshot()\r\n }, 300, { trailing: true })\r\n\r\n const handleClick = debounce(function() {\r\n const attr = getTextAttrs(editorView)\r\n emitter.emit(EmitterEvents.UPDATE_TEXT_STATE, attr)\r\n }, 30, { trailing: true })\r\n\r\n const handleKeydown = () => {\r\n handleInput()\r\n handleClick()\r\n }\r\n\r\n // 将富文本内容同步到DOM\r\n const textContent = computed(() => props.elementInfo.content)\r\n watch(textContent, () => {\r\n if (!editorView) return\r\n if (editorView.hasFocus()) return\r\n editorView.dom.innerHTML = textContent.value\r\n })\r\n\r\n // 打开/关闭编辑器的编辑模式\r\n const editable = computed(() => !props.elementInfo.lock)\r\n watch(editable, () => {\r\n editorView.setProps({ editable: () => editable.value })\r\n })\r\n\r\n // Prosemirror编辑器的初始化和卸载\r\n onMounted(() => {\r\n editorView = initProsemirrorEditor((editorViewRef.value as Element), textContent.value, {\r\n handleDOMEvents: {\r\n focus: handleFocus,\r\n blur: handleBlur,\r\n keydown: handleKeydown,\r\n click: handleClick,\r\n },\r\n editable: () => editable.value,\r\n })\r\n })\r\n onUnmounted(() => {\r\n editorView && editorView.destroy()\r\n })\r\n \r\n // 执行富文本命令(可以是一个或多个)\r\n // 部分命令在执行前先判断当前选区是否为空,如果选区为空先进行全选操作\r\n const execCommand = (payload: CommandPayload | CommandPayload[]) => {\r\n if (handleElementId.value !== props.elementInfo.id) return\r\n\r\n const commands = ('command' in payload) ? [payload] : payload\r\n\r\n for (const item of commands) {\r\n if (item.command === 'fontname' && item.value) {\r\n const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'fontsize' && item.value) {\r\n const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'color' && item.value) {\r\n const mark = editorView.state.schema.marks.forecolor.create({ color: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'backcolor' && item.value) {\r\n const mark = editorView.state.schema.marks.backcolor.create({ backcolor: item.value })\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\r\n }\r\n else if (item.command === 'bold') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'em') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'underline') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'strikethrough') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'subscript') {\r\n toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'superscript') {\r\n toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'blockquote') {\r\n wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'code') {\r\n toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'align' && item.value) {\r\n alignmentCommand(editorView, item.value)\r\n }\r\n else if (item.command === 'bulletList') {\r\n const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes\r\n toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'orderedList') {\r\n const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes\r\n toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)\r\n }\r\n else if (item.command === 'clear') {\r\n const { empty } = editorView.state.selection\r\n if (empty) selectAll(editorView.state, editorView.dispatch)\r\n const { $from, $to } = editorView.state.selection\r\n editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))\r\n }\r\n }\r\n\r\n editorView.focus()\r\n handleInput()\r\n handleClick()\r\n }\r\n\r\n emitter.on(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\r\n })\r\n\r\n return {\r\n elementRef,\r\n editorViewRef,\r\n handleSelectElement,\r\n shadowStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=3f17bdc9&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=3f17bdc9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3f17bdc9\"\n\nexport default script","<template>\r\n <div \r\n class=\"editable-element-shape\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n @mousedown=\"$event => handleSelectElement($event)\"\r\n >\r\n <div \r\n class=\"element-content\" \r\n v-contextmenu=\"contextmenus\"\r\n :style=\"{\r\n opacity: elementInfo.opacity,\r\n filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',\r\n transform: flipStyle,\r\n }\"\r\n >\r\n <SvgWrapper \r\n overflow=\"visible\" \r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n >\r\n <defs v-if=\"elementInfo.gradient\">\r\n <GradientDefs\r\n :id=\"`editabel-gradient-${elementInfo.id}`\" \r\n :type=\"elementInfo.gradient.type\"\r\n :color1=\"elementInfo.gradient.color[0]\"\r\n :color2=\"elementInfo.gradient.color[1]\"\r\n :rotate=\"elementInfo.gradient.rotate\"\r\n />\r\n </defs>\r\n <g \r\n :transform=\"`scale(${elementInfo.width / elementInfo.viewBox}, ${elementInfo.height / elementInfo.viewBox}) translate(0,0) matrix(1,0,0,1,0,0)`\"\r\n >\r\n <path \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin=\"\" \r\n :d=\"elementInfo.path\" \r\n :fill=\"elementInfo.gradient ? `url(#editabel-gradient-${elementInfo.id})` : elementInfo.fill\"\r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 6' : '0 0'\" \r\n ></path>\r\n </g>\r\n\t\t\t</SvgWrapper>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\n\r\nimport GradientDefs from './GradientDefs.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n GradientDefs,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n const outline = computed(() => props.elementInfo.outline)\r\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n return {\r\n handleSelectElement,\r\n shadowStyle,\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-shape {\r\n position: absolute;\r\n cursor: move;\r\n\r\n &.lock .element-content {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n svg {\r\n transform-origin: 0 0;\r\n overflow: visible;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <linearGradient \r\n v-if=\"type === 'linear'\"\r\n :id=\"id\" \r\n x1=\"0%\" \r\n y1=\"0%\" \r\n x2=\"100%\" \r\n y2=\"0%\" \r\n :gradientTransform=\"`rotate(${rotate},0.5,0.5)`\"\r\n >\r\n <stop offset=\"0%\" :stop-color=\"color1\" />\r\n <stop offset=\"100%\" :stop-color=\"color2\" />\r\n </linearGradient>\r\n\r\n <radialGradient :id=\"id\" v-else>\r\n <stop offset=\"0%\" :stop-color=\"color1\" />\r\n <stop offset=\"100%\" :stop-color=\"color2\" />\r\n </radialGradient>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'gradient-defs',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'linear' | 'radial'>,\r\n },\r\n color1: {\r\n type: String,\r\n required: true,\r\n },\r\n color2: {\r\n type: String,\r\n required: true,\r\n },\r\n rotate: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n})\r\n</script>","\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'gradient-defs',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'linear' | 'radial'>,\r\n },\r\n color1: {\r\n type: String,\r\n required: true,\r\n },\r\n color2: {\r\n type: String,\r\n required: true,\r\n },\r\n rotate: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n})\r\n","import { render } from \"./GradientDefs.vue?vue&type=template&id=b787d5ea\"\nimport script from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nexport * from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\n\r\nimport GradientDefs from './GradientDefs.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n GradientDefs,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n const outline = computed(() => props.elementInfo.outline)\r\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n return {\r\n handleSelectElement,\r\n shadowStyle,\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=a0860bd0&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=a0860bd0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a0860bd0\"\n\nexport default script","<template>\r\n <div \r\n class=\"editable-element-shape\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\" \r\n :style=\"{ filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '' }\"\r\n >\r\n <SvgWrapper\r\n overflow=\"visible\" \r\n :width=\"svgWidth\"\r\n :height=\"svgHeight\"\r\n >\r\n <defs>\r\n <LinePointMarker\r\n v-if=\"elementInfo.points[0]\"\r\n :id=\"elementInfo.id\"\r\n position=\"start\"\r\n :type=\"elementInfo.points[0]\"\r\n :color=\"elementInfo.color\"\r\n :baseSize=\"elementInfo.width\"\r\n />\r\n <LinePointMarker\r\n v-if=\"elementInfo.points[1]\"\r\n :id=\"elementInfo.id\"\r\n position=\"end\"\r\n :type=\"elementInfo.points[1]\"\r\n :color=\"elementInfo.color\"\r\n :baseSize=\"elementInfo.width\"\r\n />\r\n </defs>\r\n\t\t\t\t<path\r\n :d=\"path\" \r\n :stroke=\"elementInfo.color\" \r\n :stroke-width=\"elementInfo.width\" \r\n :stroke-dasharray=\"lineDashArray\"\r\n fill=\"none\" \r\n stroke-linecap \r\n stroke-linejoin \r\n stroke-miterlimit \r\n :marker-start=\"elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''\"\r\n :marker-end=\"elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''\"\r\n ></path>\r\n\t\t\t\t<path\r\n class=\"line-path\"\r\n :d=\"path\" \r\n stroke=\"transparent\" \r\n stroke-width=\"20\" \r\n fill=\"none\" \r\n @mousedown=\"$event => handleSelectElement($event)\"\r\n v-contextmenu=\"contextmenus\"\r\n ></path>\r\n\t\t\t</SvgWrapper>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nimport LinePointMarker from './LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n LinePointMarker,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const svgWidth = computed(() => {\r\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\r\n return width < 24 ? 24 : width\r\n })\r\n const svgHeight = computed(() => {\r\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\r\n return height < 24 ? 24 : height\r\n })\r\n\r\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10 6' : '0 0')\r\n\r\n const path = computed(() => {\r\n const start = props.elementInfo.start.join(',')\r\n const end = props.elementInfo.end.join(',')\r\n return `M${start} L${end}`\r\n })\r\n\r\n return {\r\n handleSelectElement,\r\n shadowStyle,\r\n svgWidth,\r\n svgHeight,\r\n lineDashArray,\r\n path,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-shape {\r\n position: absolute;\r\n\r\n &.lock .line-path {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n svg {\r\n transform-origin: 0 0;\r\n overflow: visible;\r\n }\r\n}\r\n.line-path {\r\n cursor: move;\r\n}\r\n</style>\r\n","<template>\r\n <marker \r\n :id=\"`${id}-${type}-${position}`\" \r\n markerUnits=\"userSpaceOnUse\" \r\n orient=\"auto\" \r\n :markerWidth=\"size * 3\" \r\n :markerHeight=\"size * 3\" \r\n :refX=\"size * 1.5\" \r\n :refY=\"size * 1.5\"\r\n >\r\n\t\t<path \r\n :d=\"path\" \r\n :fill=\"color\"\r\n :transform=\"`scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)`\"\r\n ></path>\r\n\t</marker>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\n\r\nconst pathMap = {\r\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\r\n arrow: 'M0,0 L10,5 0,10 Z',\r\n}\r\nconst rotateMap = {\r\n 'arrow-start': 180,\r\n 'arrow-end': 0,\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'line-point-marker',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n position: {\r\n type: String as PropType<'start' | 'end'>,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'dot' | 'arrow'>,\r\n required: true,\r\n },\r\n color: {\r\n type: String,\r\n },\r\n baseSize: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const path = computed(() => pathMap[props.type])\r\n const rotate = computed(() => rotateMap[`${props.type}-${props.position}`] || 0)\r\n const size = computed(() => props.baseSize < 2 ? 2 : props.baseSize)\r\n\r\n return {\r\n path,\r\n rotate,\r\n size,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\n\r\nconst pathMap = {\r\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\r\n arrow: 'M0,0 L10,5 0,10 Z',\r\n}\r\nconst rotateMap = {\r\n 'arrow-start': 180,\r\n 'arrow-end': 0,\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'line-point-marker',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n position: {\r\n type: String as PropType<'start' | 'end'>,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'dot' | 'arrow'>,\r\n required: true,\r\n },\r\n color: {\r\n type: String,\r\n },\r\n baseSize: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const path = computed(() => pathMap[props.type])\r\n const rotate = computed(() => rotateMap[`${props.type}-${props.position}`] || 0)\r\n const size = computed(() => props.baseSize < 2 ? 2 : props.baseSize)\r\n\r\n return {\r\n path,\r\n rotate,\r\n size,\r\n }\r\n },\r\n})\r\n","import { render } from \"./LinePointMarker.vue?vue&type=template&id=62085f5a\"\nimport script from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nimport LinePointMarker from './LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n LinePointMarker,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const svgWidth = computed(() => {\r\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\r\n return width < 24 ? 24 : width\r\n })\r\n const svgHeight = computed(() => {\r\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\r\n return height < 24 ? 24 : height\r\n })\r\n\r\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10 6' : '0 0')\r\n\r\n const path = computed(() => {\r\n const start = props.elementInfo.start.join(',')\r\n const end = props.elementInfo.end.join(',')\r\n return `M${start} L${end}`\r\n })\r\n\r\n return {\r\n handleSelectElement,\r\n shadowStyle,\r\n svgWidth,\r\n svgHeight,\r\n lineDashArray,\r\n path,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=58592d51&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=58592d51&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-58592d51\"\n\nexport default script","<template>\r\n <div class=\"editable-element-chart\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n }\"\r\n @mousedown=\"$event => handleSelectElement($event)\"\r\n >\r\n <div \r\n class=\"element-content\" \r\n :style=\"{\r\n backgroundColor: elementInfo.fill,\r\n }\"\r\n v-contextmenu=\"contextmenus\"\r\n >\r\n <ElementOutline\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <Chart\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :type=\"elementInfo.chartType\"\r\n :data=\"elementInfo.data\"\r\n :options=\"elementInfo.options\"\r\n :themeColor=\"elementInfo.themeColor\"\r\n :gridColor=\"elementInfo.gridColor\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTChartElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n return {\r\n handleSelectElement,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-chart {\r\n position: absolute;\r\n cursor: move;\r\n\r\n &.lock .element-content {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"chart\">\r\n <div \r\n class=\"chart-content\"\r\n ref=\"chartRef\"\r\n :style=\"{\r\n width: width + 'px',\r\n height: height + 'px',\r\n transform: `scale(${1 / slideScale})`,\r\n }\"\r\n ></div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, inject, onMounted, PropType, ref, Ref, watch } from 'vue'\r\nimport upperFirst from 'lodash/upperFirst'\r\nimport tinycolor from 'tinycolor2'\r\nimport Chartist, {\r\n IChartistLineChart,\r\n IChartistBarChart,\r\n IChartistPieChart,\r\n ILineChartOptions,\r\n IBarChartOptions,\r\n IPieChartOptions,\r\n} from 'chartist'\r\nimport { ChartData, ChartType } from '@/types/slides'\r\n\r\nimport 'chartist/dist/scss/chartist.scss'\r\n\r\nexport default defineComponent({\r\n name: 'chart',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<ChartType>,\r\n required: true,\r\n },\r\n data: {\r\n type: Object as PropType<ChartData>,\r\n required: true,\r\n },\r\n options: {\r\n type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>,\r\n },\r\n themeColor: {\r\n type: String,\r\n required: true,\r\n },\r\n gridColor: {\r\n type: String,\r\n },\r\n },\r\n setup(props) {\r\n const chartRef = ref<HTMLElement>()\r\n const slideScale: Ref<number> = inject('slideScale') || ref(1)\r\n\r\n let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined\r\n\r\n const getDataAndOptions = () => {\r\n const propsOptopns = props.options || {}\r\n const options = {\r\n ...propsOptopns,\r\n width: props.width * slideScale.value,\r\n height: props.height * slideScale.value,\r\n }\r\n const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data\r\n return { data, options }\r\n }\r\n\r\n const renderChart = () => {\r\n if (!chartRef.value) return\r\n\r\n const type = upperFirst(props.type)\r\n const { data, options } = getDataAndOptions()\r\n chart = new Chartist[type](chartRef.value, data, options)\r\n }\r\n\r\n const updateChart = () => {\r\n if (!chart) {\r\n renderChart()\r\n return\r\n }\r\n const { data, options } = getDataAndOptions()\r\n chart.update(data, options)\r\n }\r\n\r\n watch([\r\n () => props.width,\r\n () => props.height,\r\n () => props.data,\r\n slideScale,\r\n ], updateChart)\r\n\r\n onMounted(renderChart)\r\n\r\n // 更新主题配色:通过主题色的色相旋转,计算出一系列的颜色作为主题配色\r\n const updateTheme = () => {\r\n if (!chartRef.value) return\r\n\r\n const hsla = tinycolor(props.themeColor).toHsl()\r\n\r\n for (let i = 0; i < 10; i++) {\r\n let h = hsla.h + i * 36\r\n if (h > 360) h = h - 360\r\n\r\n const _hsla = {\r\n ...hsla,\r\n h,\r\n }\r\n chartRef.value.style.setProperty(`--theme-color-${i + 1}`, tinycolor(_hsla).toRgbString())\r\n }\r\n }\r\n\r\n watch(() => props.themeColor, updateTheme)\r\n onMounted(updateTheme)\r\n\r\n // 更新网格颜色,包括坐标的文字部分\r\n const updateGridColor = () => {\r\n if (!chartRef.value) return\r\n if (props.gridColor) chartRef.value.style.setProperty(`--grid-color`, props.gridColor)\r\n }\r\n\r\n watch(() => props.gridColor, updateGridColor)\r\n onMounted(updateGridColor)\r\n\r\n return {\r\n slideScale,\r\n chartRef,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.chart-content {\r\n transform-origin: 0 0;\r\n}\r\n</style>\r\n\r\n<style lang=\"scss\">\r\n.chart-content {\r\n $ct-series-names: (a, b, c, d, e, f, g, h, i, j);\r\n\r\n --theme-color-1: #666;\r\n --theme-color-2: #666;\r\n --theme-color-3: #666;\r\n --theme-color-4: #666;\r\n --theme-color-5: #666;\r\n --theme-color-6: #666;\r\n --theme-color-7: #666;\r\n --theme-color-8: #666;\r\n --theme-color-9: #666;\r\n --theme-color-10: #666;\r\n\r\n @for $i from 1 to length($ct-series-names) {\r\n $color: var(--theme-color-#{$i});\r\n\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-line {\r\n stroke: $color;\r\n }\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-point {\r\n stroke: $color;\r\n }\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-area {\r\n fill: $color;\r\n }\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-bar {\r\n stroke: $color;\r\n }\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-slice-pie {\r\n fill: $color;\r\n }\r\n .ct-series-#{nth($ct-series-names, $i)} .ct-slice-donut {\r\n stroke: $color;\r\n }\r\n }\r\n\r\n --grid-color: rgba(0, 0, 0, 0.4);\r\n\r\n .ct-grid {\r\n stroke: var(--grid-color);\r\n }\r\n .ct-label {\r\n fill: var(--grid-color);\r\n color: var(--grid-color);\r\n }\r\n}\r\n</style>","\r\nimport { defineComponent, inject, onMounted, PropType, ref, Ref, watch } from 'vue'\r\nimport upperFirst from 'lodash/upperFirst'\r\nimport tinycolor from 'tinycolor2'\r\nimport Chartist, {\r\n IChartistLineChart,\r\n IChartistBarChart,\r\n IChartistPieChart,\r\n ILineChartOptions,\r\n IBarChartOptions,\r\n IPieChartOptions,\r\n} from 'chartist'\r\nimport { ChartData, ChartType } from '@/types/slides'\r\n\r\nimport 'chartist/dist/scss/chartist.scss'\r\n\r\nexport default defineComponent({\r\n name: 'chart',\r\n props: {\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<ChartType>,\r\n required: true,\r\n },\r\n data: {\r\n type: Object as PropType<ChartData>,\r\n required: true,\r\n },\r\n options: {\r\n type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>,\r\n },\r\n themeColor: {\r\n type: String,\r\n required: true,\r\n },\r\n gridColor: {\r\n type: String,\r\n },\r\n },\r\n setup(props) {\r\n const chartRef = ref<HTMLElement>()\r\n const slideScale: Ref<number> = inject('slideScale') || ref(1)\r\n\r\n let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined\r\n\r\n const getDataAndOptions = () => {\r\n const propsOptopns = props.options || {}\r\n const options = {\r\n ...propsOptopns,\r\n width: props.width * slideScale.value,\r\n height: props.height * slideScale.value,\r\n }\r\n const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data\r\n return { data, options }\r\n }\r\n\r\n const renderChart = () => {\r\n if (!chartRef.value) return\r\n\r\n const type = upperFirst(props.type)\r\n const { data, options } = getDataAndOptions()\r\n chart = new Chartist[type](chartRef.value, data, options)\r\n }\r\n\r\n const updateChart = () => {\r\n if (!chart) {\r\n renderChart()\r\n return\r\n }\r\n const { data, options } = getDataAndOptions()\r\n chart.update(data, options)\r\n }\r\n\r\n watch([\r\n () => props.width,\r\n () => props.height,\r\n () => props.data,\r\n slideScale,\r\n ], updateChart)\r\n\r\n onMounted(renderChart)\r\n\r\n // 更新主题配色:通过主题色的色相旋转,计算出一系列的颜色作为主题配色\r\n const updateTheme = () => {\r\n if (!chartRef.value) return\r\n\r\n const hsla = tinycolor(props.themeColor).toHsl()\r\n\r\n for (let i = 0; i < 10; i++) {\r\n let h = hsla.h + i * 36\r\n if (h > 360) h = h - 360\r\n\r\n const _hsla = {\r\n ...hsla,\r\n h,\r\n }\r\n chartRef.value.style.setProperty(`--theme-color-${i + 1}`, tinycolor(_hsla).toRgbString())\r\n }\r\n }\r\n\r\n watch(() => props.themeColor, updateTheme)\r\n onMounted(updateTheme)\r\n\r\n // 更新网格颜色,包括坐标的文字部分\r\n const updateGridColor = () => {\r\n if (!chartRef.value) return\r\n if (props.gridColor) chartRef.value.style.setProperty(`--grid-color`, props.gridColor)\r\n }\r\n\r\n watch(() => props.gridColor, updateGridColor)\r\n onMounted(updateGridColor)\r\n\r\n return {\r\n slideScale,\r\n chartRef,\r\n }\r\n },\r\n})\r\n","import { render } from \"./Chart.vue?vue&type=template&id=561c26d2&scoped=true\"\nimport script from \"./Chart.vue?vue&type=script&lang=ts\"\nexport * from \"./Chart.vue?vue&type=script&lang=ts\"\n\nimport \"./Chart.vue?vue&type=style&index=0&id=561c26d2&lang=scss&scoped=true\"\nimport \"./Chart.vue?vue&type=style&index=1&id=561c26d2&lang=scss\"\nscript.render = render\nscript.__scopeId = \"data-v-561c26d2\"\n\nexport default script","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTChartElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n return {\r\n handleSelectElement,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=2fd38bde&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=2fd38bde&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2fd38bde\"\n\nexport default script","<template>\r\n <div \r\n class=\"editable-element-table\"\r\n ref=\"elementRef\"\r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\" \r\n v-contextmenu=\"contextmenus\"\r\n >\r\n <EditableTable \r\n @mousedown.stop\r\n :data=\"elementInfo.data\"\r\n :width=\"elementInfo.width\"\r\n :colWidths=\"elementInfo.colWidths\"\r\n :outline=\"elementInfo.outline\"\r\n :theme=\"elementInfo.theme\"\r\n :editable=\"editable\"\r\n @change=\"data => updateTableCells(data)\"\r\n @changeColWidths=\"widths => updateColWidths(widths)\"\r\n @changeSelectedCells=\"cells => updateSelectedCells(cells)\"\r\n />\r\n <div \r\n class=\"table-mask\" \r\n :class=\"{ 'lock': elementInfo.lock }\"\r\n v-if=\"!editable || elementInfo.lock\"\r\n @dblclick=\"startEdit()\"\r\n @mousedown=\"$event => handleSelectElement($event)\"\r\n >\r\n <div class=\"mask-tip\" :style=\"{ transform: `scale(${ 1 / canvasScale })` }\">双击编辑</div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTableElement, TableCell } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport EditableTable from './EditableTable.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-table',\r\n components: {\r\n EditableTable,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n \r\n const elementRef = ref<HTMLElement>()\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n // 更新表格的可编辑状态,表格处于编辑状态时需要禁用全局快捷键\r\n const editable = ref(false)\r\n\r\n watch(handleElementId, () => {\r\n if (handleElementId.value !== props.elementInfo.id) editable.value = false\r\n })\r\n\r\n watch(editable, () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, editable.value)\r\n })\r\n\r\n const startEdit = () => {\r\n if (!props.elementInfo.lock) editable.value = true\r\n }\r\n\r\n // 监听表格元素的尺寸变化,当高度变化时,更新高度到vuex\r\n // 如果高度变化时正处在缩放操作中,则等待缩放操作结束后再更新\r\n const isScaling = ref(false)\r\n const realHeightCache = ref(-1)\r\n\r\n const scaleElementStateListener = (state: boolean) => {\r\n isScaling.value = state\r\n\r\n if (state) editable.value = false\r\n\r\n if (!state && realHeightCache.value !== -1) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeightCache.value },\r\n })\r\n realHeightCache.value = -1\r\n }\r\n }\r\n\r\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n })\r\n\r\n const updateTableElementHeight = (entries: ResizeObserverEntry[]) => {\r\n const contentRect = entries[0].contentRect\r\n if (!elementRef.value) return\r\n\r\n const realHeight = contentRect.height\r\n\r\n if (props.elementInfo.height !== realHeight) {\r\n if (!isScaling.value) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeight },\r\n })\r\n }\r\n else realHeightCache.value = realHeight\r\n }\r\n }\r\n\r\n const resizeObserver = new ResizeObserver(updateTableElementHeight)\r\n\r\n onMounted(() => {\r\n if (elementRef.value) resizeObserver.observe(elementRef.value)\r\n })\r\n onUnmounted(() => {\r\n if (elementRef.value) resizeObserver.unobserve(elementRef.value)\r\n })\r\n\r\n // 更新表格内容数据\r\n const updateTableCells = (data: TableCell[][]) => {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { data },\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 更新表格的列宽数据\r\n const updateColWidths = (widths: number[]) => {\r\n const width = widths.reduce((a, b) => a + b)\r\n const colWidths = widths.map(item => item / width)\r\n\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { width, colWidths },\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 更新表格当前选中的单元格\r\n const updateSelectedCells = (cells: string[]) => {\r\n nextTick(() => emitter.emit(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells))\r\n }\r\n\r\n return {\r\n elementRef,\r\n canvasScale,\r\n handleSelectElement,\r\n updateTableCells,\r\n updateColWidths,\r\n editable,\r\n startEdit,\r\n updateSelectedCells,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-table {\r\n position: absolute;\r\n cursor: move;\r\n\r\n &.lock .element-content {\r\n cursor: default;\r\n }\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n}\r\n.table-mask {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n opacity: 0;\r\n transition: opacity .2s;\r\n\r\n .mask-tip {\r\n position: absolute;\r\n top: 5px;\r\n left: 5px;\r\n background-color: rgba($color: #000, $alpha: .5);\r\n color: #fff;\r\n padding: 6px 12px;\r\n font-size: 12px;\r\n transform-origin: 0 0;\r\n }\r\n\r\n &:hover:not(.lock) {\r\n opacity: .9;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div \r\n class=\"editable-table\"\r\n :style=\"{ width: totalWidth + 'px' }\"\r\n >\r\n <div class=\"handler\" v-if=\"editable\">\r\n <div \r\n class=\"drag-line\" \r\n v-for=\"(pos, index) in dragLinePosition\" \r\n :key=\"index\"\r\n :style=\"{\r\n left: pos + 'px',\r\n }\"\r\n @mousedown=\"$event => handleMousedownColHandler($event, index)\"\r\n ></div>\r\n </div>\r\n <table \r\n :class=\"{\r\n 'theme': theme,\r\n 'row-header': theme?.rowHeader,\r\n 'row-footer': theme?.rowFooter,\r\n 'col-header': theme?.colHeader,\r\n 'col-footer': theme?.colFooter,\r\n }\"\r\n :style=\"`--themeColor: ${theme?.color}; --subThemeColor1: ${subThemeColor[0]}; --subThemeColor2: ${subThemeColor[1]}`\"\r\n >\r\n <colgroup>\r\n <col span=\"1\" v-for=\"(width, index) in colSizeList\" :key=\"index\" :width=\"width\">\r\n </colgroup>\r\n <tbody>\r\n <tr\r\n v-for=\"(rowCells, rowIndex) in tableCells\" \r\n :key=\"rowIndex\"\r\n >\r\n <td \r\n class=\"cell\"\r\n :class=\"{\r\n 'selected': selectedCells.includes(`${rowIndex}_${colIndex}`) && selectedCells.length > 1,\r\n 'active': activedCell === `${rowIndex}_${colIndex}`,\r\n }\"\r\n :style=\"{\r\n borderStyle: outline.style,\r\n borderColor: outline.color,\r\n borderWidth: outline.width + 'px',\r\n ...getTextStyle(cell.style),\r\n }\"\r\n v-for=\"(cell, colIndex) in rowCells\"\r\n :key=\"cell.id\"\r\n :rowspan=\"cell.rowspan\"\r\n :colspan=\"cell.colspan\"\r\n :data-cell-index=\"`${rowIndex}_${colIndex}`\"\r\n v-show=\"!hideCells.includes(`${rowIndex}_${colIndex}`)\"\r\n @mousedown=\"$event => handleCellMousedown($event, rowIndex, colIndex)\"\r\n @mouseenter=\"handleCellMouseenter(rowIndex, colIndex)\"\r\n v-contextmenu=\"el => contextmenus(el)\"\r\n >\r\n <CustomTextarea \r\n class=\"cell-text\" \r\n :class=\"{ 'active': activedCell === `${rowIndex}_${colIndex}` }\"\r\n :contenteditable=\"activedCell === `${rowIndex}_${colIndex}` ? 'plaintext-only' : false\"\r\n v-model=\"cell.text\"\r\n @update:modelValue=\"handleInput()\"\r\n />\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport debounce from 'lodash/debounce'\r\nimport { useStore } from '@/store'\r\nimport { PPTElementOutline, TableCell, TableTheme } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { getTextStyle } from './utils'\r\nimport useHideCells from './useHideCells'\r\nimport useSubThemeColor from './useSubThemeColor'\r\n\r\nimport CustomTextarea from './CustomTextarea.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-table',\r\n components: {\r\n CustomTextarea,\r\n },\r\n props: {\r\n data: {\r\n type: Array as PropType<TableCell[][]>,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n colWidths: {\r\n type: Array as PropType<number[]>,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>,\r\n required: true,\r\n },\r\n theme: {\r\n type: Object as PropType<TableTheme>,\r\n },\r\n editable: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n \r\n const isStartSelect = ref(false)\r\n const startCell = ref<number[]>([])\r\n const endCell = ref<number[]>([])\r\n\r\n const tableCells = computed<TableCell[][]>({\r\n get() {\r\n return props.data\r\n },\r\n set(newData) {\r\n emit('change', newData)\r\n },\r\n })\r\n\r\n // 主题辅助色\r\n const theme = computed(() => props.theme)\r\n const { subThemeColor } = useSubThemeColor(theme)\r\n\r\n // 计算表格每一列的列宽和总宽度\r\n const colSizeList = ref<number[]>([])\r\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\r\n watch([\r\n () => props.colWidths,\r\n () => props.width,\r\n ], () => {\r\n colSizeList.value = props.colWidths.map(item => item * props.width)\r\n }, { immediate: true })\r\n \r\n // 清除全部单元格的选中状态\r\n // 表格处于不可编辑状态时也需要清除\r\n const removeSelectedCells = () => {\r\n startCell.value = []\r\n endCell.value = []\r\n }\r\n\r\n watch(() => props.editable, () => {\r\n if (!props.editable) removeSelectedCells()\r\n })\r\n\r\n // 用于拖拽列宽的操作节点位置\r\n const dragLinePosition = computed(() => {\r\n const dragLinePosition: number[] = []\r\n for (let i = 1; i < colSizeList.value.length + 1; i++) {\r\n const pos = colSizeList.value.slice(0, i).reduce((a, b) => (a + b))\r\n dragLinePosition.push(pos)\r\n }\r\n return dragLinePosition\r\n })\r\n\r\n // 无效的单元格位置(被合并的单元格位置)集合\r\n const cells = computed(() => props.data)\r\n const { hideCells } = useHideCells(cells)\r\n\r\n // 当前选中的单元格集合\r\n const selectedCells = computed(() => {\r\n if (!startCell.value.length) return []\r\n const [startX, startY] = startCell.value\r\n\r\n if (!endCell.value.length) return [`${startX}_${startY}`]\r\n const [endX, endY] = endCell.value\r\n\r\n if (startX === endX && startY === endY) return [`${startX}_${startY}`]\r\n\r\n const selectedCells = []\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n const rowCells = tableCells.value[i]\r\n for (let j = 0; j < rowCells.length; j++) {\r\n if (i >= minX && i <= maxX && j >= minY && j <= maxY) selectedCells.push(`${i}_${j}`)\r\n }\r\n }\r\n return selectedCells\r\n })\r\n\r\n watch(selectedCells, () => {\r\n emit('changeSelectedCells', selectedCells.value)\r\n })\r\n\r\n // 当前激活的单元格:当且仅当只有一个选中单元格时,该单元格为激活的单元格\r\n const activedCell = computed(() => {\r\n if (selectedCells.value.length > 1) return null\r\n return selectedCells.value[0]\r\n })\r\n\r\n // 当前选中的单元格位置范围\r\n const selectedRange = computed(() => {\r\n if (!startCell.value.length) return null\r\n const [startX, startY] = startCell.value\r\n\r\n if (!endCell.value.length) return { row: [startX, startX], col: [startY, startY] }\r\n const [endX, endY] = endCell.value\r\n\r\n if (startX === endX && startY === endY) return { row: [startX, startX], col: [startY, startY] }\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n return {\r\n row: [minX, maxX],\r\n col: [minY, maxY],\r\n }\r\n })\r\n\r\n // 设置选中单元格状态(鼠标点击或拖选)\r\n const handleMouseup = () => isStartSelect.value = false\r\n\r\n const handleCellMousedown = (e: MouseEvent, rowIndex: number, colIndex: number) => {\r\n if (e.button === 0) {\r\n endCell.value = []\r\n isStartSelect.value = true\r\n startCell.value = [rowIndex, colIndex]\r\n }\r\n }\r\n\r\n const handleCellMouseenter = (rowIndex: number, colIndex: number) => {\r\n if (!isStartSelect.value) return\r\n endCell.value = [rowIndex, colIndex]\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('mouseup', handleMouseup)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('mouseup', handleMouseup)\r\n })\r\n\r\n // 判断某位置是否为无效单元格(被合并掉的位置)\r\n const isHideCell = (rowIndex: number, colIndex: number) => hideCells.value.includes(`${rowIndex}_${colIndex}`)\r\n\r\n // 选中指定的列\r\n const selectCol = (index: number) => {\r\n const maxRow = tableCells.value.length - 1\r\n startCell.value = [0, index]\r\n endCell.value = [maxRow, index]\r\n }\r\n\r\n // 选中指定的行\r\n const selectRow = (index: number) => {\r\n const maxCol = tableCells.value[index].length - 1\r\n startCell.value = [index, 0]\r\n endCell.value = [index, maxCol]\r\n }\r\n\r\n // 选中全部单元格\r\n const selectAll = () => {\r\n const maxRow = tableCells.value.length - 1\r\n const maxCol = tableCells.value[maxRow].length - 1\r\n startCell.value = [0, 0]\r\n endCell.value = [maxRow, maxCol]\r\n }\r\n\r\n // 删除一行\r\n const deleteRow = (rowIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const targetCells = tableCells.value[rowIndex]\r\n const hideCellsPos = []\r\n for (let i = 0; i < targetCells.length; i++) {\r\n if (isHideCell(rowIndex, i)) hideCellsPos.push(i)\r\n }\r\n \r\n for (const pos of hideCellsPos) {\r\n for (let i = rowIndex; i >= 0; i--) {\r\n if (!isHideCell(i, pos)) {\r\n _tableCells[i][pos].rowspan = _tableCells[i][pos].rowspan - 1\r\n break\r\n }\r\n }\r\n }\r\n\r\n _tableCells.splice(rowIndex, 1)\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 删除一列\r\n const deleteCol = (colIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const hideCellsPos = []\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n if (isHideCell(i, colIndex)) hideCellsPos.push(i)\r\n }\r\n\r\n for (const pos of hideCellsPos) {\r\n for (let i = colIndex; i >= 0; i--) {\r\n if (!isHideCell(pos, i)) {\r\n _tableCells[pos][i].colspan = _tableCells[pos][i].colspan - 1\r\n break\r\n }\r\n }\r\n }\r\n\r\n tableCells.value = _tableCells.map(item => {\r\n item.splice(colIndex, 1)\r\n return item\r\n })\r\n colSizeList.value.splice(colIndex, 1)\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n \r\n // 插入一行\r\n const insertRow = (rowIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const rowCells: TableCell[] = []\r\n for (let i = 0; i < _tableCells[0].length; i++) {\r\n rowCells.push({\r\n colspan: 1,\r\n rowspan: 1,\r\n text: '',\r\n id: createRandomCode(),\r\n })\r\n }\r\n\r\n _tableCells.splice(rowIndex, 0, rowCells)\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 插入一列\r\n const insertCol = (colIndex: number) => {\r\n tableCells.value = tableCells.value.map(item => {\r\n const cell = {\r\n colspan: 1,\r\n rowspan: 1,\r\n text: '',\r\n id: createRandomCode(),\r\n }\r\n item.splice(colIndex, 0, cell)\r\n return item\r\n })\r\n colSizeList.value.splice(colIndex, 0, 100)\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n \r\n // 合并单元格\r\n const mergeCells = () => {\r\n const [startX, startY] = startCell.value\r\n const [endX, endY] = endCell.value\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n \r\n _tableCells[minX][minY].rowspan = maxX - minX + 1\r\n _tableCells[minX][minY].colspan = maxY - minY + 1\r\n\r\n tableCells.value = _tableCells\r\n removeSelectedCells()\r\n }\r\n\r\n // 拆分单元格\r\n const splitCells = (rowIndex: number, colIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n _tableCells[rowIndex][colIndex].rowspan = 1\r\n _tableCells[rowIndex][colIndex].colspan = 1\r\n\r\n tableCells.value = _tableCells\r\n removeSelectedCells()\r\n }\r\n\r\n // 鼠标拖拽调整列宽\r\n const handleMousedownColHandler = (e: MouseEvent, colIndex: number) => {\r\n removeSelectedCells()\r\n let isMouseDown = true\r\n\r\n const originWidth = colSizeList.value[colIndex]\r\n const startPageX = e.pageX\r\n\r\n const minWidth = 50\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n \r\n const moveX = (e.pageX - startPageX) / canvasScale.value\r\n const width = originWidth + moveX < minWidth ? minWidth : Math.round(originWidth + moveX)\r\n\r\n colSizeList.value[colIndex] = width\r\n }\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n }\r\n\r\n // 清空选中单元格内的文字\r\n const clearSelectedCellText = () => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n for (let i = 0; i < _tableCells.length; i++) {\r\n for (let j = 0; j < _tableCells[i].length; j++) {\r\n if (selectedCells.value.includes(`${i}_${j}`)) {\r\n _tableCells[i][j].text = ''\r\n }\r\n }\r\n }\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 将焦点移动到下一个单元格\r\n // 当前行右边有单元格时,焦点右移\r\n // 当前行右边无单元格(已处在行末),且存在下一行时,焦点移动下下一行行首\r\n // 当前行右边无单元格(已处在行末),且不存在下一行(已处在最后一行)时,新建一行并将焦点移动下下一行行首\r\n const tabActiveCell = () => {\r\n const getNextCell = (i: number, j: number): [number, number] | null => {\r\n if (!tableCells.value[i]) return null\r\n if (!tableCells.value[i][j]) return getNextCell(i + 1, 0)\r\n if (isHideCell(i, j)) return getNextCell(i, j + 1)\r\n return [i, j]\r\n }\r\n\r\n endCell.value = []\r\n\r\n const nextRow = startCell.value[0]\r\n const nextCol = startCell.value[1] + 1\r\n\r\n const nextCell = getNextCell(nextRow, nextCol)\r\n if (!nextCell) {\r\n insertRow(nextRow + 1)\r\n startCell.value = [nextRow + 1, 0]\r\n }\r\n else startCell.value = nextCell\r\n\r\n // 移动焦点后自动聚焦文本\r\n nextTick(() => {\r\n const textRef = document.querySelector('.cell-text.active') as HTMLInputElement\r\n if (textRef) textRef.focus()\r\n })\r\n }\r\n\r\n // 表格快捷键监听\r\n const keydownListener = (e: KeyboardEvent) => {\r\n if (!props.editable || !selectedCells.value.length) return\r\n\r\n const key = e.key.toUpperCase()\r\n if (selectedCells.value.length < 2) {\r\n if (key === KEYS.TAB) {\r\n e.preventDefault()\r\n tabActiveCell()\r\n }\r\n if (e.ctrlKey && key === KEYS.UP) {\r\n e.preventDefault()\r\n const rowIndex = +selectedCells.value[0].split('_')[0]\r\n insertRow(rowIndex)\r\n }\r\n if (e.ctrlKey && key === KEYS.DOWN) {\r\n e.preventDefault()\r\n const rowIndex = +selectedCells.value[0].split('_')[0]\r\n insertRow(rowIndex + 1)\r\n }\r\n if (e.ctrlKey && key === KEYS.LEFT) {\r\n e.preventDefault()\r\n const colIndex = +selectedCells.value[0].split('_')[1]\r\n insertCol(colIndex)\r\n }\r\n if (e.ctrlKey && key === KEYS.RIGHT) {\r\n e.preventDefault()\r\n const colIndex = +selectedCells.value[0].split('_')[1]\r\n insertCol(colIndex + 1)\r\n }\r\n }\r\n else if (key === KEYS.DELETE) {\r\n clearSelectedCellText()\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('keydown', keydownListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keydownListener)\r\n })\r\n\r\n // 单元格文字输入时更新表格数据\r\n const handleInput = debounce(function() {\r\n emit('change', tableCells.value)\r\n }, 300, { trailing: true })\r\n\r\n // 获取有效的单元格(排除掉被合并的单元格)\r\n const getEffectiveTableCells = () => {\r\n const effectiveTableCells = []\r\n\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n const rowCells = tableCells.value[i]\r\n const _rowCells = []\r\n for (let j = 0; j < rowCells.length; j++) {\r\n if (!isHideCell(i, j)) _rowCells.push(rowCells[j])\r\n }\r\n if (_rowCells.length) effectiveTableCells.push(_rowCells)\r\n }\r\n\r\n return effectiveTableCells\r\n }\r\n\r\n // 检查是否可以删除行和列:有效的行/列数大于1\r\n const checkCanDeleteRowOrCol = () => {\r\n const effectiveTableCells = getEffectiveTableCells()\r\n const canDeleteRow = effectiveTableCells.length > 1\r\n const canDeleteCol = effectiveTableCells[0].length > 1\r\n\r\n return { canDeleteRow, canDeleteCol }\r\n }\r\n\r\n // 检查是否可以合并或拆分\r\n // 必须多选才可以合并\r\n // 必须单选且所选单元格为合并单元格才可以拆分\r\n const checkCanMergeOrSplit = (rowIndex: number, colIndex: number) => {\r\n const isMultiSelected = selectedCells.value.length > 1\r\n const targetCell = tableCells.value[rowIndex][colIndex]\r\n\r\n const canMerge = isMultiSelected\r\n const canSplit = !isMultiSelected && (targetCell.rowspan > 1 || targetCell.colspan > 1)\r\n\r\n return { canMerge, canSplit }\r\n }\r\n\r\n const contextmenus = (el: HTMLElement): ContextmenuItem[] => {\r\n const cellIndex = el.dataset.cellIndex as string\r\n const rowIndex = +cellIndex.split('_')[0]\r\n const colIndex = +cellIndex.split('_')[1]\r\n\r\n if (!selectedCells.value.includes(`${rowIndex}_${colIndex}`)) {\r\n startCell.value = [rowIndex, colIndex]\r\n endCell.value = []\r\n }\r\n\r\n const { canMerge, canSplit } = checkCanMergeOrSplit(rowIndex, colIndex)\r\n const { canDeleteRow, canDeleteCol } = checkCanDeleteRowOrCol()\r\n\r\n return [\r\n {\r\n text: '插入列',\r\n children: [\r\n { text: '到左侧', handler: () => insertCol(colIndex) },\r\n { text: '到右侧', handler: () => insertCol(colIndex + 1) },\r\n ],\r\n },\r\n {\r\n text: '插入行',\r\n children: [\r\n { text: '到上方', handler: () => insertRow(rowIndex) },\r\n { text: '到下方', handler: () => insertRow(rowIndex + 1) },\r\n ],\r\n },\r\n {\r\n text: '删除列',\r\n disable: !canDeleteCol,\r\n handler: () => deleteCol(colIndex),\r\n },\r\n {\r\n text: '删除行',\r\n disable: !canDeleteRow,\r\n handler: () => deleteRow(rowIndex),\r\n },\r\n { divider: true },\r\n {\r\n text: '合并单元格',\r\n disable: !canMerge,\r\n handler: mergeCells,\r\n },\r\n {\r\n text: '取消合并单元格',\r\n disable: !canSplit,\r\n handler: () => splitCells(rowIndex, colIndex),\r\n },\r\n { divider: true },\r\n {\r\n text: '选中当前列',\r\n handler: () => selectCol(colIndex),\r\n },\r\n {\r\n text: '选中当前行',\r\n handler: () => selectRow(rowIndex),\r\n },\r\n {\r\n text: '选中全部单元格',\r\n handler: selectAll,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n getTextStyle,\r\n dragLinePosition,\r\n tableCells,\r\n colSizeList,\r\n totalWidth,\r\n hideCells,\r\n selectedCells,\r\n activedCell,\r\n selectedRange,\r\n handleCellMousedown,\r\n handleCellMouseenter,\r\n selectCol,\r\n selectRow,\r\n handleMousedownColHandler,\r\n contextmenus,\r\n handleInput,\r\n subThemeColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-table {\r\n position: relative;\r\n user-select: none;\r\n}\r\ntable {\r\n width: 100%;\r\n position: relative;\r\n table-layout: fixed;\r\n border-collapse: collapse;\r\n border-spacing: 0;\r\n border: 0;\r\n word-wrap: break-word;\r\n user-select: none;\r\n\r\n --themeColor: $themeColor;\r\n --subThemeColor1: $themeColor;\r\n --subThemeColor2: $themeColor;\r\n\r\n &.theme {\r\n tr:nth-child(2n) .cell {\r\n background-color: var(--subThemeColor1);\r\n }\r\n tr:nth-child(2n + 1) .cell {\r\n background-color: var(--subThemeColor2);\r\n }\r\n\r\n &.row-header {\r\n tr:first-child .cell {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.row-footer {\r\n tr:last-child .cell {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.col-header {\r\n tr .cell:first-child {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.col-footer {\r\n tr .cell:last-child {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n }\r\n\r\n tr {\r\n height: 36px;\r\n }\r\n\r\n .cell {\r\n position: relative;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n vertical-align: middle;\r\n font-size: 14px;\r\n cursor: default;\r\n\r\n &.selected::after {\r\n content: '';\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n background-color: rgba($color: #666, $alpha: .4);\r\n }\r\n }\r\n\r\n .cell-text {\r\n min-height: 32px;\r\n padding: 5px;\r\n border: 0;\r\n outline: 0;\r\n line-height: 1.5;\r\n user-select: none;\r\n cursor: text;\r\n\r\n &.active {\r\n user-select: text;\r\n }\r\n }\r\n}\r\n\r\n.drag-line {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n width: 3px;\r\n background-color: $themeColor;\r\n margin-left: -1px;\r\n opacity: 0;\r\n z-index: 2;\r\n cursor: col-resize;\r\n\r\n &:hover {\r\n opacity: 1;\r\n }\r\n}\r\n</style>","import { TableCellStyle } from '@/types/slides'\r\n\r\n/**\r\n * 计算单元格文本样式\r\n * @param style 单元格文本样式原数据\r\n */\r\nexport const getTextStyle = (style?: TableCellStyle) => {\r\n if (!style) return {}\r\n const {\r\n bold,\r\n em,\r\n underline,\r\n strikethrough,\r\n color,\r\n backcolor,\r\n fontsize,\r\n fontname,\r\n align,\r\n } = style\r\n \r\n return {\r\n fontWeight: bold ? 'bold' : 'normal',\r\n fontStyle: em ? 'italic' : 'normal',\r\n textDecoration: `${underline ? 'underline' : ''} ${strikethrough ? 'line-through' : ''}`,\r\n color: color || '#000',\r\n backgroundColor: backcolor || '',\r\n fontSize: fontsize || '14px',\r\n fontFamily: fontname || '微软雅黑',\r\n textAlign: align || 'left',\r\n }\r\n}","import { computed, Ref } from 'vue'\r\nimport { TableCell } from '@/types/slides'\r\n\r\n// 计算无效的单元格位置(被合并的单元格位置)集合\r\n\r\nexport default (cells: Ref<TableCell[][]>) => {\r\n const hideCells = computed(() => {\r\n const hideCells = []\r\n \r\n for (let i = 0; i < cells.value.length; i++) {\r\n const rowCells = cells.value[i]\r\n\r\n for (let j = 0; j < rowCells.length; j++) {\r\n const cell = rowCells[j]\r\n \r\n if (cell.colspan > 1 || cell.rowspan > 1) {\r\n for (let row = i; row < i + cell.rowspan; row++) {\r\n for (let col = row === i ? j + 1 : j; col < j + cell.colspan; col++) {\r\n hideCells.push(`${row}_${col}`)\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return hideCells\r\n })\r\n\r\n return {\r\n hideCells,\r\n }\r\n}","import { ref, Ref, watch } from 'vue'\r\nimport tinycolor from 'tinycolor2'\r\nimport { TableTheme } from '@/types/slides'\r\n\r\n// 通过表格的主题色计算辅助颜色\r\n\r\nexport default (theme: Ref<TableTheme | undefined>) => {\r\n const subThemeColor = ref(['', ''])\r\n watch(() => theme.value, () => {\r\n if (theme.value) {\r\n const rgba = tinycolor(theme.value.color).toRgb()\r\n const subRgba1 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.3 }\r\n const subRgba2 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.1 }\r\n subThemeColor.value = [\r\n `rgba(${[subRgba1.r, subRgba1.g, subRgba1.b, subRgba1.a].join(',')})`,\r\n `rgba(${[subRgba2.r, subRgba2.g, subRgba2.b, subRgba2.a].join(',')})`,\r\n ]\r\n }\r\n }, { immediate: true })\r\n\r\n return {\r\n subThemeColor,\r\n }\r\n}","<template>\r\n <div \r\n class=\"custom-textarea\"\r\n ref=\"textareaRef\"\r\n :contenteditable=\"contenteditable\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n @input=\"$event => handleInput($event)\"\r\n v-html=\"text\"\r\n ></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, onUnmounted, ref, watch } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'custom-textarea',\r\n props: {\r\n modelValue: {\r\n type: String,\r\n default: '',\r\n },\r\n contenteditable: {\r\n type: [Boolean, String],\r\n default: false,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const textareaRef = ref<HTMLElement>()\r\n const text = ref('')\r\n const isFocus = ref(false)\r\n\r\n // 自定义v-modal,同步数据\r\n // 当文本框聚焦时,不执行数据同步\r\n watch(() => props.modelValue, () => {\r\n if (isFocus.value) return\r\n text.value = props.modelValue\r\n if (textareaRef.value) textareaRef.value.innerHTML = props.modelValue\r\n }, { immediate: true })\r\n\r\n const handleInput = () => {\r\n if (!textareaRef.value) return\r\n const text = textareaRef.value.innerHTML\r\n emit('update:modelValue', text)\r\n }\r\n\r\n // 聚焦时更新焦点标记,并监听粘贴事件\r\n const handleFocus = () => {\r\n isFocus.value = true\r\n\r\n if (!textareaRef.value) return\r\n textareaRef.value.onpaste = (e: ClipboardEvent) => {\r\n e.preventDefault()\r\n if (!e.clipboardData) return\r\n\r\n const clipboardDataFirstItem = e.clipboardData.items[0]\r\n\r\n if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\r\n clipboardDataFirstItem.getAsString(text => emit('update:modelValue', text))\r\n }\r\n }\r\n }\r\n\r\n // 失焦时更新焦点标记,清除粘贴事件监听\r\n const handleBlur = () => {\r\n isFocus.value = false\r\n if (textareaRef.value) textareaRef.value.onpaste = null\r\n }\r\n\r\n // 清除粘贴事件监听\r\n onUnmounted(() => {\r\n if (textareaRef.value) textareaRef.value.onpaste = null\r\n })\r\n\r\n return {\r\n textareaRef,\r\n handleFocus,\r\n handleInput,\r\n handleBlur,\r\n text,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { defineComponent, onUnmounted, ref, watch } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'custom-textarea',\r\n props: {\r\n modelValue: {\r\n type: String,\r\n default: '',\r\n },\r\n contenteditable: {\r\n type: [Boolean, String],\r\n default: false,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const textareaRef = ref<HTMLElement>()\r\n const text = ref('')\r\n const isFocus = ref(false)\r\n\r\n // 自定义v-modal,同步数据\r\n // 当文本框聚焦时,不执行数据同步\r\n watch(() => props.modelValue, () => {\r\n if (isFocus.value) return\r\n text.value = props.modelValue\r\n if (textareaRef.value) textareaRef.value.innerHTML = props.modelValue\r\n }, { immediate: true })\r\n\r\n const handleInput = () => {\r\n if (!textareaRef.value) return\r\n const text = textareaRef.value.innerHTML\r\n emit('update:modelValue', text)\r\n }\r\n\r\n // 聚焦时更新焦点标记,并监听粘贴事件\r\n const handleFocus = () => {\r\n isFocus.value = true\r\n\r\n if (!textareaRef.value) return\r\n textareaRef.value.onpaste = (e: ClipboardEvent) => {\r\n e.preventDefault()\r\n if (!e.clipboardData) return\r\n\r\n const clipboardDataFirstItem = e.clipboardData.items[0]\r\n\r\n if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\r\n clipboardDataFirstItem.getAsString(text => emit('update:modelValue', text))\r\n }\r\n }\r\n }\r\n\r\n // 失焦时更新焦点标记,清除粘贴事件监听\r\n const handleBlur = () => {\r\n isFocus.value = false\r\n if (textareaRef.value) textareaRef.value.onpaste = null\r\n }\r\n\r\n // 清除粘贴事件监听\r\n onUnmounted(() => {\r\n if (textareaRef.value) textareaRef.value.onpaste = null\r\n })\r\n\r\n return {\r\n textareaRef,\r\n handleFocus,\r\n handleInput,\r\n handleBlur,\r\n text,\r\n }\r\n },\r\n})\r\n","import { render } from \"./CustomTextarea.vue?vue&type=template&id=3b83d85b\"\nimport script from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nexport * from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport debounce from 'lodash/debounce'\r\nimport { useStore } from '@/store'\r\nimport { PPTElementOutline, TableCell, TableTheme } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { getTextStyle } from './utils'\r\nimport useHideCells from './useHideCells'\r\nimport useSubThemeColor from './useSubThemeColor'\r\n\r\nimport CustomTextarea from './CustomTextarea.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-table',\r\n components: {\r\n CustomTextarea,\r\n },\r\n props: {\r\n data: {\r\n type: Array as PropType<TableCell[][]>,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n colWidths: {\r\n type: Array as PropType<number[]>,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>,\r\n required: true,\r\n },\r\n theme: {\r\n type: Object as PropType<TableTheme>,\r\n },\r\n editable: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n \r\n const isStartSelect = ref(false)\r\n const startCell = ref<number[]>([])\r\n const endCell = ref<number[]>([])\r\n\r\n const tableCells = computed<TableCell[][]>({\r\n get() {\r\n return props.data\r\n },\r\n set(newData) {\r\n emit('change', newData)\r\n },\r\n })\r\n\r\n // 主题辅助色\r\n const theme = computed(() => props.theme)\r\n const { subThemeColor } = useSubThemeColor(theme)\r\n\r\n // 计算表格每一列的列宽和总宽度\r\n const colSizeList = ref<number[]>([])\r\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\r\n watch([\r\n () => props.colWidths,\r\n () => props.width,\r\n ], () => {\r\n colSizeList.value = props.colWidths.map(item => item * props.width)\r\n }, { immediate: true })\r\n \r\n // 清除全部单元格的选中状态\r\n // 表格处于不可编辑状态时也需要清除\r\n const removeSelectedCells = () => {\r\n startCell.value = []\r\n endCell.value = []\r\n }\r\n\r\n watch(() => props.editable, () => {\r\n if (!props.editable) removeSelectedCells()\r\n })\r\n\r\n // 用于拖拽列宽的操作节点位置\r\n const dragLinePosition = computed(() => {\r\n const dragLinePosition: number[] = []\r\n for (let i = 1; i < colSizeList.value.length + 1; i++) {\r\n const pos = colSizeList.value.slice(0, i).reduce((a, b) => (a + b))\r\n dragLinePosition.push(pos)\r\n }\r\n return dragLinePosition\r\n })\r\n\r\n // 无效的单元格位置(被合并的单元格位置)集合\r\n const cells = computed(() => props.data)\r\n const { hideCells } = useHideCells(cells)\r\n\r\n // 当前选中的单元格集合\r\n const selectedCells = computed(() => {\r\n if (!startCell.value.length) return []\r\n const [startX, startY] = startCell.value\r\n\r\n if (!endCell.value.length) return [`${startX}_${startY}`]\r\n const [endX, endY] = endCell.value\r\n\r\n if (startX === endX && startY === endY) return [`${startX}_${startY}`]\r\n\r\n const selectedCells = []\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n const rowCells = tableCells.value[i]\r\n for (let j = 0; j < rowCells.length; j++) {\r\n if (i >= minX && i <= maxX && j >= minY && j <= maxY) selectedCells.push(`${i}_${j}`)\r\n }\r\n }\r\n return selectedCells\r\n })\r\n\r\n watch(selectedCells, () => {\r\n emit('changeSelectedCells', selectedCells.value)\r\n })\r\n\r\n // 当前激活的单元格:当且仅当只有一个选中单元格时,该单元格为激活的单元格\r\n const activedCell = computed(() => {\r\n if (selectedCells.value.length > 1) return null\r\n return selectedCells.value[0]\r\n })\r\n\r\n // 当前选中的单元格位置范围\r\n const selectedRange = computed(() => {\r\n if (!startCell.value.length) return null\r\n const [startX, startY] = startCell.value\r\n\r\n if (!endCell.value.length) return { row: [startX, startX], col: [startY, startY] }\r\n const [endX, endY] = endCell.value\r\n\r\n if (startX === endX && startY === endY) return { row: [startX, startX], col: [startY, startY] }\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n return {\r\n row: [minX, maxX],\r\n col: [minY, maxY],\r\n }\r\n })\r\n\r\n // 设置选中单元格状态(鼠标点击或拖选)\r\n const handleMouseup = () => isStartSelect.value = false\r\n\r\n const handleCellMousedown = (e: MouseEvent, rowIndex: number, colIndex: number) => {\r\n if (e.button === 0) {\r\n endCell.value = []\r\n isStartSelect.value = true\r\n startCell.value = [rowIndex, colIndex]\r\n }\r\n }\r\n\r\n const handleCellMouseenter = (rowIndex: number, colIndex: number) => {\r\n if (!isStartSelect.value) return\r\n endCell.value = [rowIndex, colIndex]\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('mouseup', handleMouseup)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('mouseup', handleMouseup)\r\n })\r\n\r\n // 判断某位置是否为无效单元格(被合并掉的位置)\r\n const isHideCell = (rowIndex: number, colIndex: number) => hideCells.value.includes(`${rowIndex}_${colIndex}`)\r\n\r\n // 选中指定的列\r\n const selectCol = (index: number) => {\r\n const maxRow = tableCells.value.length - 1\r\n startCell.value = [0, index]\r\n endCell.value = [maxRow, index]\r\n }\r\n\r\n // 选中指定的行\r\n const selectRow = (index: number) => {\r\n const maxCol = tableCells.value[index].length - 1\r\n startCell.value = [index, 0]\r\n endCell.value = [index, maxCol]\r\n }\r\n\r\n // 选中全部单元格\r\n const selectAll = () => {\r\n const maxRow = tableCells.value.length - 1\r\n const maxCol = tableCells.value[maxRow].length - 1\r\n startCell.value = [0, 0]\r\n endCell.value = [maxRow, maxCol]\r\n }\r\n\r\n // 删除一行\r\n const deleteRow = (rowIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const targetCells = tableCells.value[rowIndex]\r\n const hideCellsPos = []\r\n for (let i = 0; i < targetCells.length; i++) {\r\n if (isHideCell(rowIndex, i)) hideCellsPos.push(i)\r\n }\r\n \r\n for (const pos of hideCellsPos) {\r\n for (let i = rowIndex; i >= 0; i--) {\r\n if (!isHideCell(i, pos)) {\r\n _tableCells[i][pos].rowspan = _tableCells[i][pos].rowspan - 1\r\n break\r\n }\r\n }\r\n }\r\n\r\n _tableCells.splice(rowIndex, 1)\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 删除一列\r\n const deleteCol = (colIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const hideCellsPos = []\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n if (isHideCell(i, colIndex)) hideCellsPos.push(i)\r\n }\r\n\r\n for (const pos of hideCellsPos) {\r\n for (let i = colIndex; i >= 0; i--) {\r\n if (!isHideCell(pos, i)) {\r\n _tableCells[pos][i].colspan = _tableCells[pos][i].colspan - 1\r\n break\r\n }\r\n }\r\n }\r\n\r\n tableCells.value = _tableCells.map(item => {\r\n item.splice(colIndex, 1)\r\n return item\r\n })\r\n colSizeList.value.splice(colIndex, 1)\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n \r\n // 插入一行\r\n const insertRow = (rowIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n const rowCells: TableCell[] = []\r\n for (let i = 0; i < _tableCells[0].length; i++) {\r\n rowCells.push({\r\n colspan: 1,\r\n rowspan: 1,\r\n text: '',\r\n id: createRandomCode(),\r\n })\r\n }\r\n\r\n _tableCells.splice(rowIndex, 0, rowCells)\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 插入一列\r\n const insertCol = (colIndex: number) => {\r\n tableCells.value = tableCells.value.map(item => {\r\n const cell = {\r\n colspan: 1,\r\n rowspan: 1,\r\n text: '',\r\n id: createRandomCode(),\r\n }\r\n item.splice(colIndex, 0, cell)\r\n return item\r\n })\r\n colSizeList.value.splice(colIndex, 0, 100)\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n \r\n // 合并单元格\r\n const mergeCells = () => {\r\n const [startX, startY] = startCell.value\r\n const [endX, endY] = endCell.value\r\n\r\n const minX = Math.min(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxX = Math.max(startX, endX)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n \r\n _tableCells[minX][minY].rowspan = maxX - minX + 1\r\n _tableCells[minX][minY].colspan = maxY - minY + 1\r\n\r\n tableCells.value = _tableCells\r\n removeSelectedCells()\r\n }\r\n\r\n // 拆分单元格\r\n const splitCells = (rowIndex: number, colIndex: number) => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n _tableCells[rowIndex][colIndex].rowspan = 1\r\n _tableCells[rowIndex][colIndex].colspan = 1\r\n\r\n tableCells.value = _tableCells\r\n removeSelectedCells()\r\n }\r\n\r\n // 鼠标拖拽调整列宽\r\n const handleMousedownColHandler = (e: MouseEvent, colIndex: number) => {\r\n removeSelectedCells()\r\n let isMouseDown = true\r\n\r\n const originWidth = colSizeList.value[colIndex]\r\n const startPageX = e.pageX\r\n\r\n const minWidth = 50\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n \r\n const moveX = (e.pageX - startPageX) / canvasScale.value\r\n const width = originWidth + moveX < minWidth ? minWidth : Math.round(originWidth + moveX)\r\n\r\n colSizeList.value[colIndex] = width\r\n }\r\n document.onmouseup = () => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n emit('changeColWidths', colSizeList.value)\r\n }\r\n }\r\n\r\n // 清空选中单元格内的文字\r\n const clearSelectedCellText = () => {\r\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\r\n\r\n for (let i = 0; i < _tableCells.length; i++) {\r\n for (let j = 0; j < _tableCells[i].length; j++) {\r\n if (selectedCells.value.includes(`${i}_${j}`)) {\r\n _tableCells[i][j].text = ''\r\n }\r\n }\r\n }\r\n tableCells.value = _tableCells\r\n }\r\n\r\n // 将焦点移动到下一个单元格\r\n // 当前行右边有单元格时,焦点右移\r\n // 当前行右边无单元格(已处在行末),且存在下一行时,焦点移动下下一行行首\r\n // 当前行右边无单元格(已处在行末),且不存在下一行(已处在最后一行)时,新建一行并将焦点移动下下一行行首\r\n const tabActiveCell = () => {\r\n const getNextCell = (i: number, j: number): [number, number] | null => {\r\n if (!tableCells.value[i]) return null\r\n if (!tableCells.value[i][j]) return getNextCell(i + 1, 0)\r\n if (isHideCell(i, j)) return getNextCell(i, j + 1)\r\n return [i, j]\r\n }\r\n\r\n endCell.value = []\r\n\r\n const nextRow = startCell.value[0]\r\n const nextCol = startCell.value[1] + 1\r\n\r\n const nextCell = getNextCell(nextRow, nextCol)\r\n if (!nextCell) {\r\n insertRow(nextRow + 1)\r\n startCell.value = [nextRow + 1, 0]\r\n }\r\n else startCell.value = nextCell\r\n\r\n // 移动焦点后自动聚焦文本\r\n nextTick(() => {\r\n const textRef = document.querySelector('.cell-text.active') as HTMLInputElement\r\n if (textRef) textRef.focus()\r\n })\r\n }\r\n\r\n // 表格快捷键监听\r\n const keydownListener = (e: KeyboardEvent) => {\r\n if (!props.editable || !selectedCells.value.length) return\r\n\r\n const key = e.key.toUpperCase()\r\n if (selectedCells.value.length < 2) {\r\n if (key === KEYS.TAB) {\r\n e.preventDefault()\r\n tabActiveCell()\r\n }\r\n if (e.ctrlKey && key === KEYS.UP) {\r\n e.preventDefault()\r\n const rowIndex = +selectedCells.value[0].split('_')[0]\r\n insertRow(rowIndex)\r\n }\r\n if (e.ctrlKey && key === KEYS.DOWN) {\r\n e.preventDefault()\r\n const rowIndex = +selectedCells.value[0].split('_')[0]\r\n insertRow(rowIndex + 1)\r\n }\r\n if (e.ctrlKey && key === KEYS.LEFT) {\r\n e.preventDefault()\r\n const colIndex = +selectedCells.value[0].split('_')[1]\r\n insertCol(colIndex)\r\n }\r\n if (e.ctrlKey && key === KEYS.RIGHT) {\r\n e.preventDefault()\r\n const colIndex = +selectedCells.value[0].split('_')[1]\r\n insertCol(colIndex + 1)\r\n }\r\n }\r\n else if (key === KEYS.DELETE) {\r\n clearSelectedCellText()\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('keydown', keydownListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keydownListener)\r\n })\r\n\r\n // 单元格文字输入时更新表格数据\r\n const handleInput = debounce(function() {\r\n emit('change', tableCells.value)\r\n }, 300, { trailing: true })\r\n\r\n // 获取有效的单元格(排除掉被合并的单元格)\r\n const getEffectiveTableCells = () => {\r\n const effectiveTableCells = []\r\n\r\n for (let i = 0; i < tableCells.value.length; i++) {\r\n const rowCells = tableCells.value[i]\r\n const _rowCells = []\r\n for (let j = 0; j < rowCells.length; j++) {\r\n if (!isHideCell(i, j)) _rowCells.push(rowCells[j])\r\n }\r\n if (_rowCells.length) effectiveTableCells.push(_rowCells)\r\n }\r\n\r\n return effectiveTableCells\r\n }\r\n\r\n // 检查是否可以删除行和列:有效的行/列数大于1\r\n const checkCanDeleteRowOrCol = () => {\r\n const effectiveTableCells = getEffectiveTableCells()\r\n const canDeleteRow = effectiveTableCells.length > 1\r\n const canDeleteCol = effectiveTableCells[0].length > 1\r\n\r\n return { canDeleteRow, canDeleteCol }\r\n }\r\n\r\n // 检查是否可以合并或拆分\r\n // 必须多选才可以合并\r\n // 必须单选且所选单元格为合并单元格才可以拆分\r\n const checkCanMergeOrSplit = (rowIndex: number, colIndex: number) => {\r\n const isMultiSelected = selectedCells.value.length > 1\r\n const targetCell = tableCells.value[rowIndex][colIndex]\r\n\r\n const canMerge = isMultiSelected\r\n const canSplit = !isMultiSelected && (targetCell.rowspan > 1 || targetCell.colspan > 1)\r\n\r\n return { canMerge, canSplit }\r\n }\r\n\r\n const contextmenus = (el: HTMLElement): ContextmenuItem[] => {\r\n const cellIndex = el.dataset.cellIndex as string\r\n const rowIndex = +cellIndex.split('_')[0]\r\n const colIndex = +cellIndex.split('_')[1]\r\n\r\n if (!selectedCells.value.includes(`${rowIndex}_${colIndex}`)) {\r\n startCell.value = [rowIndex, colIndex]\r\n endCell.value = []\r\n }\r\n\r\n const { canMerge, canSplit } = checkCanMergeOrSplit(rowIndex, colIndex)\r\n const { canDeleteRow, canDeleteCol } = checkCanDeleteRowOrCol()\r\n\r\n return [\r\n {\r\n text: '插入列',\r\n children: [\r\n { text: '到左侧', handler: () => insertCol(colIndex) },\r\n { text: '到右侧', handler: () => insertCol(colIndex + 1) },\r\n ],\r\n },\r\n {\r\n text: '插入行',\r\n children: [\r\n { text: '到上方', handler: () => insertRow(rowIndex) },\r\n { text: '到下方', handler: () => insertRow(rowIndex + 1) },\r\n ],\r\n },\r\n {\r\n text: '删除列',\r\n disable: !canDeleteCol,\r\n handler: () => deleteCol(colIndex),\r\n },\r\n {\r\n text: '删除行',\r\n disable: !canDeleteRow,\r\n handler: () => deleteRow(rowIndex),\r\n },\r\n { divider: true },\r\n {\r\n text: '合并单元格',\r\n disable: !canMerge,\r\n handler: mergeCells,\r\n },\r\n {\r\n text: '取消合并单元格',\r\n disable: !canSplit,\r\n handler: () => splitCells(rowIndex, colIndex),\r\n },\r\n { divider: true },\r\n {\r\n text: '选中当前列',\r\n handler: () => selectCol(colIndex),\r\n },\r\n {\r\n text: '选中当前行',\r\n handler: () => selectRow(rowIndex),\r\n },\r\n {\r\n text: '选中全部单元格',\r\n handler: selectAll,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n getTextStyle,\r\n dragLinePosition,\r\n tableCells,\r\n colSizeList,\r\n totalWidth,\r\n hideCells,\r\n selectedCells,\r\n activedCell,\r\n selectedRange,\r\n handleCellMousedown,\r\n handleCellMouseenter,\r\n selectCol,\r\n selectRow,\r\n handleMousedownColHandler,\r\n contextmenus,\r\n handleInput,\r\n subThemeColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./EditableTable.vue?vue&type=template&id=ae1d6576&scoped=true\"\nimport script from \"./EditableTable.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableTable.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableTable.vue?vue&type=style&index=0&id=ae1d6576&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-ae1d6576\"\n\nexport default script","\r\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTableElement, TableCell } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport EditableTable from './EditableTable.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-table',\r\n components: {\r\n EditableTable,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n \r\n const elementRef = ref<HTMLElement>()\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if (props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n // 更新表格的可编辑状态,表格处于编辑状态时需要禁用全局快捷键\r\n const editable = ref(false)\r\n\r\n watch(handleElementId, () => {\r\n if (handleElementId.value !== props.elementInfo.id) editable.value = false\r\n })\r\n\r\n watch(editable, () => {\r\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, editable.value)\r\n })\r\n\r\n const startEdit = () => {\r\n if (!props.elementInfo.lock) editable.value = true\r\n }\r\n\r\n // 监听表格元素的尺寸变化,当高度变化时,更新高度到vuex\r\n // 如果高度变化时正处在缩放操作中,则等待缩放操作结束后再更新\r\n const isScaling = ref(false)\r\n const realHeightCache = ref(-1)\r\n\r\n const scaleElementStateListener = (state: boolean) => {\r\n isScaling.value = state\r\n\r\n if (state) editable.value = false\r\n\r\n if (!state && realHeightCache.value !== -1) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeightCache.value },\r\n })\r\n realHeightCache.value = -1\r\n }\r\n }\r\n\r\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\r\n })\r\n\r\n const updateTableElementHeight = (entries: ResizeObserverEntry[]) => {\r\n const contentRect = entries[0].contentRect\r\n if (!elementRef.value) return\r\n\r\n const realHeight = contentRect.height\r\n\r\n if (props.elementInfo.height !== realHeight) {\r\n if (!isScaling.value) {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id,\r\n props: { height: realHeight },\r\n })\r\n }\r\n else realHeightCache.value = realHeight\r\n }\r\n }\r\n\r\n const resizeObserver = new ResizeObserver(updateTableElementHeight)\r\n\r\n onMounted(() => {\r\n if (elementRef.value) resizeObserver.observe(elementRef.value)\r\n })\r\n onUnmounted(() => {\r\n if (elementRef.value) resizeObserver.unobserve(elementRef.value)\r\n })\r\n\r\n // 更新表格内容数据\r\n const updateTableCells = (data: TableCell[][]) => {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { data },\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 更新表格的列宽数据\r\n const updateColWidths = (widths: number[]) => {\r\n const width = widths.reduce((a, b) => a + b)\r\n const colWidths = widths.map(item => item / width)\r\n\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: props.elementInfo.id, \r\n props: { width, colWidths },\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 更新表格当前选中的单元格\r\n const updateSelectedCells = (cells: string[]) => {\r\n nextTick(() => emitter.emit(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells))\r\n }\r\n\r\n return {\r\n elementRef,\r\n canvasScale,\r\n handleSelectElement,\r\n updateTableCells,\r\n updateColWidths,\r\n editable,\r\n startEdit,\r\n updateSelectedCells,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=c0edfdac&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=c0edfdac&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-c0edfdac\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport useLockElement from '@/hooks/useLockElement'\r\nimport useDeleteElement from '@/hooks/useDeleteElement'\r\nimport useCombineElement from '@/hooks/useCombineElement'\r\nimport useOrderElement from '@/hooks/useOrderElement'\r\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\r\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\r\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\r\n\r\nimport { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'\r\n\r\nimport ImageElement from '@/views/components/element/ImageElement/index.vue'\r\nimport TextElement from '@/views/components/element/TextElement/index.vue'\r\nimport ShapeElement from '@/views/components/element/ShapeElement/index.vue'\r\nimport LineElement from '@/views/components/element/LineElement/index.vue'\r\nimport ChartElement from '@/views/components/element/ChartElement/index.vue'\r\nimport TableElement from '@/views/components/element/TableElement/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElement,\r\n [ElementTypes.TEXT]: TextElement,\r\n [ElementTypes.SHAPE]: ShapeElement,\r\n [ElementTypes.LINE]: LineElement,\r\n [ElementTypes.CHART]: ChartElement,\r\n [ElementTypes.TABLE]: TableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const { orderElement } = useOrderElement()\r\n const { alignElementToCanvas } = useAlignElementToCanvas()\r\n const { combineElements, uncombineElements } = useCombineElement()\r\n const { deleteElement } = useDeleteElement()\r\n const { lockElement, unlockElement } = useLockElement()\r\n const { copyElement, pasteElement, cutElement } = useCopyAndPasteElement()\r\n const { selectAllElement } = useSelectAllElement()\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n if (props.elementInfo.lock) {\r\n return [{\r\n text: '解锁', \r\n handler: () => unlockElement(props.elementInfo),\r\n }]\r\n }\r\n\r\n return [\r\n {\r\n text: '剪切',\r\n subText: 'Ctrl + X',\r\n handler: cutElement,\r\n },\r\n {\r\n text: '复制',\r\n subText: 'Ctrl + C',\r\n handler: copyElement,\r\n },\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteElement,\r\n },\r\n { divider: true },\r\n {\r\n text: '对齐方式',\r\n children: [\r\n { text: '水平垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.CENTER) },\r\n { divider: true },\r\n { text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },\r\n { text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },\r\n { text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },\r\n { divider: true },\r\n { text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },\r\n { text: '顶部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },\r\n { text: '底部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },\r\n ],\r\n },\r\n {\r\n text: '层级排序',\r\n disable: props.isMultiSelect && !props.elementInfo.groupId,\r\n children: [\r\n { text: '置顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },\r\n { text: '置底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },\r\n { divider: true },\r\n { text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },\r\n { text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },\r\n ],\r\n },\r\n { divider: true },\r\n {\r\n text: props.elementInfo.groupId ? '取消组合' : '组合',\r\n subText: 'Ctrl + G',\r\n handler: props.elementInfo.groupId ? uncombineElements : combineElements,\r\n hide: !props.isMultiSelect,\r\n },\r\n {\r\n text: '全选',\r\n subText: 'Ctrl + A',\r\n handler: selectAllElement,\r\n },\r\n {\r\n text: '锁定',\r\n subText: 'Ctrl + L',\r\n handler: lockElement,\r\n },\r\n {\r\n text: '删除',\r\n subText: 'Delete',\r\n handler: deleteElement,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n currentElementComponent,\r\n contextmenus,\r\n theme,\r\n }\r\n },\r\n})\r\n","import { render } from \"./EditableElement.vue?vue&type=template&id=66e6b935\"\nimport script from \"./EditableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div :class=\"`mouse-selection quadrant-${quadrant}`\"\r\n :style=\"{\r\n top: top + 'px',\r\n left: left + 'px',\r\n width: width + 'px',\r\n height: height + 'px',\r\n }\"\r\n ></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'mouse-selection',\r\n props: {\r\n top: {\r\n type: Number,\r\n required: true,\r\n },\r\n left: {\r\n type: Number,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n quadrant: {\r\n type: Number,\r\n required: true,\r\n validator(value: number) {\r\n return [1, 2, 3, 4].includes(value)\r\n },\r\n },\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.mouse-selection {\r\n position: absolute;\r\n background-color: rgba($themeColor, 0.1);\r\n border: 1px solid $themeColor;\r\n z-index: 200;\r\n\r\n &.quadrant-1 {\r\n transform-origin: 0 0;\r\n transform: rotate(180deg);\r\n }\r\n &.quadrant-2 {\r\n transform-origin: 50% 0;\r\n transform: rotate(180deg);\r\n }\r\n &.quadrant-3 {\r\n transform-origin: 0 50%;\r\n transform: rotate(180deg);\r\n }\r\n &.quadrant-4 {\r\n transform-origin: 0 0;\r\n transform: rotate(0deg);\r\n }\r\n}\r\n</style>","\r\nexport default {\r\n name: 'mouse-selection',\r\n props: {\r\n top: {\r\n type: Number,\r\n required: true,\r\n },\r\n left: {\r\n type: Number,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n height: {\r\n type: Number,\r\n required: true,\r\n },\r\n quadrant: {\r\n type: Number,\r\n required: true,\r\n validator(value: number) {\r\n return [1, 2, 3, 4].includes(value)\r\n },\r\n },\r\n }\r\n}\r\n","import { render } from \"./MouseSelection.vue?vue&type=template&id=1619c258&scoped=true\"\nimport script from \"./MouseSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./MouseSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./MouseSelection.vue?vue&type=style&index=0&id=1619c258&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1619c258\"\n\nexport default script","<template>\r\n <div \r\n class=\"slide-background\"\r\n :style=\"backgroundStyle\"\r\n >\r\n <GridLines v-if=\"showGridLines\" />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { SlideBackground } from '@/types/slides'\r\nimport GridLines from './GridLines.vue'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nexport default defineComponent({\r\n name: 'slide-background',\r\n components: {\r\n GridLines,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)\r\n\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n return {\r\n showGridLines,\r\n backgroundStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.slide-background {\r\n width: 100%;\r\n height: 100%;\r\n background-position: center;\r\n position: absolute;\r\n}\r\n</style>\r\n","<template>\r\n <SvgWrapper class=\"grid-lines\">\r\n <path \r\n :style=\"{\r\n transform: `scale(${canvasScale})`,\r\n }\" \r\n :d=\"path\" \r\n fill=\"none\" \r\n :stroke=\"gridColor\" \r\n stroke-width=\"0.3\" \r\n shape-rendering=\"crispEdges\"\r\n stroke-dasharray=\"5\"\r\n ></path>\r\n </SvgWrapper>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, computed } from 'vue'\r\nimport tinycolor from 'tinycolor2'\r\nimport { useStore } from '@/store'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport { SlideBackground } from '@/types/slides'\r\n\r\nexport default defineComponent({\r\n name: 'grid-lines',\r\n setup() {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)\r\n\r\n // 计算网格线的颜色,避免与背景的颜色太接近\r\n const gridColor = computed(() => {\r\n if (!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'\r\n const color = background.value.color\r\n const rgba = tinycolor(color).toRgb()\r\n const newRgba = {\r\n r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,\r\n g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,\r\n b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,\r\n a: 0.5\r\n }\r\n return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`\r\n })\r\n\r\n const gridSize = 50\r\n\r\n // 计算网格路径\r\n const getPath = () => {\r\n const maxX = VIEWPORT_SIZE\r\n const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n\r\n let path = ''\r\n for (let i = 0; i <= Math.floor(maxY / gridSize); i++) {\r\n path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`\r\n }\r\n for (let i = 0; i <= Math.floor(maxX / gridSize); i++) {\r\n path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`\r\n }\r\n return path\r\n }\r\n\r\n return {\r\n canvasScale,\r\n gridColor,\r\n width: VIEWPORT_SIZE,\r\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\r\n path: getPath(),\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.grid-lines {\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n bottom: 0;\r\n right: 0;\r\n overflow: visible;\r\n}\r\n</style>","\r\nimport { defineComponent, computed } from 'vue'\r\nimport tinycolor from 'tinycolor2'\r\nimport { useStore } from '@/store'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport { SlideBackground } from '@/types/slides'\r\n\r\nexport default defineComponent({\r\n name: 'grid-lines',\r\n setup() {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)\r\n\r\n // 计算网格线的颜色,避免与背景的颜色太接近\r\n const gridColor = computed(() => {\r\n if (!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'\r\n const color = background.value.color\r\n const rgba = tinycolor(color).toRgb()\r\n const newRgba = {\r\n r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,\r\n g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,\r\n b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,\r\n a: 0.5\r\n }\r\n return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`\r\n })\r\n\r\n const gridSize = 50\r\n\r\n // 计算网格路径\r\n const getPath = () => {\r\n const maxX = VIEWPORT_SIZE\r\n const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\r\n\r\n let path = ''\r\n for (let i = 0; i <= Math.floor(maxY / gridSize); i++) {\r\n path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`\r\n }\r\n for (let i = 0; i <= Math.floor(maxX / gridSize); i++) {\r\n path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`\r\n }\r\n return path\r\n }\r\n\r\n return {\r\n canvasScale,\r\n gridColor,\r\n width: VIEWPORT_SIZE,\r\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\r\n path: getPath(),\r\n }\r\n },\r\n})\r\n","import { render } from \"./GridLines.vue?vue&type=template&id=5664d2b2&scoped=true\"\nimport script from \"./GridLines.vue?vue&type=script&lang=ts\"\nexport * from \"./GridLines.vue?vue&type=script&lang=ts\"\n\nimport \"./GridLines.vue?vue&type=style&index=0&id=5664d2b2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5664d2b2\"\n\nexport default script","import { Ref, computed } from 'vue'\r\nimport { SlideBackground } from '@/types/slides'\r\n\r\n// 将页面背景数据转换为css样式\r\nexport default (background: Ref<SlideBackground | undefined>) => {\r\n const backgroundStyle = computed(() => {\r\n if (!background.value) return { backgroundColor: '#fff' }\r\n\r\n const {\r\n type,\r\n color,\r\n image,\r\n imageSize,\r\n gradientColor,\r\n gradientRotate,\r\n gradientType,\r\n } = background.value\r\n\r\n // 纯色背景\r\n if (type === 'solid') return { backgroundColor: color }\r\n\r\n // 背景图模式\r\n // 包括:背景图、背景大小,是否重复\r\n else if (type === 'image') {\r\n if (!image) return { backgroundColor: '#fff' }\r\n if (imageSize === 'repeat') {\r\n return {\r\n backgroundImage: `url(${image}`,\r\n backgroundRepeat: 'repeat',\r\n backgroundSize: 'initial',\r\n }\r\n }\r\n return {\r\n backgroundImage: `url(${image}`,\r\n backgroundRepeat: 'no-repeat',\r\n backgroundSize: imageSize || 'cover',\r\n }\r\n }\r\n\r\n // 渐变色背景\r\n else if (type === 'gradient') {\r\n const rotate = gradientRotate || 0\r\n const color1 = gradientColor ? gradientColor[0] : '#fff'\r\n const color2 = gradientColor ? gradientColor[1] : '#fff'\r\n \r\n if (gradientType === 'radial') return { backgroundImage: `radial-gradient(${color1}, ${color2}` }\r\n return { backgroundImage: `linear-gradient(${rotate}deg, ${color1}, ${color2}` }\r\n }\r\n\r\n return { backgroundColor: '#fff' }\r\n })\r\n\r\n return {\r\n backgroundStyle,\r\n }\r\n}","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { SlideBackground } from '@/types/slides'\r\nimport GridLines from './GridLines.vue'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nexport default defineComponent({\r\n name: 'slide-background',\r\n components: {\r\n GridLines,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)\r\n\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n return {\r\n showGridLines,\r\n backgroundStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./SlideBackground.vue?vue&type=template&id=a1052b6c&scoped=true\"\nimport script from \"./SlideBackground.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideBackground.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideBackground.vue?vue&type=style&index=0&id=a1052b6c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a1052b6c\"\n\nexport default script","<template>\r\n <div class=\"alignment-line\" :style=\"{ left, top }\">\r\n <div :class=\"['line', type]\" :style=\"sizeStyle\"></div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { AlignmentLineAxis } from '@/types/edit'\r\n\r\nexport default defineComponent({\r\n name: 'alignment-line',\r\n props: {\r\n type: {\r\n type: String as PropType<'vertical' | 'horizontal'>,\r\n required: true,\r\n },\r\n axis: {\r\n type: Object as PropType<AlignmentLineAxis>,\r\n required: true,\r\n },\r\n length: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n // 吸附对齐线的位置\r\n const left = computed(() => props.axis.x * canvasScale.value + 'px')\r\n const top = computed(() => props.axis.y * canvasScale.value + 'px')\r\n\r\n // 吸附对齐线的长度\r\n const sizeStyle = computed(() => {\r\n if (props.type === 'vertical') return { height: props.length * canvasScale.value + 'px' }\r\n return { width: props.length * canvasScale.value + 'px' }\r\n })\r\n\r\n return {\r\n left,\r\n top,\r\n sizeStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.alignment-line {\r\n position: absolute;\r\n z-index: 100;\r\n\r\n .line {\r\n width: 0;\r\n height: 0;\r\n border: 0 dashed $themeColor;\r\n\r\n &.vertical {\r\n transform: translateY(-0.5px);\r\n border-left-width: 1px;\r\n }\r\n &.horizontal {\r\n transform: translateX(-0.5px);\r\n border-top-width: 1px;\r\n }\r\n }\r\n}\r\n</style>","\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { AlignmentLineAxis } from '@/types/edit'\r\n\r\nexport default defineComponent({\r\n name: 'alignment-line',\r\n props: {\r\n type: {\r\n type: String as PropType<'vertical' | 'horizontal'>,\r\n required: true,\r\n },\r\n axis: {\r\n type: Object as PropType<AlignmentLineAxis>,\r\n required: true,\r\n },\r\n length: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n // 吸附对齐线的位置\r\n const left = computed(() => props.axis.x * canvasScale.value + 'px')\r\n const top = computed(() => props.axis.y * canvasScale.value + 'px')\r\n\r\n // 吸附对齐线的长度\r\n const sizeStyle = computed(() => {\r\n if (props.type === 'vertical') return { height: props.length * canvasScale.value + 'px' }\r\n return { width: props.length * canvasScale.value + 'px' }\r\n })\r\n\r\n return {\r\n left,\r\n top,\r\n sizeStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./AlignmentLine.vue?vue&type=template&id=2d3eddf5&scoped=true\"\nimport script from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\nexport * from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\n\nimport \"./AlignmentLine.vue?vue&type=style&index=0&id=2d3eddf5&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2d3eddf5\"\n\nexport default script","<template>\r\n <div \r\n class=\"element-create-selection\"\r\n ref=\"selectionRef\"\r\n @mousedown.stop=\"$event => createSelection($event)\"\r\n >\r\n <div :class=\"['selection', creatingElement.type]\" v-if=\"start && end\" :style=\"position\">\r\n\r\n <!-- 绘制线条专用 -->\r\n <SvgWrapper\r\n v-if=\"creatingElement.type === 'line' && lineData\"\r\n overflow=\"visible\" \r\n :width=\"lineData.svgWidth\"\r\n :height=\"lineData.svgHeight\"\r\n >\r\n\t\t\t\t<path\r\n :d=\"lineData.path\" \r\n stroke=\"#888\" \r\n fill=\"none\" \r\n stroke-width=\"1\" \r\n stroke-linecap \r\n stroke-linejoin \r\n stroke-miterlimit \r\n ></path>\r\n\t\t\t</SvgWrapper>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onMounted, reactive, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\n\r\nexport default defineComponent({\r\n name: 'element-create-selection',\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n const creatingElement = computed(() => store.state.creatingElement)\r\n\r\n const start = ref<[number, number] | null>(null)\r\n const end = ref<[number, number] | null>(null)\r\n\r\n const selectionRef = ref<HTMLElement>()\r\n const offset = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n onMounted(() => {\r\n if (!selectionRef.value) return\r\n const { x, y } = selectionRef.value.getBoundingClientRect()\r\n offset.x = x\r\n offset.y = y\r\n })\r\n\r\n // 鼠标拖动创建元素生成位置大小\r\n // 获取范围的起始位置和终点位置\r\n const createSelection = (e: MouseEvent) => {\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n start.value = [startPageX, startPageY]\r\n\r\n document.onmousemove = e => {\r\n if (!creatingElement.value || !isMouseDown) return\r\n\r\n let currentPageX = e.pageX\r\n let currentPageY = e.pageY\r\n\r\n // 按住Ctrl键或者Shift键时:\r\n // 对于非线条元素需要锁定宽高比例,对于线条元素需要锁定水平或垂直方向\r\n if (ctrlOrShiftKeyActive.value) {\r\n const moveX = currentPageX - startPageX\r\n const moveY = currentPageY - startPageY\r\n\r\n // 水平和垂直方向的拖动距离,后面以拖动距离较大的方向为基础计算另一方向的数据\r\n const absX = Math.abs(moveX)\r\n const absY = Math.abs(moveY)\r\n\r\n if (creatingElement.value.type === 'shape') {\r\n\r\n // 判断是否为反向拖动:从左上到右下为正向操作,此外所有情况都是反向操作\r\n const isOpposite = (moveY > 0 && moveX < 0) || (moveY < 0 && moveX > 0)\r\n\r\n if (absX > absY) {\r\n currentPageY = isOpposite ? startPageY - moveX : startPageY + moveX\r\n }\r\n else {\r\n currentPageX = isOpposite ? startPageX - moveY : startPageX + moveY\r\n }\r\n }\r\n\r\n else if (creatingElement.value.type === 'line') {\r\n if (absX > absY) currentPageY = startPageY\r\n else currentPageX = startPageX\r\n }\r\n }\r\n\r\n end.value = [currentPageX, currentPageY]\r\n }\r\n\r\n document.onmouseup = e => {\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n isMouseDown = false\r\n\r\n const endPageX = e.pageX\r\n const endPageY = e.pageY\r\n\r\n const minSize = 30\r\n\r\n if (Math.abs(endPageX - startPageX) >= minSize || Math.abs(endPageY - startPageY) >= minSize) {\r\n emit('created', {\r\n start: start.value,\r\n end: end.value,\r\n })\r\n }\r\n else store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\r\n }\r\n }\r\n\r\n // 绘制线条的路径相关数据(仅当绘制元素类型为线条时使用)\r\n const lineData = computed(() => {\r\n if (!start.value || !end.value) return null\r\n if (!creatingElement.value || creatingElement.value.type !== 'line') return null\r\n\r\n const [_startX, _startY] = start.value\r\n const [_endX, _endY] = end.value\r\n const minX = Math.min(_startX, _endX)\r\n const maxX = Math.max(_startX, _endX)\r\n const minY = Math.min(_startY, _endY)\r\n const maxY = Math.max(_startY, _endY)\r\n\r\n const svgWidth = maxX - minX >= 24 ? maxX - minX : 24\r\n const svgHeight = maxY - minY >= 24 ? maxY - minY : 24\r\n\r\n const startX = _startX === minX ? 0 : maxX - minX\r\n const startY = _startY === minY ? 0 : maxY - minY\r\n const endX = _endX === minX ? 0 : maxX - minX\r\n const endY = _endY === minY ? 0 : maxY - minY\r\n\r\n const path = `M${startX}, ${startY} L${endX}, ${endY}`\r\n\r\n return {\r\n svgWidth,\r\n svgHeight,\r\n startX,\r\n startY,\r\n endX,\r\n endY,\r\n path,\r\n }\r\n })\r\n\r\n // 根据生成范围的起始位置和终点位置,计算元素创建时的位置和大小\r\n const position = computed(() => {\r\n if (!start.value || !end.value) return {}\r\n\r\n const [startX, startY] = start.value\r\n const [endX, endY] = end.value\r\n const minX = Math.min(startX, endX)\r\n const maxX = Math.max(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const width = maxX - minX\r\n const height = maxY - minY\r\n\r\n return {\r\n left: minX - offset.x + 'px',\r\n top: minY - offset.y + 'px',\r\n width: width + 'px',\r\n height: height + 'px',\r\n }\r\n })\r\n\r\n return {\r\n selectionRef,\r\n start,\r\n end,\r\n creatingElement,\r\n createSelection,\r\n lineData,\r\n position,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.element-create-selection {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n z-index: 2;\r\n cursor: crosshair;\r\n}\r\n.selection {\r\n position: absolute;\r\n\r\n &:not(.line) {\r\n border: 1px solid #888;\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent, onMounted, reactive, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\n\r\nexport default defineComponent({\r\n name: 'element-create-selection',\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n const creatingElement = computed(() => store.state.creatingElement)\r\n\r\n const start = ref<[number, number] | null>(null)\r\n const end = ref<[number, number] | null>(null)\r\n\r\n const selectionRef = ref<HTMLElement>()\r\n const offset = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n onMounted(() => {\r\n if (!selectionRef.value) return\r\n const { x, y } = selectionRef.value.getBoundingClientRect()\r\n offset.x = x\r\n offset.y = y\r\n })\r\n\r\n // 鼠标拖动创建元素生成位置大小\r\n // 获取范围的起始位置和终点位置\r\n const createSelection = (e: MouseEvent) => {\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n start.value = [startPageX, startPageY]\r\n\r\n document.onmousemove = e => {\r\n if (!creatingElement.value || !isMouseDown) return\r\n\r\n let currentPageX = e.pageX\r\n let currentPageY = e.pageY\r\n\r\n // 按住Ctrl键或者Shift键时:\r\n // 对于非线条元素需要锁定宽高比例,对于线条元素需要锁定水平或垂直方向\r\n if (ctrlOrShiftKeyActive.value) {\r\n const moveX = currentPageX - startPageX\r\n const moveY = currentPageY - startPageY\r\n\r\n // 水平和垂直方向的拖动距离,后面以拖动距离较大的方向为基础计算另一方向的数据\r\n const absX = Math.abs(moveX)\r\n const absY = Math.abs(moveY)\r\n\r\n if (creatingElement.value.type === 'shape') {\r\n\r\n // 判断是否为反向拖动:从左上到右下为正向操作,此外所有情况都是反向操作\r\n const isOpposite = (moveY > 0 && moveX < 0) || (moveY < 0 && moveX > 0)\r\n\r\n if (absX > absY) {\r\n currentPageY = isOpposite ? startPageY - moveX : startPageY + moveX\r\n }\r\n else {\r\n currentPageX = isOpposite ? startPageX - moveY : startPageX + moveY\r\n }\r\n }\r\n\r\n else if (creatingElement.value.type === 'line') {\r\n if (absX > absY) currentPageY = startPageY\r\n else currentPageX = startPageX\r\n }\r\n }\r\n\r\n end.value = [currentPageX, currentPageY]\r\n }\r\n\r\n document.onmouseup = e => {\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n isMouseDown = false\r\n\r\n const endPageX = e.pageX\r\n const endPageY = e.pageY\r\n\r\n const minSize = 30\r\n\r\n if (Math.abs(endPageX - startPageX) >= minSize || Math.abs(endPageY - startPageY) >= minSize) {\r\n emit('created', {\r\n start: start.value,\r\n end: end.value,\r\n })\r\n }\r\n else store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\r\n }\r\n }\r\n\r\n // 绘制线条的路径相关数据(仅当绘制元素类型为线条时使用)\r\n const lineData = computed(() => {\r\n if (!start.value || !end.value) return null\r\n if (!creatingElement.value || creatingElement.value.type !== 'line') return null\r\n\r\n const [_startX, _startY] = start.value\r\n const [_endX, _endY] = end.value\r\n const minX = Math.min(_startX, _endX)\r\n const maxX = Math.max(_startX, _endX)\r\n const minY = Math.min(_startY, _endY)\r\n const maxY = Math.max(_startY, _endY)\r\n\r\n const svgWidth = maxX - minX >= 24 ? maxX - minX : 24\r\n const svgHeight = maxY - minY >= 24 ? maxY - minY : 24\r\n\r\n const startX = _startX === minX ? 0 : maxX - minX\r\n const startY = _startY === minY ? 0 : maxY - minY\r\n const endX = _endX === minX ? 0 : maxX - minX\r\n const endY = _endY === minY ? 0 : maxY - minY\r\n\r\n const path = `M${startX}, ${startY} L${endX}, ${endY}`\r\n\r\n return {\r\n svgWidth,\r\n svgHeight,\r\n startX,\r\n startY,\r\n endX,\r\n endY,\r\n path,\r\n }\r\n })\r\n\r\n // 根据生成范围的起始位置和终点位置,计算元素创建时的位置和大小\r\n const position = computed(() => {\r\n if (!start.value || !end.value) return {}\r\n\r\n const [startX, startY] = start.value\r\n const [endX, endY] = end.value\r\n const minX = Math.min(startX, endX)\r\n const maxX = Math.max(startX, endX)\r\n const minY = Math.min(startY, endY)\r\n const maxY = Math.max(startY, endY)\r\n\r\n const width = maxX - minX\r\n const height = maxY - minY\r\n\r\n return {\r\n left: minX - offset.x + 'px',\r\n top: minY - offset.y + 'px',\r\n width: width + 'px',\r\n height: height + 'px',\r\n }\r\n })\r\n\r\n return {\r\n selectionRef,\r\n start,\r\n end,\r\n creatingElement,\r\n createSelection,\r\n lineData,\r\n position,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementCreateSelection.vue?vue&type=template&id=97a153b6&scoped=true\"\nimport script from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementCreateSelection.vue?vue&type=style&index=0&id=97a153b6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-97a153b6\"\n\nexport default script","<template>\r\n <div \r\n class=\"multi-select-operate\"\r\n :style=\"{\r\n left: minX * canvasScale + 'px',\r\n top: minY * canvasScale + 'px',\r\n }\"\r\n >\r\n <BorderLine v-for=\"line in borderLines\" :key=\"line.type\" :type=\"line.type\" :style=\"line.style\" />\r\n\r\n <template v-if=\"!disableResize\">\r\n <ResizeHandler\r\n v-for=\"point in resizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"scaleMultiElement($event, { minX, maxX, minY, maxY }, point.direction)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, reactive, PropType, watchEffect, toRefs } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { getElementListRange } from '@/utils/element'\r\nimport { OperateResizeHandler, MultiSelectRange } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'multi-select-operate',\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementList: {\r\n type: Array as PropType<PPTElement[]>,\r\n required: true,\r\n },\r\n scaleMultiElement: {\r\n type: Function as PropType<(e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))\r\n\r\n const range = reactive({\r\n minX: 0,\r\n maxX: 0,\r\n minY: 0,\r\n maxY: 0,\r\n })\r\n\r\n // 根据多选元素整体在画布中的范围,计算边框线和缩放点的位置信息\r\n const width = computed(() => (range.maxX - range.minX) * canvasScale.value)\r\n const height = computed(() => (range.maxY - range.minY) * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(width, height)\r\n\r\n // 计算多选元素整体在画布中的范围\r\n const setRange = () => {\r\n const { minX, maxX, minY, maxY } = getElementListRange(localActiveElementList.value)\r\n range.minX = minX\r\n range.maxX = maxX\r\n range.minY = minY\r\n range.maxY = maxY\r\n }\r\n watchEffect(setRange)\r\n\r\n // 禁用多选状态下缩放:仅未旋转的图片和形状可以在多选状态下缩放\r\n const disableResize = computed(() => {\r\n return localActiveElementList.value.some(item => {\r\n if (\r\n (item.type === 'image' || item.type === 'shape') && \r\n !item.rotate\r\n ) return false\r\n return true\r\n })\r\n })\r\n\r\n return {\r\n ...toRefs(range),\r\n canvasScale,\r\n borderLines,\r\n disableResize,\r\n resizeHandlers,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.multi-select-operate {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n z-index: 101;\r\n}\r\n</style>","import { computed, Ref } from 'vue'\r\nimport { OperateResizeHandlers, OperateBorderLines } from '@/types/edit'\r\n\r\nexport default (width: Ref<number>, height: Ref<number>) => {\r\n // 元素缩放点\r\n const resizeHandlers = computed(() => {\r\n return [\r\n { direction: OperateResizeHandlers.LEFT_TOP, style: {} },\r\n { direction: OperateResizeHandlers.TOP, style: {left: width.value / 2 + 'px'} },\r\n { direction: OperateResizeHandlers.RIGHT_TOP, style: {left: width.value + 'px'} },\r\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\r\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\r\n { direction: OperateResizeHandlers.LEFT_BOTTOM, style: {top: height.value + 'px'} },\r\n { direction: OperateResizeHandlers.BOTTOM, style: {left: width.value / 2 + 'px', top: height.value + 'px'} },\r\n { direction: OperateResizeHandlers.RIGHT_BOTTOM, style: {left: width.value + 'px', top: height.value + 'px'} },\r\n ]\r\n })\r\n\r\n // 文本元素缩放点\r\n const textElementResizeHandlers = computed(() => {\r\n return [\r\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\r\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\r\n ]\r\n })\r\n\r\n // 元素选中边框线\r\n const borderLines = computed(() => {\r\n return [\r\n { type: OperateBorderLines.T, style: {width: width.value + 'px'} },\r\n { type: OperateBorderLines.B, style: {top: height.value + 'px', width: width.value + 'px'} },\r\n { type: OperateBorderLines.L, style: {height: height.value + 'px'} },\r\n { type: OperateBorderLines.R, style: {left: width.value + 'px', height: height.value + 'px'} },\r\n ]\r\n })\r\n\r\n return {\r\n resizeHandlers,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n}","<template>\r\n <div :class=\"['resize-handler', type]\"></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType } from 'vue'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\n\r\nexport default {\r\n name: 'resize-handler',\r\n props: {\r\n type: {\r\n type: String as PropType<OperateResizeHandler>,\r\n default: '',\r\n },\r\n },\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.resize-handler {\r\n position: absolute;\r\n width: 10px;\r\n height: 10px;\r\n left: 0;\r\n top: 0;\r\n margin: -5px 0 0 -5px;\r\n border: 1px solid $themeColor;\r\n background-color: #fff;\r\n border-radius: 1px;\r\n\r\n &.left-top {\r\n cursor: nwse-resize;\r\n }\r\n &.top {\r\n cursor: ns-resize;\r\n }\r\n &.right-top {\r\n cursor: nesw-resize;\r\n }\r\n &.left {\r\n cursor: ew-resize;\r\n }\r\n &.right {\r\n cursor: ew-resize;\r\n }\r\n &.left-bottom {\r\n cursor: nesw-resize;\r\n }\r\n &.bottom {\r\n cursor: ns-resize;\r\n }\r\n &.right-bottom {\r\n cursor: nwse-resize;\r\n }\r\n}\r\n</style>","\r\nimport { PropType } from 'vue'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\n\r\nexport default {\r\n name: 'resize-handler',\r\n props: {\r\n type: {\r\n type: String as PropType<OperateResizeHandler>,\r\n default: '',\r\n },\r\n },\r\n}\r\n","import { render } from \"./ResizeHandler.vue?vue&type=template&id=1c2a68d0&scoped=true\"\nimport script from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ResizeHandler.vue?vue&type=style&index=0&id=1c2a68d0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1c2a68d0\"\n\nexport default script","<template>\r\n <div :class=\"['border-line', type, { 'wide': isWide }]\"></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType } from 'vue'\r\nimport { OperateBorderLine } from '@/types/edit'\r\n\r\nexport default {\r\n name: 'border-line',\r\n props: {\r\n type: {\r\n type: String as PropType<OperateBorderLine>,\r\n required: true,\r\n },\r\n isWide: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.border-line {\r\n position: absolute;\r\n width: 0;\r\n height: 0;\r\n left: 0;\r\n top: 0;\r\n border: 0 dashed $themeColor;\r\n\r\n &.top {\r\n border-top-width: 1px;\r\n }\r\n &.bottom {\r\n border-bottom-width: 1px;\r\n }\r\n &.left {\r\n border-left-width: 1px;\r\n }\r\n &.right {\r\n border-right-width: 1px;\r\n }\r\n\r\n &.wide {\r\n &::before {\r\n content: '';\r\n position: absolute;\r\n background: transparent;\r\n cursor: move;\r\n }\r\n\r\n &.top::before {\r\n top: -8px;\r\n left: -8px;\r\n width: calc(100% + 16px);\r\n height: 16px;\r\n }\r\n &.bottom::before {\r\n bottom: -8px;\r\n left: -8px;\r\n width: calc(100% + 16px);\r\n height: 16px;\r\n }\r\n &.left::before {\r\n top: -8px;\r\n left: -8px;\r\n width: 16px;\r\n height: calc(100% + 16px);\r\n }\r\n &.right::before {\r\n top: -8px;\r\n right: -8px;\r\n width: 16px;\r\n height: calc(100% + 16px);\r\n }\r\n }\r\n}\r\n</style>","\r\nimport { PropType } from 'vue'\r\nimport { OperateBorderLine } from '@/types/edit'\r\n\r\nexport default {\r\n name: 'border-line',\r\n props: {\r\n type: {\r\n type: String as PropType<OperateBorderLine>,\r\n required: true,\r\n },\r\n isWide: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n","import { render } from \"./BorderLine.vue?vue&type=template&id=630e246b&scoped=true\"\nimport script from \"./BorderLine.vue?vue&type=script&lang=ts\"\nexport * from \"./BorderLine.vue?vue&type=script&lang=ts\"\n\nimport \"./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-630e246b\"\n\nexport default script","\r\nimport { computed, defineComponent, reactive, PropType, watchEffect, toRefs } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { getElementListRange } from '@/utils/element'\r\nimport { OperateResizeHandler, MultiSelectRange } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'multi-select-operate',\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementList: {\r\n type: Array as PropType<PPTElement[]>,\r\n required: true,\r\n },\r\n scaleMultiElement: {\r\n type: Function as PropType<(e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))\r\n\r\n const range = reactive({\r\n minX: 0,\r\n maxX: 0,\r\n minY: 0,\r\n maxY: 0,\r\n })\r\n\r\n // 根据多选元素整体在画布中的范围,计算边框线和缩放点的位置信息\r\n const width = computed(() => (range.maxX - range.minX) * canvasScale.value)\r\n const height = computed(() => (range.maxY - range.minY) * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(width, height)\r\n\r\n // 计算多选元素整体在画布中的范围\r\n const setRange = () => {\r\n const { minX, maxX, minY, maxY } = getElementListRange(localActiveElementList.value)\r\n range.minX = minX\r\n range.maxX = maxX\r\n range.minY = minY\r\n range.maxY = maxY\r\n }\r\n watchEffect(setRange)\r\n\r\n // 禁用多选状态下缩放:仅未旋转的图片和形状可以在多选状态下缩放\r\n const disableResize = computed(() => {\r\n return localActiveElementList.value.some(item => {\r\n if (\r\n (item.type === 'image' || item.type === 'shape') && \r\n !item.rotate\r\n ) return false\r\n return true\r\n })\r\n })\r\n\r\n return {\r\n ...toRefs(range),\r\n canvasScale,\r\n borderLines,\r\n disableResize,\r\n resizeHandlers,\r\n }\r\n },\r\n})\r\n","import { render } from \"./MultiSelectOperate.vue?vue&type=template&id=4def6455&scoped=true\"\nimport script from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiSelectOperate.vue?vue&type=style&index=0&id=4def6455&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4def6455\"\n\nexport default script","<template>\r\n <div\r\n class=\"operate\"\r\n :class=\"{ 'multi-select': isMultiSelect && !isActive }\"\r\n :style=\"{\r\n top: elementInfo.top * canvasScale + 'px',\r\n left: elementInfo.left * canvasScale + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n transformOrigin: `${elementInfo.width * canvasScale / 2}px ${elementInfo.height * canvasScale / 2}px`,\r\n }\"\r\n >\r\n <component\r\n v-if=\"isSelected\"\r\n :is=\"currentOperateComponent\"\r\n :elementInfo=\"elementInfo\"\r\n :isActiveGroupElement=\"isActiveGroupElement\"\r\n :isMultiSelect=\"isMultiSelect\"\r\n :rotateElement=\"rotateElement\"\r\n :scaleElement=\"scaleElement\"\r\n :dragLineElement=\"dragLineElement\"\r\n ></component>\r\n\r\n <div \r\n class=\"animation-index\"\r\n v-if=\"toolbarState === 'elAnimation' && elementIndexInAnimation !== -1\"\r\n >\r\n {{elementIndexInAnimation + 1}}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\nimport { OperateLineHandler, OperateResizeHandler } from '@/types/edit'\r\n\r\nimport ImageElementOperate from './ImageElementOperate.vue'\r\nimport TextElementOperate from './TextElementOperate.vue'\r\nimport ShapeElementOperate from './ShapeElementOperate.vue'\r\nimport LineElementOperate from './LineElementOperate.vue'\r\nimport ChartElementOperate from './ChartElementOperate.vue'\r\nimport TableElementOperate from './TableElementOperate.vue'\r\n\r\nexport default defineComponent({\r\n name: 'operate',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n isSelected: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActive: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const currentOperateComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElementOperate,\r\n [ElementTypes.TEXT]: TextElementOperate,\r\n [ElementTypes.SHAPE]: ShapeElementOperate,\r\n [ElementTypes.LINE]: LineElementOperate,\r\n [ElementTypes.CHART]: ChartElementOperate,\r\n [ElementTypes.TABLE]: TableElementOperate,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const elementIndexInAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n return animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n })\r\n\r\n return {\r\n currentOperateComponent,\r\n canvasScale,\r\n toolbarState,\r\n elementIndexInAnimation,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.operate {\r\n position: absolute;\r\n z-index: 100;\r\n user-select: none;\r\n\r\n &.multi-select {\r\n opacity: 0;\r\n }\r\n}\r\n.animation-index {\r\n position: absolute;\r\n top: 0;\r\n left: -24px;\r\n font-size: 12px;\r\n width: 18px;\r\n height: 18px;\r\n background-color: #fff;\r\n color: $themeColor;\r\n border: 1px solid $themeColor;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n margin-bottom: 3px;\r\n}\r\n</style>","<template>\r\n <div class=\"image-element-operate\" :class=\"{ 'cliping': isCliping }\">\r\n <BorderLine \r\n class=\"operate-border-line\"\r\n v-for=\"line in borderLines\" \r\n :key=\"line.type\" \r\n :type=\"line.type\" \r\n :style=\"line.style\"\r\n />\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in resizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => scaleElement($event, elementInfo, point.direction)\"\r\n />\r\n <RotateHandler\r\n class=\"operate-rotate-handler\" \r\n :style=\"{ left: scaleWidth / 2 + 'px' }\"\r\n @mousedown.stop=\"rotateElement(elementInfo)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTImageElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n isCliping,\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.image-element-operate.cliping {\r\n visibility: hidden;\r\n}\r\n</style>","<template>\r\n <div class=\"rotate-handler\"></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'rotate-handler',\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.rotate-handler {\r\n position: absolute;\r\n width: 10px;\r\n height: 10px;\r\n top: -25px;\r\n margin-left: -5px;\r\n border: 1px solid $themeColor;\r\n background-color: #fff;\r\n border-radius: 1px;\r\n cursor: grab;\r\n\r\n &:active {\r\n cursor: grabbing;\r\n }\r\n}\r\n</style>","\r\nexport default {\r\n name: 'rotate-handler',\r\n}\r\n","import { render } from \"./RotateHandler.vue?vue&type=template&id=9a549510&scoped=true\"\nimport script from \"./RotateHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./RotateHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./RotateHandler.vue?vue&type=style&index=0&id=9a549510&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-9a549510\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTImageElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n isCliping,\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageElementOperate.vue?vue&type=template&id=5b0628aa&scoped=true\"\nimport script from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageElementOperate.vue?vue&type=style&index=0&id=5b0628aa&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b0628aa\"\n\nexport default script","<template>\r\n <div class=\"text-element-operate\">\r\n <BorderLine \r\n class=\"operate-border-line\"\r\n v-for=\"line in borderLines\" \r\n :key=\"line.type\" \r\n :type=\"line.type\" \r\n :style=\"line.style\"\r\n />\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in textElementResizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => scaleElement($event, elementInfo, point.direction)\"\r\n />\r\n <RotateHandler\r\n class=\"operate-rotate-handler\" \r\n :style=\"{ left: scaleWidth / 2 + 'px' }\"\r\n @mousedown.stop=\"rotateElement(elementInfo)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTTextElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTTextElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TextElementOperate.vue?vue&type=template&id=1f730982\"\nimport script from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div class=\"shape-element-operate\">\r\n <BorderLine \r\n class=\"operate-border-line\"\r\n v-for=\"line in borderLines\" \r\n :key=\"line.type\" \r\n :type=\"line.type\" \r\n :style=\"line.style\"\r\n />\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in resizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => scaleElement($event, elementInfo, point.direction)\"\r\n />\r\n <RotateHandler\r\n class=\"operate-rotate-handler\" \r\n :style=\"{ left: scaleWidth / 2 + 'px' }\"\r\n @mousedown.stop=\"rotateElement(elementInfo)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'shape-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTShapeElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'shape-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTShapeElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ShapeElementOperate.vue?vue&type=template&id=bfcf602e\"\nimport script from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div class=\"text-element-operate\">\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in resizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => dragLineElement($event, elementInfo, point.handler)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const resizeHandlers = computed(() => {\r\n return [\r\n {\r\n handler: OperateLineHandlers.START,\r\n style: {\r\n left: props.elementInfo.start[0] * canvasScale.value + 'px',\r\n top: props.elementInfo.start[1] * canvasScale.value + 'px',\r\n }\r\n },\r\n {\r\n handler: OperateLineHandlers.END,\r\n style: {\r\n left: props.elementInfo.end[0] * canvasScale.value + 'px',\r\n top: props.elementInfo.end[1] * canvasScale.value + 'px',\r\n }\r\n },\r\n ]\r\n })\r\n\r\n return {\r\n resizeHandlers,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const resizeHandlers = computed(() => {\r\n return [\r\n {\r\n handler: OperateLineHandlers.START,\r\n style: {\r\n left: props.elementInfo.start[0] * canvasScale.value + 'px',\r\n top: props.elementInfo.start[1] * canvasScale.value + 'px',\r\n }\r\n },\r\n {\r\n handler: OperateLineHandlers.END,\r\n style: {\r\n left: props.elementInfo.end[0] * canvasScale.value + 'px',\r\n top: props.elementInfo.end[1] * canvasScale.value + 'px',\r\n }\r\n },\r\n ]\r\n })\r\n\r\n return {\r\n resizeHandlers,\r\n }\r\n },\r\n})\r\n","import { render } from \"./LineElementOperate.vue?vue&type=template&id=670e07f8\"\nimport script from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div class=\"chart-element-operate\">\r\n <BorderLine \r\n class=\"operate-border-line\"\r\n v-for=\"line in borderLines\" \r\n :key=\"line.type\" \r\n :type=\"line.type\" \r\n :style=\"line.style\"\r\n />\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in resizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => scaleElement($event, elementInfo, point.direction)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ChartElementOperate.vue?vue&type=template&id=4218643e\"\nimport script from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div class=\"table-element-operate\">\r\n <BorderLine \r\n class=\"operate-border-line\"\r\n v-for=\"line in borderLines\" \r\n :key=\"line.type\" \r\n :type=\"line.type\" \r\n :style=\"line.style\"\r\n />\r\n <template v-if=\"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)\">\r\n <ResizeHandler\r\n class=\"operate-resize-handler\" \r\n v-for=\"point in textElementResizeHandlers\"\r\n :key=\"point.direction\"\r\n :type=\"point.direction\"\r\n :style=\"point.style\"\r\n @mousedown.stop=\"$event => scaleElement($event, elementInfo, point.direction)\"\r\n />\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTableElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const outlineWidth = computed(() => props.elementInfo.outline.width || 1)\r\n\r\n const scaleWidth = computed(() => (props.elementInfo.width + outlineWidth.value) * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n</script>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTableElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const outlineWidth = computed(() => props.elementInfo.outline.width || 1)\r\n\r\n const scaleWidth = computed(() => (props.elementInfo.width + outlineWidth.value) * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TableElementOperate.vue?vue&type=template&id=459ab724\"\nimport script from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\nimport { OperateLineHandler, OperateResizeHandler } from '@/types/edit'\r\n\r\nimport ImageElementOperate from './ImageElementOperate.vue'\r\nimport TextElementOperate from './TextElementOperate.vue'\r\nimport ShapeElementOperate from './ShapeElementOperate.vue'\r\nimport LineElementOperate from './LineElementOperate.vue'\r\nimport ChartElementOperate from './ChartElementOperate.vue'\r\nimport TableElementOperate from './TableElementOperate.vue'\r\n\r\nexport default defineComponent({\r\n name: 'operate',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n isSelected: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActive: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const currentOperateComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElementOperate,\r\n [ElementTypes.TEXT]: TextElementOperate,\r\n [ElementTypes.SHAPE]: ShapeElementOperate,\r\n [ElementTypes.LINE]: LineElementOperate,\r\n [ElementTypes.CHART]: ChartElementOperate,\r\n [ElementTypes.TABLE]: TableElementOperate,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const elementIndexInAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n return animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n })\r\n\r\n return {\r\n currentOperateComponent,\r\n canvasScale,\r\n toolbarState,\r\n elementIndexInAnimation,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=558a94fe&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=558a94fe&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-558a94fe\"\n\nexport default script","\r\nimport { computed, defineComponent, provide, ref, watch, watchEffect } from 'vue'\r\nimport throttle from 'lodash/throttle'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { AlignmentLineProps } from '@/types/edit'\r\nimport { removeAllRanges } from '@/utils/selection'\r\n\r\nimport useViewportSize from './hooks/useViewportSize'\r\nimport useMouseSelection from './hooks/useMouseSelection'\r\nimport useDropImageOrText from './hooks/useDropImageOrText'\r\nimport useRotateElement from './hooks/useRotateElement'\r\nimport useScaleElement from './hooks/useScaleElement'\r\nimport useSelectElement from './hooks/useSelectElement'\r\nimport useDragElement from './hooks/useDragElement'\r\nimport useDragLineElement from './hooks/useDragLineElement'\r\nimport useInsertFromCreateSelection from './hooks/useInsertFromCreateSelection'\r\n\r\nimport useDeleteElement from '@/hooks/useDeleteElement'\r\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\r\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\r\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport EditableElement from './EditableElement.vue'\r\nimport MouseSelection from './MouseSelection.vue'\r\nimport SlideBackground from './SlideBackground.vue'\r\nimport AlignmentLine from './AlignmentLine.vue'\r\nimport ElementCreateSelection from './ElementCreateSelection.vue'\r\nimport MultiSelectOperate from './Operate/MultiSelectOperate.vue'\r\nimport Operate from './Operate/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor-canvas',\r\n components: {\r\n EditableElement,\r\n MouseSelection,\r\n SlideBackground,\r\n AlignmentLine,\r\n ElementCreateSelection,\r\n MultiSelectOperate,\r\n Operate,\r\n },\r\n setup() {\r\n const store = useStore()\r\n\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const handleElementId = computed(() => store.state.handleElementId)\r\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\r\n const ctrlKeyState = computed(() => store.state.ctrlKeyState)\r\n const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)\r\n\r\n const viewportRef = ref<HTMLElement>()\r\n const alignmentLines = ref<AlignmentLineProps[]>([])\r\n\r\n const activeGroupElementId = ref('')\r\n watch(handleElementId, () => activeGroupElementId.value = '')\r\n\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n const elementList = ref<PPTElement[]>([])\r\n const setLocalElementList = () => {\r\n elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []\r\n }\r\n watchEffect(setLocalElementList)\r\n\r\n const canvasRef = ref<HTMLElement>()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const { viewportStyles } = useViewportSize(canvasRef)\r\n\r\n useDropImageOrText(canvasRef)\r\n\r\n const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef)\r\n\r\n const { dragElement } = useDragElement(elementList, activeGroupElementId, alignmentLines)\r\n const { dragLineElement } = useDragLineElement(elementList)\r\n const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)\r\n const { scaleElement, scaleMultiElement } = useScaleElement(elementList, activeGroupElementId, alignmentLines)\r\n const { rotateElement } = useRotateElement(elementList, viewportRef)\r\n\r\n const { selectAllElement } = useSelectAllElement()\r\n const { deleteAllElements } = useDeleteElement()\r\n const { pasteElement } = useCopyAndPasteElement()\r\n const { enterScreening } = useScreening()\r\n\r\n // 点击画布的空白区域:清空焦点元素、设置画布焦点、清除文字选区\r\n const handleClickBlankArea = (e: MouseEvent) => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n if (!ctrlOrShiftKeyActive.value) updateMouseSelection(e)\r\n if (!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\r\n removeAllRanges()\r\n }\r\n\r\n // 移除画布编辑区域焦点\r\n const removeEditorAreaFocus = () => {\r\n if (editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)\r\n }\r\n\r\n // 按住Ctrl键滚动鼠标缩放画布\r\n const { scaleCanvas } = useScaleCanvas()\r\n const throttleScaleCanvas = throttle(scaleCanvas, 100, { leading: true, trailing: false })\r\n\r\n const mousewheelScaleCanvas = (e: WheelEvent) => {\r\n if (!ctrlKeyState.value) return\r\n\r\n e.preventDefault()\r\n if (e.deltaY > 0) throttleScaleCanvas('-')\r\n else if (e.deltaY < 0) throttleScaleCanvas('+')\r\n }\r\n\r\n // 开关网格线\r\n const showGridLines = computed(() => store.state.showGridLines)\r\n const toggleGridLines = () => {\r\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\r\n }\r\n\r\n // 在鼠标绘制的范围插入元素\r\n const creatingElement = computed(() => store.state.creatingElement)\r\n const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteElement,\r\n },\r\n {\r\n text: '全选',\r\n subText: 'Ctrl + A',\r\n handler: selectAllElement,\r\n },\r\n {\r\n text: '网格线',\r\n subText: showGridLines.value ? '√' : '',\r\n handler: toggleGridLines,\r\n },\r\n {\r\n text: '重置当前页',\r\n handler: deleteAllElements,\r\n },\r\n { divider: true },\r\n {\r\n text: '从当前页演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n provide('slideScale', canvasScale)\r\n\r\n return {\r\n elementList,\r\n activeElementIdList,\r\n handleElementId,\r\n activeGroupElementId,\r\n canvasRef,\r\n viewportRef,\r\n viewportStyles,\r\n canvasScale,\r\n mouseSelectionState,\r\n handleClickBlankArea,\r\n removeEditorAreaFocus,\r\n currentSlide,\r\n creatingElement,\r\n insertElementFromCreateSelection,\r\n alignmentLines,\r\n selectElement,\r\n rotateElement,\r\n scaleElement,\r\n dragLineElement,\r\n scaleMultiElement,\r\n mousewheelScaleCanvas,\r\n contextmenus,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=0214a634&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0214a634&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0214a634\"\n\nexport default script","<template>\r\n <div class=\"canvas-tool\">\r\n <div class=\"left-handler\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"撤销\">\r\n <IconBack class=\"handler-item\" :class=\"{ 'disable': !canUndo }\" @click=\"undo()\" />\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"重做\">\r\n <IconNext class=\"handler-item\" :class=\"{ 'disable': !canRedo }\" @click=\"redo()\" />\r\n </Tooltip>\r\n </div>\r\n\r\n <div class=\"add-element-handler\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入文字\">\r\n <IconFontSize class=\"handler-item\" @click=\"drawText()\" />\r\n </Tooltip>\r\n <FileInput @change=\"files => insertImageElement(files)\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入图片\">\r\n <IconPicture class=\"handler-item\" />\r\n </Tooltip>\r\n </FileInput>\r\n <Popover trigger=\"click\" v-model:visible=\"shapePoolVisible\">\r\n <template #content>\r\n <ShapePool @select=\"shape => drawShape(shape)\" />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入形状\">\r\n <IconPentagonOne class=\"handler-item\" />\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\" v-model:visible=\"linePoolVisible\">\r\n <template #content>\r\n <LinePool @select=\"line => drawLine(line)\" />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入线条\">\r\n <IconConnection class=\"handler-item\" />\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\" v-model:visible=\"chartPoolVisible\">\r\n <template #content>\r\n <ChartPool @select=\"chart => { createChartElement(chart); chartPoolVisible = false }\" />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入图表\">\r\n <IconChartProportion class=\"handler-item\" />\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\" v-model:visible=\"tableGeneratorVisible\">\r\n <template #content>\r\n <TableGenerator\r\n @close=\"tableGeneratorVisible = false\"\r\n @insert=\"({ row, col }) => { createTableElement(row, col); tableGeneratorVisible = false }\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"插入表格\">\r\n <IconInsertTable class=\"handler-item\" />\r\n </Tooltip>\r\n </Popover>\r\n </div>\r\n\r\n <div class=\"right-handler\">\r\n <IconMinus class=\"handler-item viewport-size\" @click=\"scaleCanvas('-')\" />\r\n <span class=\"text\">{{canvasScalePercentage}}</span>\r\n <IconPlus class=\"handler-item viewport-size\" @click=\"scaleCanvas('+')\" />\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"适配屏幕\">\r\n <IconFullScreen class=\"handler-item viewport-size-adaptation\" @click=\"setCanvasPercentage(90)\" />\r\n </Tooltip>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, computed, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\nimport useCreateElement from '@/hooks/useCreateElement'\r\n\r\nimport ShapePool from './ShapePool.vue'\r\nimport LinePool from './LinePool.vue'\r\nimport ChartPool from './ChartPool.vue'\r\nimport TableGenerator from './TableGenerator.vue'\r\n\r\nexport default defineComponent({\r\n name: 'canvas-tool',\r\n components: {\r\n ShapePool,\r\n LinePool,\r\n ChartPool,\r\n TableGenerator,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const canUndo = computed(() => store.getters.canUndo)\r\n const canRedo = computed(() => store.getters.canRedo)\r\n\r\n const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')\r\n\r\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\r\n const { redo, undo } = useHistorySnapshot()\r\n\r\n const { createImageElement, createChartElement, createTableElement } = useCreateElement()\r\n\r\n const insertImageElement = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\r\n }\r\n\r\n const shapePoolVisible = ref(false)\r\n const linePoolVisible = ref(false)\r\n const chartPoolVisible = ref(false)\r\n const tableGeneratorVisible = ref(false)\r\n\r\n // 绘制文字范围\r\n const drawText = () => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'text',\r\n data: null,\r\n })\r\n }\r\n\r\n // 绘制形状范围\r\n const drawShape = (shape: ShapePoolItem) => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'shape',\r\n data: shape,\r\n })\r\n shapePoolVisible.value = false\r\n }\r\n\r\n // 绘制线条路径\r\n const drawLine = (line: LinePoolItem) => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'line',\r\n data: line,\r\n })\r\n linePoolVisible.value = false\r\n }\r\n\r\n return {\r\n scaleCanvas,\r\n setCanvasPercentage,\r\n canvasScalePercentage,\r\n canUndo,\r\n canRedo,\r\n redo,\r\n undo,\r\n insertImageElement,\r\n shapePoolVisible,\r\n linePoolVisible,\r\n chartPoolVisible,\r\n tableGeneratorVisible,\r\n drawText,\r\n drawShape,\r\n drawLine,\r\n createChartElement,\r\n createTableElement,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.canvas-tool {\r\n position: relative;\r\n border-bottom: 1px solid $borderColor;\r\n background-color: #fff;\r\n display: flex;\r\n justify-content: space-between;\r\n padding: 0 10px;\r\n font-size: 13px;\r\n user-select: none;\r\n}\r\n.left-handler {\r\n display: flex;\r\n align-items: center;\r\n}\r\n.add-element-handler {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n display: flex;\r\n}\r\n.handler-item {\r\n margin: 0 10px;\r\n cursor: pointer;\r\n\r\n &.disable {\r\n opacity: .5;\r\n }\r\n}\r\n.right-handler {\r\n display: flex;\r\n align-items: center;\r\n\r\n .text {\r\n width: 40px;\r\n text-align: center;\r\n }\r\n\r\n .viewport-size {\r\n font-size: 12px;\r\n margin-top: -1px;\r\n }\r\n}\r\n</style>","<template>\r\n <div class=\"shape-pool\">\r\n <div class=\"category\" v-for=\"item in shapeList\" :key=\"item.type\">\r\n <div class=\"category-name\">{{item.type}}</div>\r\n <div class=\"shape-list\">\r\n <div class=\"shape-item\" v-for=\"(shape, index) in item.children\" :key=\"index\">\r\n <div class=\"shape-content\" @click=\"selectShape(shape)\">\r\n <SvgWrapper \r\n overflow=\"visible\" \r\n width=\"18\"\r\n height=\"18\"\r\n >\r\n <g \r\n :transform=\"`scale(${18 / shape.viewBox}, ${18 / shape.viewBox}) translate(0,0) matrix(1,0,0,1,0,0)`\"\r\n >\r\n <path \r\n class=\"shape-path\"\r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin\r\n fill=\"transparent\"\r\n stroke=\"#999\"\r\n stroke-width=\"2\" \r\n :d=\"shape.path\"\r\n ></path>\r\n </g>\r\n </SvgWrapper>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent } from 'vue'\r\nimport { SHAPE_LIST, ShapePoolItem } from '@/configs/shapes'\r\n\r\nexport default defineComponent({\r\n name: 'shape-pool',\r\n setup(props, { emit }) {\r\n const shapeList = SHAPE_LIST\r\n\r\n const selectShape = (shape: ShapePoolItem) => {\r\n emit('select', shape)\r\n }\r\n\r\n return {\r\n shapeList,\r\n selectShape,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.shape-pool {\r\n width: 340px;\r\n max-height: 540px;\r\n overflow: auto;\r\n margin-bottom: -12px;\r\n margin-right: -12px;\r\n padding-right: 12px;\r\n}\r\n.category-name {\r\n width: 100%;\r\n font-size: 13px;\r\n margin-bottom: 10px;\r\n border-left: 4px solid #aaa;\r\n background-color: #eee;\r\n padding: 2px 0 2px 10px;\r\n}\r\n.shape-list {\r\n @include flex-grid-layout();\r\n\r\n margin-bottom: 10px;\r\n}\r\n.shape-item {\r\n @include flex-grid-layout-children(10, 8%);\r\n\r\n height: 0;\r\n padding-bottom: 8%;\r\n flex-shrink: 0;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n.shape-content {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n\r\n &:hover .shape-path {\r\n stroke: $themeColor;\r\n }\r\n\r\n svg:not(:root) {\r\n overflow: visible;\r\n }\r\n}\r\n</style>","export interface ShapePoolItem {\r\n viewBox: number;\r\n path: string;\r\n}\r\n\r\nexport const SHAPE_LIST = [\r\n {\r\n type: '矩形',\r\n children: [\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z'\r\n },\r\n ]\r\n },\r\n\r\n {\r\n type: '常用形状',\r\n children: [\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 100 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 200 0 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 200 0 Q 200 200 0 200 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 200 L 200 200 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 0 200 L 200 200 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 50 0 L 200 0 L 150 200 L 0 200 L 50 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 150 0 L 200 200 L 50 200 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 50 0 L 150 0 L 200 200 L 0 200 L 50 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 100 L 100 200 L 200 100 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 90 L 50 200 L 150 200 L 200 90 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 60 L 0 140 L 100 200 L 200 140 L 200 60 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 60 0 L 140 0 L 200 60 L 200 140 L 140 200 L 60 200 L 0 140 L 0 60 L 60 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 75 0 L 125 0 L 175 25 L 200 75 L 200 125 L 175 175 L 125 200 L 75 200 L 25 175 L 0 125 L 0 75 L 25 25 L 75 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 50 L 0 200 L 200 200 L 200 50 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 L 0 0 L 150 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 A 50 100 0 0 0 0 0 L 150 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 100 L 150 0 L 0 0 L 50 100 L 0 200 L 150 200 L 200 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 0 L 200 200 L 0 200 L 0 100 L 200 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 200 100 L 200 200 L 0 200 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 0 L 100 0 L 0 100 L 0 200 L 200 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 50 0 L 150 0 L 150 50 L 200 50 L 200 150 L 150 150 L 150 200 L 50 200 L 50 150 L 0 150 L 0 50 L 50 50 L 50 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 0 200 L 200 200 L 200 140 L 60 140 L 60 0 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M0 0 L200 0 L200 200 L0 200 L0 0 Z M50 50 L50 150 L150 150 L150 50 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M0 100 A100 100 0 1 1 0 101 Z M150 100 A50 50 0 1 0 150 101 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 70 0 L 70 70 L 0 70 L 0 130 L 70 130 L 70 200 L 130 200 L 130 130 L 200 130 L 200 70 L 130 70 L 130 0 L 70 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 40 0 L 0 40 L 60 100 L 0 160 L 40 200 L 100 140 L 160 200 L 200 160 L 140 100 L 200 40 L 160 0 L 100 60 L 40 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 200 0 L 200 160 L 100 160 L 60 200 L 60 160 L 0 160 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 40 Q 0 0 40 0 L 160 0 Q 200 0 200 40 L 200 120 Q 200 160 160 160 L 100 160 L 60 200 L 60 160 L 40 160 Q 0 160 0 120 L 0 40 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 180 160 A 100 100 0 1 0 100 200 L 200 200 L 200 160 L 180 160 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 0 L 0 0 L 200 200 L 0 200 L 200 0 Z'\r\n },\r\n ],\r\n },\r\n \r\n {\r\n type: '箭头',\r\n children: [\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 100 L 50 100 L 50 200 L 150 200 L 150 100 L 200 100 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 200 L 200 100 L 150 100 L 150 0 L 50 0 L 50 100 L 0 100 L 100 200 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 200 150 L 100 150 L 100 200 L 0 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 0 150 L 100 150 L 100 200 L 200 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 0 60 L 60 60 L 60 140 L 0 140 L 100 200 L 200 140 L 140 140 L 140 60 L 200 60 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 100 L 60 0 L 60 60 L 140 60 L 140 0 L 200 100 L 140 200 L 140 140 L 60 140 L 60 200 L 0 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 100 0 L 60 40 L 80 40 L 80 80 L 40 80 L 40 60 L 0 100 L 40 140 L 40 120 L 80 120 L 80 160 L 60 160 L 100 200 L 140 160 L 120 160 L 120 120 L 160 120 L 160 140 L 200 100 L 160 60 L 160 80 L 120 80 L 120 40 L 140 40 L 100 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 150 100 L 200 150 L 100 150 L 100 200 L 0 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 50 100 L 0 150 L 100 150 L 100 200 L 200 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 100 L 80 20 L 80 80 L 120 80 L 120 0 L 200 0 L 200 200 L 120 200 L 120 120 L 80 120 L 80 180 L 0 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 100 L 120 20 L 120 80 L 80 80 L 80 0 L 0 0 L 0 200 L 80 200 L 80 120 L 120 120 L 120 180 L 200 100 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 120 0 L 200 100 L 120 200 L 0 200 L 80 100 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 80 0 L 200 0 L 120 100 L 200 200 L 80 200 L 0 100 L 80 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 140 0 L 200 100 L 140 200 L 0 200 L 0 100 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 60 0 L 200 0 L 200 100 L 200 200 L 60 200 L 0 100 L 60 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 200 100 L 0 200 L 60 100 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 0 L 0 100 L 200 200 L 140 100 L 200 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 0 L 80 0 L 200 100 L 80 200 L 0 200 L 120 100 L 0 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 200 0 L 120 0 L 0 100 L 120 200 L 200 200 L 80 100 L 200 0 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 200 L 180 200 L 180 40 L 200 40 L 160 0 L 120 40 L 140 40 L 140 160 L 0 160 L 0 200 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 0 200 L 0 20 L 160 20 L 160 0 L 200 40 L 160 80 L 160 60 L 40 60 L 40 200 L 0 200 Z'\r\n },\r\n {\r\n viewBox: 200,\r\n path: 'M 40 180 L 180 180 L 180 40 L 200 40 L 160 0 L 120 40 L 140 40 L 140 140 L 40 140 L 40 120 L 0 160 L 40 200 L 40 180 Z'\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M398.208 302.912V64L0 482.112l398.208 418.176V655.36c284.48 0 483.584 95.552 625.792 304.64-56.896-298.688-227.584-597.312-625.792-657.088z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M625.792 302.912V64L1024 482.112l-398.208 418.176V655.36C341.312 655.36 142.208 750.912 0 960c56.896-298.688 227.584-597.312 625.792-657.088z',\r\n },\r\n ],\r\n },\r\n\r\n {\r\n type: '其他形状',\r\n children: [\r\n {\r\n viewBox: 1024,\r\n path: 'M995.336 243.4016c-15.7584-36.5736-38.3376-69.26639999-66.91440001-97.37280001-28.5768-27.98879999-61.73999999-49.8624-98.78399999-65.26799998-38.22-15.876-78.6744-23.8728-120.4224-23.87280001-57.97680001 0-114.5424 15.876-163.69919999 45.864-11.76 7.17360001-22.932 15.05279999-33.51600001 23.63760001-10.584-8.5848-21.75600001-16.46400001-33.51600001-23.63760001-49.1568-29.98799999-105.7224-45.86399999-163.69919999-45.864-41.74799999 0-82.2024 7.9968-120.4224 23.87280001-36.9264 15.28799999-70.2072 37.27919999-98.78399999 65.26799998-28.6944 28.10640001-51.156 60.79919999-66.91440001 97.37280001-16.34639999 37.9848-24.696 78.3216-24.696 119.83439999 0 39.1608 7.9968 79.96800001 23.8728 121.48080001 13.28880001 34.692 32.34000001 70.67760001 56.6832 107.016 38.57279999 57.5064 91.61040001 117.4824 157.4664 178.28160001 109.1328 100.78319999 217.2072 170.4024 221.79359999 173.22479998l27.87120001 17.8752c12.348 7.8792 28.224 7.8792 40.572 0l27.87119999-17.8752c4.58639999-2.94 112.54319999-72.44159999 221.79360001-173.22479998 65.85599999-60.79919999 118.89359999-120.7752 157.4664-178.28160001 24.3432-36.33839999 43.512-72.324 56.68319999-107.016 15.876-41.5128 23.8728-82.32 23.87280001-121.48080001 0.1176-41.5128-8.232-81.8496-24.5784-119.83439999z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M985.20746667 343.50079998l-303.32586667-44.08319999L546.28693333 24.5248c-3.70346666-7.5264-9.79626667-13.6192-17.32266665-17.32266668-18.87573334-9.3184-41.81333333-1.55306667-51.25120001 17.32266668L342.1184 299.41759999l-303.32586667 44.08319999c-8.36266667 1.19466667-16.00853333 5.13706667-21.8624 11.11040001-14.69440001 15.17226667-14.45546667 39.30453334 0.71679999 54.1184l219.46026668 213.9648-51.84853333 302.1312c-1.43359999 8.24320001-0.11946667 16.8448 3.82293333 24.25173333 9.79626667 18.6368 32.9728 25.92426667 51.6096 16.00853334L512 822.44266665l271.3088 142.64320001c7.40693333 3.9424 16.00853333 5.25653333 24.25173333 3.82293333 20.78719999-3.584 34.7648-23.296 31.1808-44.0832l-51.84853333-302.1312 219.46026668-213.9648c5.97333334-5.85386666 9.91573333-13.49973334 11.11039999-21.8624 3.2256-20.90666667-11.34933333-40.26026667-32.256-43.36640001z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M852.65066667 405.84533333C800.54044445 268.40177778 667.76177778 170.66666667 512.22755555 170.66666667S223.91466667 268.288 171.80444445 405.73155555C74.29688889 431.33155555 2.27555555 520.07822222 2.27555555 625.77777778c0 125.72444445 101.83111111 227.55555555 227.44177778 227.55555555h564.56533334C919.89333333 853.33333333 1021.72444445 751.50222222 1021.72444445 625.77777778c0-105.472-71.79377778-194.21866667-169.07377778-219.93244445z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M926.25224691 323.7371485H654.6457886L898.88200917 15.14388241c5.05486373-6.53433603 0.49315743-16.02761669-7.76722963-16.02761668H418.30008701c-3.45210206 0-6.78091476 1.84934039-8.50696579 4.93157436L90.35039154 555.76772251c-3.82197013 6.53433603 0.86302552 14.7947231 8.50696578 14.79472311h215.01664245l-110.22068713 440.88274851c-2.34249783 9.61657002 9.24670194 16.39748478 16.39748477 9.49328065L933.03316167 340.62779071c6.41104668-6.0411786 2.09591911-16.8906422-6.78091476-16.89064221z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M878.47822222 463.30311111c-22.18666667-49.83466667-53.93066667-93.98044445-94.32177777-131.072l-33.10933334-30.37866666c-4.89244445-4.32355555-12.62933333-2.38933333-14.79111111 3.75466666l-14.79111111 42.43911111c-9.216 26.624-26.16888889 53.81688889-50.176 80.55466667-1.59288889 1.70666667-3.41333333 2.16177778-4.66488889 2.27555556-1.25155555 0.11377778-3.18577778-0.11377778-4.89244445-1.70666667-1.59288889-1.36533333-2.38933333-3.41333333-2.27555555-5.46133333 4.20977778-68.49422222-16.27022222-145.74933333-61.09866667-229.83111112C561.26577778 124.01777778 509.72444445 69.51822222 445.32622222 31.51644445l-46.99022222-27.648c-6.144-3.64088889-13.99466667 1.13777778-13.65333333 8.30577777l2.50311111 54.61333333c1.70666667 37.31911111-2.61688889 70.31466667-12.85688889 97.73511112-12.51555555 33.56444445-30.49244445 64.73955555-53.47555556 92.72888888-16.15644445 19.56977778-34.24711111 37.20533333-54.04444444 52.45155556-47.90044445 36.75022222-87.38133333 84.65066667-114.11911111 138.24C125.72444445 502.10133333 111.50222222 562.74488889 111.50222222 623.50222222c0 53.70311111 10.58133333 105.69955555 31.51644445 154.73777778 20.25244445 47.21777778 49.152 89.77066667 85.90222222 126.17955555 36.864 36.40888889 79.64444445 65.08088889 127.31733333 84.992C405.61777778 1010.11911111 457.95555555 1020.58666667 512 1020.58666667s106.38222222-10.46755555 155.76177778-31.06133334c47.67288889-19.91111111 90.56711111-48.46933333 127.31733333-84.992 36.864-36.40888889 65.76355555-78.96177778 85.90222222-126.17955555 20.93511111-49.03822222 31.51644445-101.03466667 31.51644445-154.73777778 0-55.52355555-11.37777778-109.45422222-34.01955556-160.31288889z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M968.20337778 20.11591112H705.44042667c-22.17301333 0-41.92483556 15.16430222-47.14951111 37.33731555C642.36202666 124.73685332 582.08711111 173.03324444 512 173.03324444s-130.36202666-48.29639112-146.29091556-115.58001777c-5.22467555-22.17301333-24.84906667-37.33731556-47.14951111-37.33731555H55.79662222c-30.96576 0-56.06968889 25.10392889-56.06968888 56.06968888v321.12639999c0 30.96576 25.10392889 56.06968889 56.06968888 56.06968889h95.57333334v494.43271112c0 30.96576 25.10392889 56.06968889 56.06968889 56.06968888h609.1207111c30.96576 0 56.06968889-25.10392889 56.06968889-56.06968888V453.38168888h95.57333334c30.96576 0 56.06968889-25.10392889 56.06968888-56.06968889V76.1856c0-30.96576-25.10392889-56.06968889-56.06968888-56.06968888z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M980.94648889 239.80714666H523.46880001L373.99210666 96.82944c-1.91146667-1.78403556-4.46008889-2.80348444-7.00871111-2.80348445H43.05351111c-22.55530667 0-40.77795555 18.22264888-40.77795555 40.77795557v754.39217776c0 22.55530667 18.22264888 40.77795555 40.77795555 40.77795557h937.89297778c22.55530667 0 40.77795555-18.22264888 40.77795555-40.77795557V280.58510222c0-22.55530667-18.22264888-40.77795555-40.77795555-40.77795556z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M972.60904597 164.57058577L841.30587843 33.39070759c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480282-29.3428675-26.75379095 0-51.90482023 10.47959553-70.76809219 29.3428675L558.60337778 174.68031322c-18.86327195 18.86327195-29.34286748 44.1375906-29.34286749 70.64480283 0 26.75379095 10.47959553 51.90482023 29.34286749 70.76809218l103.31648301 103.31648302c-24.28800376 53.50758189-57.69942011 101.59043198-99.24793416 143.13894603-41.42522469 41.67180341-89.63136414 75.08321976-143.13894603 99.61780223L316.21649759 558.84995649c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480283-29.34286747-26.75379095 0-51.90482023 10.47959553-70.76809217 29.34286747L33.39070759 700.01627278c-18.86327195 18.86327195-29.34286748 44.1375906-29.3428675 70.76809217 0 26.75379095 10.47959553 51.90482023 29.3428675 70.76809219l131.05658883 131.05658883c30.08260365 30.205893 71.63111769 47.34311394 114.28923598 47.34311394 9.00012323 0 17.63037836-0.73973616 26.13734414-2.21920846 166.19405621-27.37023774 331.03192945-115.76870829 464.06114804-248.67463751C901.84095379 636.27567408 990.11613498 471.56109018 1017.85624079 304.87387654c8.38367642-50.91850535-8.50696579-103.31648302-45.24719482-140.30329077z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M910.60451556 640.96028445c-20.38897778-65.49959112-43.83630221-120.54983112-79.89930667-210.64362666C836.31217778 193.67708444 737.93535999 2.27555556 511.36284444 2.27555556 282.24170667 2.27555556 186.03121778 197.50001778 192.14791111 430.31665779c-36.19043555 90.22122667-59.51032888 144.88917333-79.89930667 210.64362666-43.32657778 139.53706668-29.30915556 197.26336001-18.60494222 198.53767111 22.9376 2.80348444 89.32920888-105.00323556 89.32920889-105.00323556 0 62.44124445 32.11264001 143.86972444 101.69002667 202.61546667-33.64181333 10.32192-109.20846222 38.10190221-91.24067556 68.55793777 14.52714667 24.59420444 250.01984 15.67402668 317.94062222 8.02816 67.92078222 7.64586667 303.41347556 16.56604444 317.94062223-8.02816 17.96778667-30.32860444-57.72629333-58.23601779-91.24067555-68.55793777 69.57738667-58.87317334 101.69002667-140.30165333 101.69002667-202.61546667 0 0 66.39160889 107.80672 89.32920888 105.00323556 10.83164445-1.40174222 24.84906667-59.12803556-18.47751111-198.53767111z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M1016.86992592 199.24764445c-37.13706667 16.01991111-77.55093333 27.54939259-119.17842962 32.03982222 42.96248889-25.60758518 75.60912592-66.02145185 91.02222222-114.08118519-39.68568889 23.66577778-84.58998518 41.02068148-131.31472593 50.00154074C819.53374815 126.79395555 765.76995555 101.79318518 706.18074075 101.79318518c-114.688 0-206.92385185 92.96402963-206.92385186 207.04521482 0 16.01991111 1.94180741 32.03982222 5.09724444 47.45291852-171.72859259-8.98085925-324.88865185-91.02222222-426.71217778-216.63288889-17.96171852 30.82619259-28.15620741 66.02145185-28.1562074 104.49351112 0 71.84687408 36.53025185 135.19834075 92.23585185 172.45677036-33.98162963-1.33499259-66.02145185-10.92266667-93.57084445-26.33576296v2.54862222c0 100.6098963 71.1186963 183.98625185 165.90317037 203.1616-17.3549037 4.49042963-35.92343703 7.03905185-54.49197037 7.03905185-13.47128889 0-26.2144-1.33499259-39.07887407-3.15543704C146.69748148 681.90814815 223.03478518 741.49736297 313.93564445 743.43917037c-71.1186963 55.7056-160.19911111 88.4736-256.9253926 88.4736-17.3549037 0-33.37481482-0.60681482-50.00154074-2.54862222C98.75911111 888.22518518 207.62168889 922.20681482 324.85831111 922.20681482 705.45256297 922.20681482 913.71140741 606.90583703 913.71140741 333.23235555c0-8.98085925 0-17.96171852-0.60681482-26.94257777 40.2925037-29.4912 75.60912592-66.02145185 103.76533333-107.04213333z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M917.96720197 1.08889505H106.03279803C53.56084718 1.08889505 9.37393998 45.27580225 9.37393998 97.74775309v5.52336372c0 19.33177108 8.28504494 41.42522469 22.0934536 55.23363205l331.40179753 392.15879462v325.87843379c0 16.57008987 8.28504494 30.37849854 22.09345359 35.90186098l209.88780469 104.94390299 2.76168121 2.76168121c27.61681602 11.04672615 55.23363335-8.28504494 55.23363335-38.66354218V550.66354348l331.40179753-392.15879462c35.90186097-41.42522469 30.37849854-102.18222047-11.04672616-135.32240022-11.04672615-13.80840865-33.14017975-22.0934536-55.23363335-22.09345359z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M491.70164031 97.48884502a25.89076502 25.89076502 0 0 1 40.59671938 0L745.66415762 367.01171317a25.89076502 25.89076502 0 0 0 30.49932208 7.72839349l208.00640948-89.14190458a25.89076502 25.89076502 0 0 1 35.56096592 29.06238339l-115.18801541 554.96855704A103.56306132 103.56306132 0 0 1 803.14165689 952.14301275H220.85834311a103.56306132 103.56306132 0 0 1-101.4011828-82.51387024l-115.18801541-554.96855704a25.89076502 25.89076502 0 0 1 35.54802012-29.06238339l208.01935528 89.14190458a25.89076502 25.89076502 0 0 0 30.49932208-7.72839349l213.36579793-269.52286815z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M643.02466884 387.7801525c19.85376751-88.69205333 33.718272-152.84087467 41.61900049-192.57389433C704.52292267 95.17283515 652.90057916 2.27555515 550.58614084 2.27555515c-92.26012484 0-138.59407685 45.84971417-165.91530666 137.49816969l-0.70087152 2.67605334c-16.40038399 74.13942085-41.47882668 131.61085116-74.6746315 172.73287031a189.06953915 189.06953915 0 0 1-143.04142182 70.44391902l-26.17434983 0.5606965C77.66380049 387.52529067 27.76177817 438.90551468 27.76177817 501.84374084V881.55022182c0 77.4144 62.25009818 140.17422182 139.05282766 140.17422303h492.82707951c101.23127467 0 191.59267516-63.995904 225.93535999-159.98976l102.37815468-286.22301868c26.04691951-72.82688-11.39234134-153.15945284-83.63303784-179.42300483a138.04612267 138.04612267 0 0 0-47.17499733-8.30850884H643.02466884z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M512 512c140.82958222 0 254.86222222-114.03264 254.86222222-254.86222222S652.82958222 2.27555555 512 2.27555555a254.78940445 254.78940445 0 0 0-254.86222222 254.86222223C257.13777778 397.96736 371.17041778 512 512 512z m0 72.81777778c-170.10232889 0-509.72444445 97.57582222-509.72444445 291.27111111v145.63555556h1019.4488889v-145.63555556c0-193.69528889-339.62211555-291.27111111-509.72444445-291.27111111z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M1019.81297778 564.50161779l-138.89991111-472.51456c-8.66531556-25.99594668-29.43658667-43.45400889-57.21656889-43.45400891s-50.33528889 15.67402668-59.00060446 41.66997334l-92.00526221 274.48661334H351.69166222L259.6864 90.33045333c-8.66531556-25.99594668-31.22062222-41.66997333-59.00060444-41.66997332s-50.33528889 17.33063112-57.2165689 43.45400887L4.69674667 564.50161779c-5.22467555 17.33063112 1.78403556 36.44529778 15.67402667 46.89464887l491.11950221 368.27591113 492.77610666-368.27591113c13.76256-10.32192 20.77127111-29.43658667 15.54659557-46.89464887z',\r\n },\r\n {\r\n viewBox: 1024,\r\n path: 'M927.78951111 340.39277037c-12.01493333-47.81700741 12.01493333-124.03294815 89.08041481-150.97552592l-82.40545184-4.36906667s-31.19028148-109.22666667-174.27721483-118.9357037c-143.08693333-9.8304-236.65777778-3.64088889-236.65777777-3.6408889s106.07122963 67.47780741 63.5941926 187.74850371c-31.06891852 63.71555555-79.85682963 116.02299259-132.04290371 175.61220741-1.57771852 1.57771852-3.03407408 3.15543703-4.2477037 4.49042962C278.25493333 624.86755555 7.13007408 934.34311111 7.13007408 934.34311111c298.43152592 78.15774815 498.43768889-7.64586667 616.76657777-110.56165926 24.87940741-0.24272592 43.5693037-0.36408889 56.19105185-0.36408888 164.8109037 0 304.13558518-142.72284445 298.43152593-301.4656-3.88361482-109.1053037-38.71478518-133.74198518-50.72971852-181.5589926z',\r\n },\r\n ],\r\n },\r\n]","\r\nimport { defineComponent } from 'vue'\r\nimport { SHAPE_LIST, ShapePoolItem } from '@/configs/shapes'\r\n\r\nexport default defineComponent({\r\n name: 'shape-pool',\r\n setup(props, { emit }) {\r\n const shapeList = SHAPE_LIST\r\n\r\n const selectShape = (shape: ShapePoolItem) => {\r\n emit('select', shape)\r\n }\r\n\r\n return {\r\n shapeList,\r\n selectShape,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ShapePool.vue?vue&type=template&id=5aabd717&scoped=true\"\nimport script from \"./ShapePool.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapePool.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapePool.vue?vue&type=style&index=0&id=5aabd717&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5aabd717\"\n\nexport default script","<template>\r\n <div class=\"line-pool\">\r\n <div class=\"line-item\" v-for=\"(line, index) in lineList\" :key=\"index\">\r\n <div class=\"line-content\" @click=\"selectLine(line)\">\r\n <SvgWrapper\r\n overflow=\"visible\" \r\n width=\"20\"\r\n height=\"20\"\r\n >\r\n <defs>\r\n <LinePointMarker\r\n class=\"line-marker\"\r\n v-if=\"line.points[0]\"\r\n :id=\"`preset-line-${index}`\"\r\n position=\"start\"\r\n :type=\"line.points[0]\"\r\n color=\"currentColor\"\r\n :baseSize=\"2\"\r\n />\r\n <LinePointMarker\r\n class=\"line-marker\"\r\n v-if=\"line.points[1]\"\r\n :id=\"`preset-line-${index}`\"\r\n position=\"end\"\r\n :type=\"line.points[1]\"\r\n color=\"currentColor\"\r\n :baseSize=\"2\"\r\n />\r\n </defs>\r\n <path\r\n class=\"line-path\"\r\n :d=\"line.path\" \r\n stroke=\"currentColor\" \r\n fill=\"none\" \r\n stroke-width=\"2\" \r\n :stroke-dasharray=\"line.style === 'solid' ? '0, 0' : '4, 1'\"\r\n stroke-linecap \r\n stroke-linejoin \r\n stroke-miterlimit \r\n :marker-start=\"line.points[0] ? `url(#${`preset-line-${index}`}-${line.points[0]}-start)` : ''\"\r\n :marker-end=\"line.points[1] ? `url(#${`preset-line-${index}`}-${line.points[1]}-end)` : ''\"\r\n ></path>\r\n </SvgWrapper>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent } from 'vue'\r\nimport { LINE_LIST, LinePoolItem } from '@/configs/lines'\r\n\r\nimport LinePointMarker from '@/views/components/element/LineElement/LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'line-pool',\r\n components: {\r\n LinePointMarker,\r\n },\r\n setup(props, { emit }) {\r\n const lineList = LINE_LIST\r\n\r\n const selectLine = (line: LinePoolItem) => {\r\n emit('select', line)\r\n }\r\n\r\n return {\r\n lineList,\r\n selectLine,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.line-pool {\r\n width: 200px;\r\n margin-bottom: -5px;\r\n\r\n @include flex-grid-layout();\r\n}\r\n.line-item {\r\n @include flex-grid-layout-children(5, 19%);\r\n\r\n height: 0;\r\n padding-bottom: 19%;\r\n flex-shrink: 0;\r\n position: relative;\r\n display: flex;\r\n justify-content: center;\r\n cursor: pointer;\r\n}\r\n.line-content {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n color: #999;\r\n\r\n &:hover {\r\n color: $themeColor;\r\n }\r\n\r\n svg:not(:root) {\r\n overflow: visible;\r\n }\r\n}\r\n</style>","export interface LinePoolItem {\r\n path: string;\r\n style: string;\r\n points: [string, string];\r\n}\r\n\r\nexport const LINE_LIST = [\r\n { path: 'M0,0 L20,20', style: 'solid', points: ['', ''] },\r\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', ''] },\r\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'arrow'] },\r\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', 'arrow'] },\r\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'dot'] },\r\n]","\r\nimport { defineComponent } from 'vue'\r\nimport { LINE_LIST, LinePoolItem } from '@/configs/lines'\r\n\r\nimport LinePointMarker from '@/views/components/element/LineElement/LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'line-pool',\r\n components: {\r\n LinePointMarker,\r\n },\r\n setup(props, { emit }) {\r\n const lineList = LINE_LIST\r\n\r\n const selectLine = (line: LinePoolItem) => {\r\n emit('select', line)\r\n }\r\n\r\n return {\r\n lineList,\r\n selectLine,\r\n }\r\n },\r\n})\r\n","import { render } from \"./LinePool.vue?vue&type=template&id=08f7cf5a&scoped=true\"\nimport script from \"./LinePool.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePool.vue?vue&type=script&lang=ts\"\n\nimport \"./LinePool.vue?vue&type=style&index=0&id=08f7cf5a&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-08f7cf5a\"\n\nexport default script","<template>\r\n <ul class=\"chart-pool\">\r\n <li class=\"chart-item\" v-for=\"(chart, index) in chartList\" :key=\"index\">\r\n <div class=\"chart-content\" @click=\"selectChart(chart)\">\r\n <IconChartLine size=\"24\" v-if=\"chart === 'line'\" />\r\n <IconChartHistogram size=\"24\" v-else-if=\"chart === 'bar'\" />\r\n <IconChartProportion size=\"24\" v-else-if=\"chart === 'pie'\" />\r\n </div>\r\n </li>\r\n </ul>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-pool',\r\n setup(props, { emit }) {\r\n const chartList = ['bar', 'line', 'pie']\r\n\r\n const selectChart = (chart: string) => {\r\n emit('select', chart)\r\n }\r\n\r\n return {\r\n chartList,\r\n selectChart,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.chart-pool {\r\n width: 120px;\r\n margin-bottom: -5px;\r\n\r\n @include flex-grid-layout();\r\n}\r\n.chart-item {\r\n @include flex-grid-layout-children(3, 32%);\r\n\r\n height: 0;\r\n padding-bottom: 32%;\r\n flex-shrink: 0;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n.chart-content {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n color: #999;\r\n\r\n &:hover {\r\n color: $themeColor;\r\n }\r\n}\r\n</style>","\r\nimport { defineComponent } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-pool',\r\n setup(props, { emit }) {\r\n const chartList = ['bar', 'line', 'pie']\r\n\r\n const selectChart = (chart: string) => {\r\n emit('select', chart)\r\n }\r\n\r\n return {\r\n chartList,\r\n selectChart,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ChartPool.vue?vue&type=template&id=58ced0dd&scoped=true\"\nimport script from \"./ChartPool.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartPool.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartPool.vue?vue&type=style&index=0&id=58ced0dd&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-58ced0dd\"\n\nexport default script","<template>\r\n <div class=\"table-generator\">\r\n <div class=\"title\">\r\n <div class=\"lef\">表格 {{endCell.length ? `${endCell[0]} x ${endCell[1]}` : ''}}</div>\r\n <div class=\"right\" @click=\"isCustom = !isCustom\">{{ isCustom ? '返回' : '自定义'}}</div>\r\n </div>\r\n <table \r\n @mouseleave=\"endCell = []\" \r\n @click=\"handleClickTable()\" \r\n v-if=\"!isCustom\"\r\n >\r\n <tbody>\r\n <tr v-for=\"row in 10\" :key=\"row\">\r\n <td \r\n @mouseenter=\"endCell = [row, col]\"\r\n v-for=\"col in 10\" :key=\"col\"\r\n >\r\n <div \r\n class=\"cell\" \r\n :class=\"{ 'active': endCell.length && row <= endCell[0] && col <= endCell[1] }\"\r\n ></div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <div class=\"custom\" v-else>\r\n <div class=\"row\">\r\n <div class=\"label\" style=\"flex: 1;\">行数:</div>\r\n <InputNumber\r\n :min=\"1\"\r\n :max=\"20\"\r\n v-model:value=\"customRow\"\r\n style=\"flex: 3;\"\r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"label\" style=\"flex: 1;\">列数:</div>\r\n <InputNumber\r\n :min=\"1\"\r\n :max=\"20\"\r\n v-model:value=\"customCol\"\r\n style=\"flex: 3;\"\r\n />\r\n </div>\r\n <div class=\"btns\">\r\n <Button class=\"btn\" @click=\"close()\">取消</Button>\r\n <Button class=\"btn\" type=\"primary\" @click=\"insertCustomTable()\">确认</Button>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, ref } from 'vue'\r\n\r\nimport { message } from 'ant-design-vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-generator',\r\n setup(props, { emit }) {\r\n const endCell = ref<number[]>([])\r\n const customRow = ref(3)\r\n const customCol = ref(3)\r\n const isCustom = ref(false)\r\n\r\n const handleClickTable = () => {\r\n if (!endCell.value.length) return\r\n const [row, col] = endCell.value\r\n emit('insert', { row, col })\r\n }\r\n\r\n const insertCustomTable = () => {\r\n if (customRow.value < 1 || customRow.value > 20) return message.warning('行数/列数必须在0~20之间!')\r\n if (customCol.value < 1 || customCol.value > 20) return message.warning('行数/列数必须在0~20之间!')\r\n emit('insert', { row: customRow.value, col: customCol.value })\r\n isCustom.value = false\r\n }\r\n\r\n const close = () => {\r\n emit('close')\r\n isCustom.value = false\r\n }\r\n\r\n return {\r\n endCell,\r\n customRow,\r\n customCol,\r\n handleClickTable,\r\n insertCustomTable,\r\n isCustom,\r\n close,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.table-generator {\r\n width: 100%;\r\n margin-top: -12px;\r\n}\r\n.title {\r\n height: 28px;\r\n line-height: 28px;\r\n background-color: #ededed;\r\n margin: 0 -12px 12px -12px;\r\n padding: 0 14px;\r\n font-size: 12px;\r\n display: flex;\r\n justify-content: space-between;\r\n\r\n .right {\r\n cursor: pointer;\r\n\r\n &:hover {\r\n color: $themeColor;\r\n }\r\n }\r\n}\r\ntable {\r\n border-collapse: separate;\r\n}\r\ntd {\r\n width: 23px;\r\n height: 23px;\r\n line-height: 23px;\r\n border: 2px solid #fff;\r\n background-color: #f7f7f7;\r\n}\r\n.cell {\r\n width: 100%;\r\n height: 100%;\r\n border: 1px solid #dcdcdc;\r\n\r\n &.active {\r\n background-color: rgba($color: $themeColor, $alpha: .1);\r\n border-color: $themeColor;\r\n }\r\n}\r\n\r\n.custom {\r\n width: 230px;\r\n\r\n .row {\r\n display: flex;\r\n align-items: center;\r\n\r\n & + .row {\r\n margin-top: 10px;\r\n }\r\n }\r\n}\r\n\r\n.btns {\r\n margin-top: 10px;\r\n text-align: right;\r\n\r\n .btn {\r\n margin-left: 10px;\r\n }\r\n}\r\n</style>","\r\nimport { defineComponent, ref } from 'vue'\r\n\r\nimport { message } from 'ant-design-vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-generator',\r\n setup(props, { emit }) {\r\n const endCell = ref<number[]>([])\r\n const customRow = ref(3)\r\n const customCol = ref(3)\r\n const isCustom = ref(false)\r\n\r\n const handleClickTable = () => {\r\n if (!endCell.value.length) return\r\n const [row, col] = endCell.value\r\n emit('insert', { row, col })\r\n }\r\n\r\n const insertCustomTable = () => {\r\n if (customRow.value < 1 || customRow.value > 20) return message.warning('行数/列数必须在0~20之间!')\r\n if (customCol.value < 1 || customCol.value > 20) return message.warning('行数/列数必须在0~20之间!')\r\n emit('insert', { row: customRow.value, col: customCol.value })\r\n isCustom.value = false\r\n }\r\n\r\n const close = () => {\r\n emit('close')\r\n isCustom.value = false\r\n }\r\n\r\n return {\r\n endCell,\r\n customRow,\r\n customCol,\r\n handleClickTable,\r\n insertCustomTable,\r\n isCustom,\r\n close,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TableGenerator.vue?vue&type=template&id=576c614c&scoped=true\"\nimport script from \"./TableGenerator.vue?vue&type=script&lang=ts\"\nexport * from \"./TableGenerator.vue?vue&type=script&lang=ts\"\n\nimport \"./TableGenerator.vue?vue&type=style&index=0&id=576c614c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-576c614c\"\n\nexport default script","\r\nimport { defineComponent, computed, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\nimport useCreateElement from '@/hooks/useCreateElement'\r\n\r\nimport ShapePool from './ShapePool.vue'\r\nimport LinePool from './LinePool.vue'\r\nimport ChartPool from './ChartPool.vue'\r\nimport TableGenerator from './TableGenerator.vue'\r\n\r\nexport default defineComponent({\r\n name: 'canvas-tool',\r\n components: {\r\n ShapePool,\r\n LinePool,\r\n ChartPool,\r\n TableGenerator,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const canUndo = computed(() => store.getters.canUndo)\r\n const canRedo = computed(() => store.getters.canRedo)\r\n\r\n const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')\r\n\r\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\r\n const { redo, undo } = useHistorySnapshot()\r\n\r\n const { createImageElement, createChartElement, createTableElement } = useCreateElement()\r\n\r\n const insertImageElement = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\r\n }\r\n\r\n const shapePoolVisible = ref(false)\r\n const linePoolVisible = ref(false)\r\n const chartPoolVisible = ref(false)\r\n const tableGeneratorVisible = ref(false)\r\n\r\n // 绘制文字范围\r\n const drawText = () => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'text',\r\n data: null,\r\n })\r\n }\r\n\r\n // 绘制形状范围\r\n const drawShape = (shape: ShapePoolItem) => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'shape',\r\n data: shape,\r\n })\r\n shapePoolVisible.value = false\r\n }\r\n\r\n // 绘制线条路径\r\n const drawLine = (line: LinePoolItem) => {\r\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\r\n type: 'line',\r\n data: line,\r\n })\r\n linePoolVisible.value = false\r\n }\r\n\r\n return {\r\n scaleCanvas,\r\n setCanvasPercentage,\r\n canvasScalePercentage,\r\n canUndo,\r\n canRedo,\r\n redo,\r\n undo,\r\n insertImageElement,\r\n shapePoolVisible,\r\n linePoolVisible,\r\n chartPoolVisible,\r\n tableGeneratorVisible,\r\n drawText,\r\n drawShape,\r\n drawLine,\r\n createChartElement,\r\n createTableElement,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=236c5f54&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=236c5f54&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-236c5f54\"\n\nexport default script","<template>\r\n <div \r\n class=\"thumbnails\"\r\n @mousedown=\"() => setThumbnailsFocus(true)\"\r\n v-click-outside=\"() => setThumbnailsFocus(false)\"\r\n v-contextmenu=\"contextmenusThumbnails\"\r\n >\r\n <div class=\"add-slide\" @click=\"createSlide()\"><IconPlus /> 添加幻灯片</div>\r\n <Draggable \r\n class=\"thumbnail-list\"\r\n :modelValue=\"slides\"\r\n :animation=\"300\"\r\n :scroll=\"true\"\r\n :scrollSensitivity=\"50\"\r\n @end=\"handleDragEnd\"\r\n itemKey=\"id\"\r\n >\r\n <template #item=\"{ element, index }\">\r\n <div\r\n class=\"thumbnail-wrapper\"\r\n :class=\"{ 'active': slideIndex === index }\"\r\n @mousedown=\"changSlideIndex(index)\"\r\n v-contextmenu=\"contextmenusThumbnailItem\"\r\n >\r\n <div class=\"slide-index\">{{ fillDigit(index + 1, 2) }}</div>\r\n <div class=\"thumbnail\">\r\n <ThumbnailSlide :slide=\"element\" :size=\"120\" />\r\n </div>\r\n </div>\r\n </template>\r\n </Draggable>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { fillDigit } from '@/utils/common'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useSlideHandler from '@/hooks/useSlideHandler'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport Draggable from 'vuedraggable'\r\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'thumbnails',\r\n components: {\r\n Draggable,\r\n ThumbnailSlide,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n\r\n const {\r\n copySlide,\r\n pasteSlide,\r\n createSlide,\r\n copyAndPasteSlide,\r\n deleteSlide,\r\n cutSlide,\r\n } = useSlideHandler()\r\n\r\n // 切换页面\r\n const changSlideIndex = (index: number) => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n\r\n if (slideIndex.value === index) return\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n }\r\n\r\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\r\n\r\n // 设置缩略图工具栏聚焦状态(只有聚焦状态下,该部分的快捷键才能生效)\r\n const setThumbnailsFocus = (focus: boolean) => {\r\n if (thumbnailsFocus.value === focus) return\r\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, focus)\r\n }\r\n\r\n // 拖拽调整顺序后进行数据的同步\r\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\r\n const { newIndex, oldIndex } = eventData\r\n if (oldIndex === newIndex) return\r\n\r\n const _slides = JSON.parse(JSON.stringify(slides.value))\r\n const _slide = _slides[oldIndex]\r\n _slides.splice(oldIndex, 1)\r\n _slides.splice(newIndex, 0, _slide)\r\n store.commit(MutationTypes.SET_SLIDES, _slides)\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)\r\n }\r\n\r\n const { enterScreening } = useScreening()\r\n\r\n const contextmenusThumbnails = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteSlide,\r\n },\r\n {\r\n text: '新建页面',\r\n subText: 'Enter',\r\n handler: createSlide,\r\n },\r\n {\r\n text: '开始演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n const contextmenusThumbnailItem = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '剪切',\r\n subText: 'Ctrl + X',\r\n handler: cutSlide,\r\n },\r\n {\r\n text: '复制',\r\n subText: 'Ctrl + C',\r\n handler: copySlide,\r\n },\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteSlide,\r\n },\r\n { divider: true },\r\n {\r\n text: '新建页面',\r\n subText: 'Enter',\r\n handler: createSlide,\r\n },\r\n {\r\n text: '复制页面',\r\n subText: 'Ctrl + D',\r\n handler: copyAndPasteSlide,\r\n },\r\n {\r\n text: '删除页面',\r\n subText: 'Delete',\r\n handler: deleteSlide,\r\n },\r\n { divider: true },\r\n {\r\n text: '从当前页演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n setThumbnailsFocus,\r\n slides,\r\n slideIndex,\r\n createSlide,\r\n changSlideIndex,\r\n contextmenusThumbnails,\r\n contextmenusThumbnailItem,\r\n fillDigit,\r\n handleDragEnd,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.thumbnails {\r\n border-right: solid 1px $borderColor;\r\n background-color: #fff;\r\n display: flex;\r\n flex-direction: column;\r\n user-select: none;\r\n}\r\n.add-slide {\r\n height: 40px;\r\n font-size: 12px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n flex-shrink: 0;\r\n border-bottom: 1px solid $borderColor;\r\n cursor: pointer;\r\n}\r\n.thumbnail-list {\r\n padding: 5px 0;\r\n flex: 1;\r\n overflow: auto;\r\n}\r\n.thumbnail-wrapper {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: 5px 0;\r\n\r\n .thumbnail {\r\n outline: 1px solid rgba($color: $themeColor, $alpha: .15);\r\n }\r\n\r\n &.active {\r\n .slide-index {\r\n color: $themeColor;\r\n }\r\n .thumbnail {\r\n outline-color: $themeColor;\r\n }\r\n }\r\n}\r\n.thumbnail {\r\n width: 120px;\r\n height: 67.5px;\r\n}\r\n.slide-index {\r\n font-size: 12px;\r\n color: #999;\r\n width: 20px;\r\n cursor: grab;\r\n\r\n &:active {\r\n cursor: grabbing;\r\n }\r\n}\r\n</style>","<template>\r\n <div class=\"thumbnail-slide\"\r\n :style=\"{\r\n width: size + 'px',\r\n height: size * VIEWPORT_ASPECT_RATIO + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"elements-wrapper\"\r\n :style=\"{\r\n width: VIEWPORT_SIZE + 'px',\r\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO + 'px',\r\n transform: `scale(${scale})`,\r\n }\"\r\n >\r\n <div class=\"background\" :style=\"backgroundStyle\"></div>\r\n <ThumbnailElement\r\n v-for=\"(element, index) in slide.elements\"\r\n :key=\"element.id\"\r\n :elementInfo=\"element\"\r\n :elementIndex=\"index + 1\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nimport ThumbnailElement from './ThumbnailElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'thumbnail-slide',\r\n components: {\r\n ThumbnailElement,\r\n },\r\n props: {\r\n slide: {\r\n type: Object as PropType<Slide>,\r\n required: true,\r\n },\r\n size: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const background = computed(() => props.slide.background)\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n const scale = computed(() => props.size / VIEWPORT_SIZE)\r\n\r\n return {\r\n scale,\r\n backgroundStyle,\r\n VIEWPORT_SIZE,\r\n VIEWPORT_ASPECT_RATIO,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.thumbnail-slide {\r\n background-color: #fff;\r\n overflow: hidden;\r\n}\r\n.elements-wrapper {\r\n transform-origin: 0 0;\r\n}\r\n.background {\r\n width: 100%;\r\n height: 100%;\r\n background-position: center;\r\n position: absolute;\r\n}\r\n</style>","<template>\r\n <div \r\n class=\"base-element\"\r\n :style=\"{\r\n zIndex: elementIndex,\r\n color: theme.fontColor,\r\n fontFamily: theme.fontName,\r\n }\"\r\n >\r\n <component\r\n :is=\"currentElementComponent\"\r\n :elementInfo=\"elementInfo\"\r\n target=\"thumbnail\"\r\n ></component>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\n\r\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\r\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\r\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\r\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\r\nimport BaseChartElement from '@/views/components/element/ChartElement/BaseChartElement.vue'\r\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: BaseImageElement,\r\n [ElementTypes.TEXT]: BaseTextElement,\r\n [ElementTypes.SHAPE]: BaseShapeElement,\r\n [ElementTypes.LINE]: BaseLineElement,\r\n [ElementTypes.CHART]: BaseChartElement,\r\n [ElementTypes.TABLE]: BaseTableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n return {\r\n currentElementComponent,\r\n theme,\r\n }\r\n },\r\n})\r\n</script>","<template>\r\n <div \r\n class=\"base-element-image\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',\r\n transform: flipStyle,\r\n }\"\r\n >\r\n <ImageOutline :elementInfo=\"elementInfo\" />\r\n\r\n <div class=\"image-content\" :style=\"{ clipPath: clipShape.style }\">\r\n <img \r\n :src=\"elementInfo.src\" \r\n :draggable=\"false\" \r\n :style=\"{\r\n top: imgPosition.top,\r\n left: imgPosition.left,\r\n width: imgPosition.width,\r\n height: imgPosition.height,\r\n filter: filter,\r\n }\" \r\n alt=\"\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\nimport useClipImage from './useClipImage'\r\nimport useFilter from './useFilter'\r\n\r\nimport ImageOutline from './ImageOutline/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-image',\r\n components: {\r\n ImageOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n \r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape, imgPosition } = useClipImage(clip)\r\n\r\n const filters = computed(() => props.elementInfo.filters)\r\n const { filter } = useFilter(filters)\r\n\r\n return {\r\n imgPosition,\r\n filter,\r\n flipStyle,\r\n shadowStyle,\r\n clipShape,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.base-element-image {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n .image-content {\r\n width: 100%;\r\n height: 100%;\r\n overflow: hidden;\r\n position: relative;\r\n }\r\n\r\n img {\r\n position: absolute;\r\n }\r\n}\r\n</style>\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\nimport useClipImage from './useClipImage'\r\nimport useFilter from './useFilter'\r\n\r\nimport ImageOutline from './ImageOutline/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-image',\r\n components: {\r\n ImageOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTImageElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n \r\n const clip = computed(() => props.elementInfo.clip)\r\n const { clipShape, imgPosition } = useClipImage(clip)\r\n\r\n const filters = computed(() => props.elementInfo.filters)\r\n const { filter } = useFilter(filters)\r\n\r\n return {\r\n imgPosition,\r\n filter,\r\n flipStyle,\r\n shadowStyle,\r\n clipShape,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseImageElement.vue?vue&type=template&id=1285108e&scoped=true\"\nimport script from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseImageElement.vue?vue&type=style&index=0&id=1285108e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1285108e\"\n\nexport default script","<template>\r\n <div \r\n class=\"base-element-text\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n backgroundColor: elementInfo.fill,\r\n opacity: elementInfo.opacity,\r\n textShadow: shadowStyle,\r\n lineHeight: elementInfo.lineHeight,\r\n letterSpacing: (elementInfo.wordSpace || 0) + 'px',\r\n }\"\r\n >\r\n <ElementOutline\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <div class=\"text ProseMirror-static\" v-html=\"elementInfo.content\"></div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-text',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n return {\r\n shadowStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.base-element-text {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n position: relative;\r\n padding: 10px;\r\n line-height: 1.5;\r\n word-break: break-word;\r\n\r\n .text {\r\n position: relative;\r\n }\r\n}\r\n</style>\r\n","\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-text',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTextElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n return {\r\n shadowStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseTextElement.vue?vue&type=template&id=fc2d45e0&scoped=true\"\nimport script from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTextElement.vue?vue&type=style&index=0&id=fc2d45e0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-fc2d45e0\"\n\nexport default script","<template>\r\n <div \r\n class=\"base-element-shape\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n transform: `rotate(${elementInfo.rotate}deg)`,\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n opacity: elementInfo.opacity,\r\n filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',\r\n transform: flipStyle,\r\n }\"\r\n >\r\n <SvgWrapper \r\n overflow=\"visible\" \r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n >\r\n <defs v-if=\"elementInfo.gradient\">\r\n <GradientDefs\r\n :id=\"`base-gradient-${elementInfo.id}`\" \r\n :type=\"elementInfo.gradient.type\"\r\n :color1=\"elementInfo.gradient.color[0]\"\r\n :color2=\"elementInfo.gradient.color[1]\"\r\n :rotate=\"elementInfo.gradient.rotate\"\r\n />\r\n </defs>\r\n <g \r\n :transform=\"`scale(${elementInfo.width / elementInfo.viewBox}, ${elementInfo.height / elementInfo.viewBox}) translate(0,0) matrix(1,0,0,1,0,0)`\"\r\n >\r\n <path \r\n vector-effect=\"non-scaling-stroke\" \r\n stroke-linecap=\"butt\" \r\n stroke-miterlimit=\"8\"\r\n stroke-linejoin=\"\" \r\n :d=\"elementInfo.path\" \r\n :fill=\"elementInfo.gradient ? `url(#base-gradient-${elementInfo.id})` : elementInfo.fill\"\r\n :stroke=\"outlineColor\"\r\n :stroke-width=\"outlineWidth\" \r\n :stroke-dasharray=\"outlineStyle === 'dashed' ? '10 5' : '0 0'\" \r\n ></path>\r\n </g>\r\n\t\t\t</SvgWrapper>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\n\r\nimport GradientDefs from './GradientDefs.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-shape',\r\n components: {\r\n GradientDefs,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const outline = computed(() => props.elementInfo.outline)\r\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n return {\r\n shadowStyle,\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.base-element-shape {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n svg {\r\n transform-origin: 0 0;\r\n overflow: visible;\r\n }\r\n}\r\n</style>\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTShapeElement } from '@/types/slides'\r\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\nimport useElementFlip from '@/views/components/element/hooks/useElementFlip'\r\n\r\nimport GradientDefs from './GradientDefs.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-shape',\r\n components: {\r\n GradientDefs,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTShapeElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const outline = computed(() => props.elementInfo.outline)\r\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\r\n \r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const flip = computed(() => props.elementInfo.flip)\r\n const { flipStyle } = useElementFlip(flip)\r\n\r\n return {\r\n shadowStyle,\r\n outlineWidth,\r\n outlineStyle,\r\n outlineColor,\r\n flipStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseShapeElement.vue?vue&type=template&id=d0a0fd1c&scoped=true\"\nimport script from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseShapeElement.vue?vue&type=style&index=0&id=d0a0fd1c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d0a0fd1c\"\n\nexport default script","<template>\r\n <div \r\n class=\"editable-element-shape\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{ filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '' }\"\r\n >\r\n <SvgWrapper\r\n overflow=\"visible\" \r\n :width=\"svgWidth\"\r\n :height=\"svgHeight\"\r\n >\r\n <defs>\r\n <LinePointMarker\r\n v-if=\"elementInfo.points[0]\"\r\n :id=\"elementInfo.id\"\r\n position=\"start\"\r\n :type=\"elementInfo.points[0]\"\r\n :color=\"elementInfo.color\"\r\n :baseSize=\"elementInfo.width\"\r\n />\r\n <LinePointMarker\r\n v-if=\"elementInfo.points[1]\"\r\n :id=\"elementInfo.id\"\r\n position=\"end\"\r\n :type=\"elementInfo.points[1]\"\r\n :color=\"elementInfo.color\"\r\n :baseSize=\"elementInfo.width\"\r\n />\r\n </defs>\r\n\t\t\t\t<path\r\n :d=\"path\" \r\n :stroke=\"elementInfo.color\" \r\n :stroke-width=\"elementInfo.width\" \r\n :stroke-dasharray=\"lineDashArray\"\r\n fill=\"none\" \r\n stroke-linecap \r\n stroke-linejoin \r\n stroke-miterlimit \r\n :marker-start=\"elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''\"\r\n :marker-end=\"elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''\"\r\n ></path>\r\n\t\t\t</SvgWrapper>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nimport LinePointMarker from './LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n LinePointMarker,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const svgWidth = computed(() => {\r\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\r\n return width < 24 ? 24 : width\r\n })\r\n const svgHeight = computed(() => {\r\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\r\n return height < 24 ? 24 : height\r\n })\r\n\r\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\r\n\r\n const path = computed(() => {\r\n const start = props.elementInfo.start.join(',')\r\n const end = props.elementInfo.end.join(',')\r\n return `M${start} L${end}`\r\n })\r\n\r\n return {\r\n shadowStyle,\r\n svgWidth,\r\n svgHeight,\r\n lineDashArray,\r\n path,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-element-shape {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n\r\n svg {\r\n transform-origin: 0 0;\r\n overflow: visible;\r\n }\r\n}\r\n</style>\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\r\n\r\nimport LinePointMarker from './LinePointMarker.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-shape',\r\n components: {\r\n LinePointMarker,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTLineElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const shadow = computed(() => props.elementInfo.shadow)\r\n const { shadowStyle } = useElementShadow(shadow)\r\n\r\n const svgWidth = computed(() => {\r\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\r\n return width < 24 ? 24 : width\r\n })\r\n const svgHeight = computed(() => {\r\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\r\n return height < 24 ? 24 : height\r\n })\r\n\r\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\r\n\r\n const path = computed(() => {\r\n const start = props.elementInfo.start.join(',')\r\n const end = props.elementInfo.end.join(',')\r\n return `M${start} L${end}`\r\n })\r\n\r\n return {\r\n shadowStyle,\r\n svgWidth,\r\n svgHeight,\r\n lineDashArray,\r\n path,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseLineElement.vue?vue&type=template&id=54a876d6&scoped=true\"\nimport script from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseLineElement.vue?vue&type=style&index=0&id=54a876d6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-54a876d6\"\n\nexport default script","<template>\r\n <div class=\"base-element-chart\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n backgroundColor: elementInfo.fill,\r\n }\"\r\n >\r\n <ElementOutline\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <IconChartLine :fill=\"elementInfo.themeColor\" strokeWidth=\"2\" :size=\"size\" v-if=\"elementInfo.chartType === 'line'\" />\r\n <IconChartHistogram :fill=\"elementInfo.themeColor\" strokeWidth=\"2\" :size=\"size\" v-else-if=\"elementInfo.chartType === 'bar'\" />\r\n <IconChartProportion :fill=\"elementInfo.themeColor\" strokeWidth=\"2\" :size=\"size\" v-else-if=\"elementInfo.chartType === 'pie'\" />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-chart',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const size = computed(() => Math.min(props.elementInfo.width, props.elementInfo.height))\r\n\r\n return {\r\n size,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.base-element-chart {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n opacity: .5;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n</style>\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-chart',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const size = computed(() => Math.min(props.elementInfo.width, props.elementInfo.height))\r\n\r\n return {\r\n size,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseChartElement.vue?vue&type=template&id=b4562eca&scoped=true\"\nimport script from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseChartElement.vue?vue&type=style&index=0&id=b4562eca&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b4562eca\"\n\nexport default script","<template>\r\n <div \r\n class=\"base-element-table\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n }\"\r\n >\r\n <div class=\"element-content\">\r\n <StaticTable\r\n :data=\"elementInfo.data\"\r\n :width=\"elementInfo.width\"\r\n :colWidths=\"elementInfo.colWidths\"\r\n :outline=\"elementInfo.outline\"\r\n :theme=\"elementInfo.theme\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTTableElement } from '@/types/slides'\r\n\r\nimport StaticTable from './StaticTable.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-table',\r\n components: {\r\n StaticTable,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.base-element-table {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n}\r\n</style>\r\n","<template>\r\n <div \r\n class=\"static-table\"\r\n :style=\"{ width: totalWidth + 'px' }\"\r\n >\r\n <table\r\n :class=\"{\r\n 'theme': theme,\r\n 'row-header': theme?.rowHeader,\r\n 'row-footer': theme?.rowFooter,\r\n 'col-header': theme?.colHeader,\r\n 'col-footer': theme?.colFooter,\r\n }\"\r\n :style=\"`--themeColor: ${theme?.color}; --subThemeColor1: ${subThemeColor[0]}; --subThemeColor2: ${subThemeColor[1]}`\"\r\n >\r\n <colgroup>\r\n <col span=\"1\" v-for=\"(width, index) in colSizeList\" :key=\"index\" :width=\"width\">\r\n </colgroup>\r\n <tbody>\r\n <tr\r\n v-for=\"(rowCells, rowIndex) in data\" \r\n :key=\"rowIndex\"\r\n >\r\n <td \r\n class=\"cell\"\r\n :style=\"{\r\n borderStyle: outline.style,\r\n borderColor: outline.color,\r\n borderWidth: outline.width + 'px',\r\n ...getTextStyle(cell.style),\r\n }\"\r\n v-for=\"(cell, colIndex) in rowCells\"\r\n :key=\"cell.id\"\r\n :rowspan=\"cell.rowspan\"\r\n :colspan=\"cell.colspan\"\r\n v-show=\"!hideCells.includes(`${rowIndex}_${colIndex}`)\"\r\n >\r\n <div class=\"cell-text\" v-html=\"cell.text\" />\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType, ref, watch } from 'vue'\r\nimport { PPTElementOutline, TableCell, TableTheme } from '@/types/slides'\r\nimport { getTextStyle } from './utils'\r\nimport useHideCells from './useHideCells'\r\nimport useSubThemeColor from './useSubThemeColor'\r\n\r\nexport default defineComponent({\r\n name: 'static-table',\r\n props: {\r\n data: {\r\n type: Array as PropType<TableCell[][]>,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n colWidths: {\r\n type: Array as PropType<number[]>,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>,\r\n required: true,\r\n },\r\n theme: {\r\n type: Object as PropType<TableTheme>,\r\n },\r\n editable: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n },\r\n setup(props) {\r\n const colSizeList = ref<number[]>([])\r\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\r\n\r\n watch([\r\n () => props.colWidths,\r\n () => props.width,\r\n ], () => {\r\n colSizeList.value = props.colWidths.map(item => item * props.width)\r\n }, { immediate: true })\r\n\r\n const cells = computed(() => props.data)\r\n const { hideCells } = useHideCells(cells)\r\n\r\n const theme = computed(() => props.theme)\r\n const { subThemeColor } = useSubThemeColor(theme)\r\n\r\n return {\r\n colSizeList,\r\n totalWidth,\r\n hideCells,\r\n getTextStyle,\r\n subThemeColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.static-table {\r\n position: relative;\r\n user-select: none;\r\n}\r\ntable {\r\n width: 100%;\r\n position: relative;\r\n table-layout: fixed;\r\n border-collapse: collapse;\r\n border-spacing: 0;\r\n border: 0;\r\n word-wrap: break-word;\r\n user-select: none;\r\n\r\n --themeColor: $themeColor;\r\n --subThemeColor1: $themeColor;\r\n --subThemeColor2: $themeColor;\r\n\r\n &.theme {\r\n tr:nth-child(2n) .cell {\r\n background-color: var(--subThemeColor1);\r\n }\r\n tr:nth-child(2n + 1) .cell {\r\n background-color: var(--subThemeColor2);\r\n }\r\n\r\n &.row-header {\r\n tr:first-child .cell {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.row-footer {\r\n tr:last-child .cell {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.col-header {\r\n tr .cell:first-child {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n &.col-footer {\r\n tr .cell:last-child {\r\n background-color: var(--themeColor);\r\n }\r\n }\r\n }\r\n\r\n tr {\r\n height: 36px;\r\n }\r\n\r\n .cell {\r\n position: relative;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n vertical-align: middle;\r\n }\r\n\r\n .cell-text {\r\n min-height: 32px;\r\n padding: 5px;\r\n border: 0;\r\n outline: 0;\r\n line-height: 1.5;\r\n font-size: 14px;\r\n user-select: none;\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent, PropType, ref, watch } from 'vue'\r\nimport { PPTElementOutline, TableCell, TableTheme } from '@/types/slides'\r\nimport { getTextStyle } from './utils'\r\nimport useHideCells from './useHideCells'\r\nimport useSubThemeColor from './useSubThemeColor'\r\n\r\nexport default defineComponent({\r\n name: 'static-table',\r\n props: {\r\n data: {\r\n type: Array as PropType<TableCell[][]>,\r\n required: true,\r\n },\r\n width: {\r\n type: Number,\r\n required: true,\r\n },\r\n colWidths: {\r\n type: Array as PropType<number[]>,\r\n required: true,\r\n },\r\n outline: {\r\n type: Object as PropType<PPTElementOutline>,\r\n required: true,\r\n },\r\n theme: {\r\n type: Object as PropType<TableTheme>,\r\n },\r\n editable: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n },\r\n setup(props) {\r\n const colSizeList = ref<number[]>([])\r\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\r\n\r\n watch([\r\n () => props.colWidths,\r\n () => props.width,\r\n ], () => {\r\n colSizeList.value = props.colWidths.map(item => item * props.width)\r\n }, { immediate: true })\r\n\r\n const cells = computed(() => props.data)\r\n const { hideCells } = useHideCells(cells)\r\n\r\n const theme = computed(() => props.theme)\r\n const { subThemeColor } = useSubThemeColor(theme)\r\n\r\n return {\r\n colSizeList,\r\n totalWidth,\r\n hideCells,\r\n getTextStyle,\r\n subThemeColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./StaticTable.vue?vue&type=template&id=01f791ba&scoped=true\"\nimport script from \"./StaticTable.vue?vue&type=script&lang=ts\"\nexport * from \"./StaticTable.vue?vue&type=script&lang=ts\"\n\nimport \"./StaticTable.vue?vue&type=style&index=0&id=01f791ba&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-01f791ba\"\n\nexport default script","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTTableElement } from '@/types/slides'\r\n\r\nimport StaticTable from './StaticTable.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-table',\r\n components: {\r\n StaticTable,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTTableElement>,\r\n required: true,\r\n },\r\n },\r\n})\r\n","import { render } from \"./BaseTableElement.vue?vue&type=template&id=dea016ac&scoped=true\"\nimport script from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTableElement.vue?vue&type=style&index=0&id=dea016ac&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dea016ac\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\n\r\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\r\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\r\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\r\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\r\nimport BaseChartElement from '@/views/components/element/ChartElement/BaseChartElement.vue'\r\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: BaseImageElement,\r\n [ElementTypes.TEXT]: BaseTextElement,\r\n [ElementTypes.SHAPE]: BaseShapeElement,\r\n [ElementTypes.LINE]: BaseLineElement,\r\n [ElementTypes.CHART]: BaseChartElement,\r\n [ElementTypes.TABLE]: BaseTableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n return {\r\n currentElementComponent,\r\n theme,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ThumbnailElement.vue?vue&type=template&id=43292aca\"\nimport script from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nimport ThumbnailElement from './ThumbnailElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'thumbnail-slide',\r\n components: {\r\n ThumbnailElement,\r\n },\r\n props: {\r\n slide: {\r\n type: Object as PropType<Slide>,\r\n required: true,\r\n },\r\n size: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const background = computed(() => props.slide.background)\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n const scale = computed(() => props.size / VIEWPORT_SIZE)\r\n\r\n return {\r\n scale,\r\n backgroundStyle,\r\n VIEWPORT_SIZE,\r\n VIEWPORT_ASPECT_RATIO,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=5332dba4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=5332dba4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5332dba4\"\n\nexport default script","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { fillDigit } from '@/utils/common'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport useSlideHandler from '@/hooks/useSlideHandler'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport Draggable from 'vuedraggable'\r\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'thumbnails',\r\n components: {\r\n Draggable,\r\n ThumbnailSlide,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n\r\n const {\r\n copySlide,\r\n pasteSlide,\r\n createSlide,\r\n copyAndPasteSlide,\r\n deleteSlide,\r\n cutSlide,\r\n } = useSlideHandler()\r\n\r\n // 切换页面\r\n const changSlideIndex = (index: number) => {\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\r\n\r\n if (slideIndex.value === index) return\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n }\r\n\r\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\r\n\r\n // 设置缩略图工具栏聚焦状态(只有聚焦状态下,该部分的快捷键才能生效)\r\n const setThumbnailsFocus = (focus: boolean) => {\r\n if (thumbnailsFocus.value === focus) return\r\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, focus)\r\n }\r\n\r\n // 拖拽调整顺序后进行数据的同步\r\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\r\n const { newIndex, oldIndex } = eventData\r\n if (oldIndex === newIndex) return\r\n\r\n const _slides = JSON.parse(JSON.stringify(slides.value))\r\n const _slide = _slides[oldIndex]\r\n _slides.splice(oldIndex, 1)\r\n _slides.splice(newIndex, 0, _slide)\r\n store.commit(MutationTypes.SET_SLIDES, _slides)\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)\r\n }\r\n\r\n const { enterScreening } = useScreening()\r\n\r\n const contextmenusThumbnails = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteSlide,\r\n },\r\n {\r\n text: '新建页面',\r\n subText: 'Enter',\r\n handler: createSlide,\r\n },\r\n {\r\n text: '开始演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n const contextmenusThumbnailItem = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '剪切',\r\n subText: 'Ctrl + X',\r\n handler: cutSlide,\r\n },\r\n {\r\n text: '复制',\r\n subText: 'Ctrl + C',\r\n handler: copySlide,\r\n },\r\n {\r\n text: '粘贴',\r\n subText: 'Ctrl + V',\r\n handler: pasteSlide,\r\n },\r\n { divider: true },\r\n {\r\n text: '新建页面',\r\n subText: 'Enter',\r\n handler: createSlide,\r\n },\r\n {\r\n text: '复制页面',\r\n subText: 'Ctrl + D',\r\n handler: copyAndPasteSlide,\r\n },\r\n {\r\n text: '删除页面',\r\n subText: 'Delete',\r\n handler: deleteSlide,\r\n },\r\n { divider: true },\r\n {\r\n text: '从当前页演示',\r\n subText: 'Ctrl+F',\r\n handler: enterScreening,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n setThumbnailsFocus,\r\n slides,\r\n slideIndex,\r\n createSlide,\r\n changSlideIndex,\r\n contextmenusThumbnails,\r\n contextmenusThumbnailItem,\r\n fillDigit,\r\n handleDragEnd,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=1c5800c2&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=1c5800c2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1c5800c2\"\n\nexport default script","<template>\r\n <div class=\"toolbar\">\r\n <div class=\"tabs\">\r\n <div \r\n class=\"tab\" \r\n :class=\"{ 'active': tab.value === toolbarState }\"\r\n v-for=\"tab in currentTabs\" \r\n :key=\"tab.value\"\r\n @click=\"setToolbarState(tab.value)\"\r\n >{{tab.label}}</div>\r\n </div>\r\n <div class=\"content\">\r\n <component :is=\"currentPanelComponent\"></component>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ToolbarState, ToolbarStates } from '@/types/toolbar'\r\n\r\nimport ElementStylePanel from './ElementStylePanel/index.vue'\r\nimport ElementPositionPanel from './ElementPositionPanel.vue'\r\nimport ElementAnimationPanel from './ElementAnimationPanel.vue'\r\nimport SlideStylePanel from './SlideStylePanel.vue'\r\nimport SlideAnimationPanel from './SlideAnimationPanel.vue'\r\nimport MultiPositionPanel from './MultiPositionPanel.vue'\r\n\r\nexport default defineComponent({\r\n name: 'toolbar',\r\n setup() {\r\n const store = useStore()\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n\r\n const elementTabs = [\r\n { label: '样式', value: ToolbarStates.EL_STYLE },\r\n { label: '位置', value: ToolbarStates.EL_POSITION },\r\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\r\n ]\r\n const slideTabs = [\r\n { label: '页面样式', value: ToolbarStates.SLIDE_STYLE },\r\n { label: '切换', value: ToolbarStates.SLIDE_ANIMATION },\r\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\r\n ]\r\n const multiSelectTabs = [\r\n { label: '位置', value: ToolbarStates.MULTI_POSITION },\r\n { label: '样式', value: ToolbarStates.EL_STYLE },\r\n ]\r\n\r\n const setToolbarState = (value: ToolbarState) => {\r\n store.commit(MutationTypes.SET_TOOLBAR_STATE, value)\r\n }\r\n\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentTabs = computed(() => {\r\n if (!activeElementIdList.value.length) return slideTabs\r\n else if (activeElementIdList.value.length > 1) return multiSelectTabs\r\n return elementTabs\r\n })\r\n\r\n watch(currentTabs, () => {\r\n const currentTabsValue = currentTabs.value.map(tab => tab.value)\r\n if (!currentTabsValue.includes(toolbarState.value)) {\r\n store.commit(MutationTypes.SET_TOOLBAR_STATE, currentTabsValue[0])\r\n }\r\n })\r\n\r\n const currentPanelComponent = computed(() => {\r\n const panelMap = {\r\n [ToolbarStates.EL_STYLE]: ElementStylePanel,\r\n [ToolbarStates.EL_POSITION]: ElementPositionPanel,\r\n [ToolbarStates.EL_ANIMATION]: ElementAnimationPanel,\r\n [ToolbarStates.SLIDE_STYLE]: SlideStylePanel,\r\n [ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,\r\n [ToolbarStates.MULTI_POSITION]: MultiPositionPanel,\r\n }\r\n return panelMap[toolbarState.value] || null\r\n })\r\n\r\n return {\r\n toolbarState,\r\n currentTabs,\r\n setToolbarState,\r\n currentPanelComponent,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.toolbar {\r\n border-left: solid 1px $borderColor;\r\n background-color: #fff;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n.tabs {\r\n height: 40px;\r\n font-size: 12px;\r\n flex-shrink: 0;\r\n display: flex;\r\n}\r\n.tab {\r\n flex: 1;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n background-color: $lightGray;\r\n border-bottom: 1px solid $borderColor;\r\n cursor: pointer;\r\n\r\n &.active {\r\n background-color: #fff;\r\n border-bottom-color: #fff;\r\n }\r\n\r\n & + .tab {\r\n border-left: 1px solid $borderColor;\r\n }\r\n}\r\n.content {\r\n padding: 12px;\r\n font-size: 13px;\r\n overflow: overlay;\r\n}\r\n</style>","export type ToolbarState = 'elAnimation' | 'elStyle' | 'elPosition' | 'slideStyle' | 'slideAnimation' | 'multiPosition'\r\n\r\nexport const ToolbarStates = {\r\n EL_ANIMATION: 'elAnimation',\r\n EL_STYLE: 'elStyle',\r\n EL_POSITION: 'elPosition',\r\n SLIDE_STYLE: 'slideStyle',\r\n SLIDE_ANIMATION: 'slideAnimation',\r\n MULTI_POSITION: 'multiPosition',\r\n}","<template>\r\n <div class=\"element-style-panel\">\r\n <div v-if=\"!currentPanelComponent\">\r\n 请先选中要编辑的元素\r\n </div>\r\n <component v-if=\"handleElement\" :is=\"currentPanelComponent\"></component>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\n\r\nimport TextStylePanel from './TextStylePanel.vue'\r\nimport ImageStylePanel from './ImageStylePanel.vue'\r\nimport ShapeStylePanel from './ShapeStylePanel.vue'\r\nimport LineStylePanel from './LineStylePanel.vue'\r\nimport ChartStylePanel from './ChartStylePanel/index.vue'\r\nimport TableStylePanel from './TableStylePanel.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-style-panel',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const currentPanelComponent = computed(() => {\r\n if (!handleElement.value) return null\r\n \r\n const panelMap = {\r\n [ElementTypes.TEXT]: TextStylePanel,\r\n [ElementTypes.IMAGE]: ImageStylePanel,\r\n [ElementTypes.SHAPE]: ShapeStylePanel,\r\n [ElementTypes.LINE]: LineStylePanel,\r\n [ElementTypes.CHART]: ChartStylePanel,\r\n [ElementTypes.TABLE]: TableStylePanel,\r\n }\r\n return panelMap[handleElement.value.type] || null\r\n })\r\n\r\n return {\r\n handleElement,\r\n currentPanelComponent,\r\n }\r\n },\r\n})\r\n</script>","<template>\r\n <div class=\"text-style-panel\">\r\n <div class=\"preset-style\">\r\n <div \r\n class=\"preset-style-item\"\r\n v-for=\"item in presetStyles\"\r\n :key=\"item.label\"\r\n :style=\"item.style\"\r\n @click=\"emitBatchRichTextCommand(item.cmd)\"\r\n >{{item.label}}</div>\r\n </div>\r\n\r\n <Divider />\r\n \r\n <InputGroup compact class=\"row\">\r\n <Select\r\n style=\"flex: 3;\"\r\n :value=\"richTextAttrs.fontname\"\r\n @change=\"value => emitRichTextCommand('fontname', value)\"\r\n >\r\n <template #suffixIcon><IconFontSize /></template>\r\n <SelectOptGroup label=\"系统字体\">\r\n <SelectOption v-for=\"font in availableFonts\" :key=\"font.value\" :value=\"font.value\">\r\n <span :style=\"{ fontFamily: font.value }\">{{font.label}}</span>\r\n </SelectOption>\r\n </SelectOptGroup>\r\n <SelectOptGroup label=\"在线字体\">\r\n <SelectOption v-for=\"font in webFonts\" :key=\"font.value\" :value=\"font.value\">\r\n <span>{{font.label}}</span>\r\n </SelectOption>\r\n </SelectOptGroup>\r\n </Select>\r\n <Select\r\n style=\"flex: 2;\"\r\n :value=\"richTextAttrs.fontsize\"\r\n @change=\"value => emitRichTextCommand('fontsize', value)\"\r\n >\r\n <template #suffixIcon><IconAddText /></template>\r\n <SelectOption v-for=\"fontsize in fontSizeOptions\" :key=\"fontsize\" :value=\"fontsize\">\r\n {{fontsize}}\r\n </SelectOption>\r\n </Select>\r\n </InputGroup>\r\n\r\n <ButtonGroup class=\"row\">\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"richTextAttrs.color\"\r\n @update:modelValue=\"value => emitRichTextCommand('color', value)\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"文字颜色\">\r\n <Button class=\"text-color-btn\" style=\"flex: 1;\">\r\n <IconText />\r\n <div class=\"text-color-block\" :style=\"{ backgroundColor: richTextAttrs.color }\"></div>\r\n </Button>\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"richTextAttrs.backcolor\"\r\n @update:modelValue=\"value => emitRichTextCommand('backcolor', value)\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"文字高亮\">\r\n <Button class=\"text-color-btn\" style=\"flex: 1;\">\r\n <IconBackgroundColor />\r\n <div class=\"text-color-block\" :style=\"{ backgroundColor: richTextAttrs.backcolor }\"></div>\r\n </Button>\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"fill\"\r\n @update:modelValue=\"value => updateFill(value)\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"文本框填充\">\r\n <Button class=\"text-color-btn\" style=\"flex: 1;\">\r\n <IconFill />\r\n <div class=\"text-color-block\" :style=\"{ backgroundColor: fill }\"></div>\r\n </Button>\r\n </Tooltip>\r\n </Popover>\r\n </ButtonGroup>\r\n\r\n <CheckboxButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"加粗\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.bold\"\r\n @click=\"emitRichTextCommand('bold')\"\r\n ><IconTextBold /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"斜体\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.em\"\r\n @click=\"emitRichTextCommand('em')\"\r\n ><IconTextItalic /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下划线\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.underline\"\r\n @click=\"emitRichTextCommand('underline')\"\r\n ><IconTextUnderline /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"删除线\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.strikethrough\"\r\n @click=\"emitRichTextCommand('strikethrough')\"\r\n ><IconStrikethrough /></CheckboxButton>\r\n </Tooltip>\r\n </CheckboxButtonGroup>\r\n\r\n <CheckboxButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"上标\">\r\n <CheckboxButton\r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.superscript\"\r\n @click=\"emitRichTextCommand('superscript')\"\r\n ><IconUpOne /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下标\">\r\n <CheckboxButton\r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.subscript\"\r\n @click=\"emitRichTextCommand('subscript')\"\r\n ><IconDownOne /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"行内代码\">\r\n <CheckboxButton\r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.code\"\r\n @click=\"emitRichTextCommand('code')\"\r\n ><IconCode /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"引用\">\r\n <CheckboxButton\r\n style=\"flex: 1;\"\r\n :checked=\"richTextAttrs.blockquote\"\r\n @click=\"emitRichTextCommand('blockquote')\"\r\n ><IconQuote /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"清除格式\">\r\n <CheckboxButton\r\n style=\"flex: 1;\"\r\n @click=\"emitRichTextCommand('clear')\"\r\n ><IconFormat /></CheckboxButton>\r\n </Tooltip>\r\n </CheckboxButtonGroup>\r\n\r\n <Divider />\r\n\r\n <RadioGroup \r\n class=\"row\" \r\n button-style=\"solid\" \r\n :value=\"richTextAttrs.align\"\r\n @change=\"e => emitRichTextCommand('align', e.target.value)\"\r\n >\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"左对齐\">\r\n <RadioButton value=\"left\" style=\"flex: 1;\"><IconAlignTextLeft /></RadioButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"居中\">\r\n <RadioButton value=\"center\" style=\"flex: 1;\"><IconAlignTextCenter /></RadioButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"右对齐\">\r\n <RadioButton value=\"right\" style=\"flex: 1;\"><IconAlignTextRight /></RadioButton>\r\n </Tooltip>\r\n </RadioGroup>\r\n\r\n <CheckboxButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"项目符号\">\r\n <CheckboxButton \r\n style=\"flex: 1;\" \r\n :checked=\"richTextAttrs.bulletList\"\r\n @click=\"emitRichTextCommand('bulletList')\"\r\n ><IconList /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"编号\">\r\n <CheckboxButton \r\n style=\"flex: 1;\" \r\n :checked=\"richTextAttrs.orderedList\"\r\n @click=\"emitRichTextCommand('orderedList')\"\r\n ><IconOrderedList /></CheckboxButton>\r\n </Tooltip>\r\n </CheckboxButtonGroup>\r\n\r\n <Divider />\r\n\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">行间距:</div>\r\n <Select style=\"flex: 3;\" :value=\"lineHeight\" @change=\"value => updateLineHeight(value)\">\r\n <template #suffixIcon><IconRowHeight /></template>\r\n <SelectOption v-for=\"item in lineHeightOptions\" :key=\"item\" :value=\"item\">{{item}}倍</SelectOption>\r\n </Select>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">字间距:</div>\r\n <Select style=\"flex: 3;\" :value=\"wordSpace\" @change=\"value => updateWordSpace(value)\">\r\n <template #suffixIcon><IconFullwidth /></template>\r\n <SelectOption v-for=\"item in wordSpaceOptions\" :key=\"item\" :value=\"item\">{{item}}px</SelectOption>\r\n </Select>\r\n </div>\r\n\r\n <Divider />\r\n <ElementOutline />\r\n <Divider />\r\n <ElementShadow />\r\n <Divider />\r\n <ElementOpacity />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { TextAttrs } from '@/prosemirror/utils'\r\nimport { WEB_FONTS } from '@/configs/font'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOpacity from '../common/ElementOpacity.vue'\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\n\r\nconst presetStyles = [\r\n {\r\n label: '大标题',\r\n style: {\r\n fontSize: '26px',\r\n fontWeight: 700,\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '48px' },\r\n { command: 'align', value: 'center' },\r\n { command: 'bold' },\r\n ],\r\n },\r\n {\r\n label: '小标题',\r\n style: {\r\n fontSize: '22px',\r\n fontWeight: 700,\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '36px' },\r\n { command: 'align', value: 'center' },\r\n { command: 'bold' },\r\n ],\r\n },\r\n {\r\n label: '正文',\r\n style: {\r\n fontSize: '20px',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '20px' },\r\n ],\r\n },\r\n {\r\n label: '正文[小]',\r\n style: {\r\n fontSize: '18px',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '18px' },\r\n ],\r\n },\r\n {\r\n label: '注释 1',\r\n style: {\r\n fontSize: '16px',\r\n fontStyle: 'italic',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '16px' },\r\n { command: 'em' },\r\n ],\r\n },\r\n {\r\n label: '注释 2',\r\n style: {\r\n fontSize: '16px',\r\n textDecoration: 'underline',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '16px' },\r\n { command: 'underline' },\r\n ],\r\n },\r\n]\r\n\r\nconst webFonts = WEB_FONTS\r\n\r\ninterface CommandPayload {\r\n command: string;\r\n value?: string;\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'text-style-panel',\r\n components: {\r\n ElementOpacity,\r\n ElementOutline,\r\n ElementShadow,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTTextElement>(() => store.getters.handleElement)\r\n\r\n const fill = ref<string>()\r\n const lineHeight = ref<number>()\r\n const wordSpace = ref<number>()\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'text') return\r\n\r\n fill.value = handleElement.value.fill || '#000'\r\n lineHeight.value = handleElement.value.lineHeight || 1.5\r\n wordSpace.value = handleElement.value.wordSpace || 0\r\n }, { deep: true, immediate: true })\r\n\r\n const richTextAttrs = ref<TextAttrs>({\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n superscript: false,\r\n subscript: false,\r\n code: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '20px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n bulletList: false,\r\n orderedList: false,\r\n blockquote: false,\r\n })\r\n\r\n const availableFonts = computed(() => store.state.availableFonts)\r\n const fontSizeOptions = [\r\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\r\n '36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '76px',\r\n '80px', '88px', '96px', '104px', '112px', '120px',\r\n ]\r\n const lineHeightOptions = [0.9, 1.0, 1.15, 1.2, 1.4, 1.5, 1.8, 2.0, 2.5, 3.0]\r\n const wordSpaceOptions = [0, 1, 2, 3, 4, 5, 6, 8, 10]\r\n\r\n // 接收并更新当前光标所在位置的富文本状态\r\n const updateRichTextAttrs = (attr: TextAttrs) => richTextAttrs.value = attr\r\n\r\n emitter.on(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\r\n })\r\n\r\n // 发射富文本设置命令\r\n const emitRichTextCommand = (command: string, value?: string) => {\r\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value })\r\n }\r\n\r\n // 发射富文本设置命令(批量)\r\n const emitBatchRichTextCommand = (payload: CommandPayload[]) => {\r\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, payload)\r\n }\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置行高\r\n const updateLineHeight = (value: number) => {\r\n const props = { lineHeight: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置字间距\r\n const updateWordSpace = (value: number) => {\r\n const props = { wordSpace: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置文本框填充\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n fill,\r\n lineHeight,\r\n wordSpace,\r\n richTextAttrs,\r\n availableFonts,\r\n webFonts,\r\n fontSizeOptions,\r\n lineHeightOptions,\r\n wordSpaceOptions,\r\n updateLineHeight,\r\n updateWordSpace,\r\n updateFill,\r\n emitRichTextCommand,\r\n emitBatchRichTextCommand,\r\n presetStyles,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.text-style-panel {\r\n user-select: none;\r\n}\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.preset-style {\r\n display: flex;\r\n flex-wrap: wrap;\r\n margin-bottom: 10px;\r\n}\r\n.preset-style-item {\r\n width: 50%;\r\n height: 50px;\r\n border: solid 1px #d6d6d6;\r\n box-sizing: border-box;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n position: relative;\r\n cursor: pointer;\r\n transition: all .2s;\r\n\r\n &:hover {\r\n border-color: $themeColor;\r\n color: $themeColor;\r\n z-index: 1;\r\n }\r\n\r\n &:nth-child(2n) {\r\n margin-left: -1px;\r\n }\r\n &:nth-child(n+3) {\r\n margin-top: -1px;\r\n }\r\n}\r\n.text-color-btn {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n.text-color-block {\r\n width: 16px;\r\n height: 3px;\r\n margin-top: 1px;\r\n}\r\n</style>","<template>\r\n <div class=\"element-opacity\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">不透明度:</div>\r\n <Slider\r\n :min=\"0\"\r\n :max=\"1\"\r\n :step=\"0.1\"\r\n :value=\"opacity\"\r\n style=\"flex: 3;\"\r\n @change=\"value => updateOpacity(value)\" \r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-opacity',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const opacity = ref<number>()\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n opacity.value = 'opacity' in handleElement.value && handleElement.value.opacity !== undefined ? handleElement.value.opacity : 1\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateOpacity = (value: number) => {\r\n const props = { opacity: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n opacity,\r\n updateOpacity,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-opacity',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const opacity = ref<number>()\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n opacity.value = 'opacity' in handleElement.value && handleElement.value.opacity !== undefined ? handleElement.value.opacity : 1\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateOpacity = (value: number) => {\r\n const props = { opacity: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n opacity,\r\n updateOpacity,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementOpacity.vue?vue&type=template&id=b884607e&scoped=true\"\nimport script from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOpacity.vue?vue&type=style&index=0&id=b884607e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b884607e\"\n\nexport default script","<template>\r\n <div class=\"element-outline\">\r\n <div class=\"row\" v-if=\"!fixed\">\r\n <div style=\"flex: 2;\">启用边框:</div>\r\n <div class=\"switch-wrapper\" style=\"flex: 3;\">\r\n <Switch \r\n :checked=\"hasOutline\" \r\n @change=\"checked => toggleOutline(checked)\" \r\n />\r\n </div>\r\n </div>\r\n <template v-if=\"hasOutline\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">边框样式:</div>\r\n <Select \r\n style=\"flex: 3;\" \r\n :value=\"outline.style\" \r\n @change=\"value => updateOutline({ style: value })\"\r\n >\r\n <SelectOption value=\"solid\">实线边框</SelectOption>\r\n <SelectOption value=\"dashed\">虚线边框</SelectOption>\r\n </Select>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">边框颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"outline.color\"\r\n @update:modelValue=\"value => updateOutline({ color: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"outline.color\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">边框粗细:</div>\r\n <InputNumber \r\n :value=\"outline.width\" \r\n @change=\"value => updateOutline({ width: value })\" \r\n style=\"flex: 3;\" \r\n />\r\n </div>\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTElementOutline } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-outline',\r\n components: {\r\n ColorButton,\r\n },\r\n props: {\r\n fixed: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const outline = ref<PPTElementOutline>()\r\n const hasOutline = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n outline.value = 'outline' in handleElement.value ? handleElement.value.outline : undefined\r\n hasOutline.value = !!outline.value\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateOutline = (outlineProps: Partial<PPTElementOutline>) => {\r\n const props = { outline: { ...outline.value, ...outlineProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n const toggleOutline = (checked: boolean) => {\r\n if (checked) {\r\n const props = { outline: { width: 2, color: '#000', style: 'solid' } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'outline' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n outline,\r\n hasOutline,\r\n toggleOutline,\r\n updateOutline,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.switch-wrapper {\r\n text-align: right;\r\n}\r\n</style>","<template>\r\n <Button class=\"color-btn\">\r\n <div \r\n class=\"color-block\" \r\n :style=\"{ backgroundColor: color }\"\r\n ></div>\r\n <IconPlatte class=\"color-btn-icon\" />\r\n </Button>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'color-button',\r\n props: {\r\n color: {\r\n type: String,\r\n required: true,\r\n },\r\n },\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.color-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 0 !important;\r\n}\r\n.color-block {\r\n height: 20px;\r\n margin-left: 8px;\r\n flex: 1;\r\n outline: 1px dashed rgba($color: #666, $alpha: .12);\r\n}\r\n.color-btn-icon {\r\n width: 30px;\r\n font-size: 12px;\r\n margin-top: 2px;\r\n color: #bfbfbf;\r\n}\r\n</style>","\r\nexport default {\r\n name: 'color-button',\r\n props: {\r\n color: {\r\n type: String,\r\n required: true,\r\n },\r\n },\r\n}\r\n","import { render } from \"./ColorButton.vue?vue&type=template&id=39016b60&scoped=true\"\nimport script from \"./ColorButton.vue?vue&type=script&lang=ts\"\nexport * from \"./ColorButton.vue?vue&type=script&lang=ts\"\n\nimport \"./ColorButton.vue?vue&type=style&index=0&id=39016b60&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-39016b60\"\n\nexport default script","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTElementOutline } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-outline',\r\n components: {\r\n ColorButton,\r\n },\r\n props: {\r\n fixed: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const outline = ref<PPTElementOutline>()\r\n const hasOutline = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n outline.value = 'outline' in handleElement.value ? handleElement.value.outline : undefined\r\n hasOutline.value = !!outline.value\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateOutline = (outlineProps: Partial<PPTElementOutline>) => {\r\n const props = { outline: { ...outline.value, ...outlineProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n const toggleOutline = (checked: boolean) => {\r\n if (checked) {\r\n const props = { outline: { width: 2, color: '#000', style: 'solid' } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'outline' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n outline,\r\n hasOutline,\r\n toggleOutline,\r\n updateOutline,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=2d8ce9c0&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=2d8ce9c0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2d8ce9c0\"\n\nexport default script","<template>\r\n <div class=\"element-shadow\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">启用阴影:</div>\r\n <div class=\"switch-wrapper\" style=\"flex: 3;\">\r\n <Switch :checked=\"hasShadow\" @change=\"checked => toggleShadow(checked)\" />\r\n </div>\r\n </div>\r\n <template v-if=\"hasShadow\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">水平阴影:</div>\r\n <Slider \r\n :min=\"0\" \r\n :max=\"10\" \r\n :step=\"1\" \r\n :value=\"shadow.h\" \r\n @change=\"value => updateShadow({ h: value })\" \r\n style=\"flex: 3;\" \r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">垂直阴影:</div>\r\n <Slider\r\n :min=\"0\"\r\n :max=\"10\"\r\n :step=\"1\"\r\n :value=\"shadow.v\"\r\n @change=\"value => updateShadow({ v: value })\" \r\n style=\"flex: 3;\"\r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">模糊距离:</div>\r\n <Slider\r\n :min=\"1\"\r\n :max=\"20\"\r\n :step=\"1\"\r\n :value=\"shadow.blur\"\r\n @change=\"value => updateShadow({ blur: value })\" \r\n style=\"flex: 3;\"\r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">阴影颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"shadow.color\"\r\n @update:modelValue=\"value => updateShadow({ color: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"shadow.color\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTElementShadow } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-shadow',\r\n components: {\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const shadow = ref<PPTElementShadow>()\r\n const hasShadow = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n shadow.value = 'shadow' in handleElement.value ? handleElement.value.shadow : undefined\r\n hasShadow.value = !!shadow.value\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateShadow = (shadowProps: Partial<PPTElementShadow>) => {\r\n const props = { shadow: { ...shadow.value, ...shadowProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n const toggleShadow = (checked: boolean) => {\r\n if (checked) {\r\n const props = { shadow: { h: 1, v: 1, blur: 2, color: '#000' } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'shadow' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n shadow,\r\n hasShadow,\r\n toggleShadow,\r\n updateShadow,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.switch-wrapper {\r\n text-align: right;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, PPTElementShadow } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-shadow',\r\n components: {\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const shadow = ref<PPTElementShadow>()\r\n const hasShadow = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n shadow.value = 'shadow' in handleElement.value ? handleElement.value.shadow : undefined\r\n hasShadow.value = !!shadow.value\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateShadow = (shadowProps: Partial<PPTElementShadow>) => {\r\n const props = { shadow: { ...shadow.value, ...shadowProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n const toggleShadow = (checked: boolean) => {\r\n if (checked) {\r\n const props = { shadow: { h: 1, v: 1, blur: 2, color: '#000' } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'shadow' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n shadow,\r\n hasShadow,\r\n toggleShadow,\r\n updateShadow,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementShadow.vue?vue&type=template&id=5cca6474&scoped=true\"\nimport script from \"./ElementShadow.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementShadow.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementShadow.vue?vue&type=style&index=0&id=5cca6474&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5cca6474\"\n\nexport default script","\r\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { TextAttrs } from '@/prosemirror/utils'\r\nimport { WEB_FONTS } from '@/configs/font'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOpacity from '../common/ElementOpacity.vue'\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\n\r\nconst presetStyles = [\r\n {\r\n label: '大标题',\r\n style: {\r\n fontSize: '26px',\r\n fontWeight: 700,\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '48px' },\r\n { command: 'align', value: 'center' },\r\n { command: 'bold' },\r\n ],\r\n },\r\n {\r\n label: '小标题',\r\n style: {\r\n fontSize: '22px',\r\n fontWeight: 700,\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '36px' },\r\n { command: 'align', value: 'center' },\r\n { command: 'bold' },\r\n ],\r\n },\r\n {\r\n label: '正文',\r\n style: {\r\n fontSize: '20px',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '20px' },\r\n ],\r\n },\r\n {\r\n label: '正文[小]',\r\n style: {\r\n fontSize: '18px',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '18px' },\r\n ],\r\n },\r\n {\r\n label: '注释 1',\r\n style: {\r\n fontSize: '16px',\r\n fontStyle: 'italic',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '16px' },\r\n { command: 'em' },\r\n ],\r\n },\r\n {\r\n label: '注释 2',\r\n style: {\r\n fontSize: '16px',\r\n textDecoration: 'underline',\r\n },\r\n cmd: [\r\n { command: 'clear' },\r\n { command: 'fontsize', value: '16px' },\r\n { command: 'underline' },\r\n ],\r\n },\r\n]\r\n\r\nconst webFonts = WEB_FONTS\r\n\r\ninterface CommandPayload {\r\n command: string;\r\n value?: string;\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'text-style-panel',\r\n components: {\r\n ElementOpacity,\r\n ElementOutline,\r\n ElementShadow,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTTextElement>(() => store.getters.handleElement)\r\n\r\n const fill = ref<string>()\r\n const lineHeight = ref<number>()\r\n const wordSpace = ref<number>()\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'text') return\r\n\r\n fill.value = handleElement.value.fill || '#000'\r\n lineHeight.value = handleElement.value.lineHeight || 1.5\r\n wordSpace.value = handleElement.value.wordSpace || 0\r\n }, { deep: true, immediate: true })\r\n\r\n const richTextAttrs = ref<TextAttrs>({\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n superscript: false,\r\n subscript: false,\r\n code: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '20px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n bulletList: false,\r\n orderedList: false,\r\n blockquote: false,\r\n })\r\n\r\n const availableFonts = computed(() => store.state.availableFonts)\r\n const fontSizeOptions = [\r\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\r\n '36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '76px',\r\n '80px', '88px', '96px', '104px', '112px', '120px',\r\n ]\r\n const lineHeightOptions = [0.9, 1.0, 1.15, 1.2, 1.4, 1.5, 1.8, 2.0, 2.5, 3.0]\r\n const wordSpaceOptions = [0, 1, 2, 3, 4, 5, 6, 8, 10]\r\n\r\n // 接收并更新当前光标所在位置的富文本状态\r\n const updateRichTextAttrs = (attr: TextAttrs) => richTextAttrs.value = attr\r\n\r\n emitter.on(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\r\n })\r\n\r\n // 发射富文本设置命令\r\n const emitRichTextCommand = (command: string, value?: string) => {\r\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value })\r\n }\r\n\r\n // 发射富文本设置命令(批量)\r\n const emitBatchRichTextCommand = (payload: CommandPayload[]) => {\r\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, payload)\r\n }\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置行高\r\n const updateLineHeight = (value: number) => {\r\n const props = { lineHeight: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置字间距\r\n const updateWordSpace = (value: number) => {\r\n const props = { wordSpace: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置文本框填充\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n fill,\r\n lineHeight,\r\n wordSpace,\r\n richTextAttrs,\r\n availableFonts,\r\n webFonts,\r\n fontSizeOptions,\r\n lineHeightOptions,\r\n wordSpaceOptions,\r\n updateLineHeight,\r\n updateWordSpace,\r\n updateFill,\r\n emitRichTextCommand,\r\n emitBatchRichTextCommand,\r\n presetStyles,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TextStylePanel.vue?vue&type=template&id=43fccffc&scoped=true\"\nimport script from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TextStylePanel.vue?vue&type=style&index=0&id=43fccffc&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-43fccffc\"\n\nexport default script","<template>\r\n <div class=\"image-style-panel\">\r\n <div \r\n class=\"origin-image\"\r\n :style=\"{ backgroundImage: `url(${handleElement.src})` }\"\r\n ></div>\r\n\r\n <ButtonGroup class=\"row\">\r\n <Button style=\"flex: 5;\" @click=\"clipImage()\"><IconTailoring class=\"btn-icon\" /> 裁剪图片</Button>\r\n <Popover trigger=\"click\" v-model:visible=\"clipPanelVisible\">\r\n <template #content>\r\n <div class=\"clip\">\r\n <div class=\"title\">按形状裁剪:</div>\r\n <div class=\"shape-clip\">\r\n <div \r\n class=\"shape-clip-item\" \r\n v-for=\"(item, index) in shapeClipPathOptions\" \r\n :key=\"index\"\r\n @click=\"presetImageClip(index)\"\r\n >\r\n <div class=\"shape\" :style=\"{ backgroundImage: `url(${handleElement.src})`, clipPath: item.style }\"></div>\r\n </div>\r\n </div>\r\n\r\n <template v-for=\"type in ratioClipOptions\" :key=\"type.label\">\r\n <div class=\"title\" v-if=\"type.label\">{{type.label}}:</div>\r\n <ButtonGroup class=\"row\">\r\n <Button \r\n style=\"flex: 1;\"\r\n v-for=\"item in type.children\"\r\n :key=\"item.key\"\r\n @click=\"presetImageClip('rect', item.ratio)\"\r\n >{{item.key}}</Button>\r\n </ButtonGroup>\r\n </template>\r\n </div>\r\n </template>\r\n <Button class=\"no-padding\" style=\"flex: 1;\"><IconDown /></Button>\r\n </Popover>\r\n </ButtonGroup>\r\n\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <div class=\"filter\">\r\n <div class=\"filter-item\" v-for=\"filter in filterOptions\" :key=\"filter.key\">\r\n <div class=\"name\">{{filter.label}}</div>\r\n <Slider\r\n class=\"filter-slider\"\r\n :max=\"filter.max\"\r\n :min=\"filter.min\"\r\n :step=\"filter.step\"\r\n :value=\"filter.value\"\r\n @change=\"value => updateFilter(filter, value)\"\r\n />\r\n <div class=\"value\">{{`${filter.value}${filter.unit}`}}</div>\r\n </div>\r\n </div>\r\n </template>\r\n <Button class=\"full-width-btn\"><IconColorFilter class=\"btn-icon\" /> 设置滤镜</Button>\r\n </Popover>\r\n \r\n <ElementFlip />\r\n <Divider />\r\n <ElementOutline />\r\n <Divider />\r\n <ElementShadow />\r\n <Divider />\r\n \r\n <FileInput @change=\"files => replaceImage(files)\">\r\n <Button class=\"full-width-btn\"><IconTransform class=\"btn-icon\" /> 替换图片</Button>\r\n </FileInput>\r\n <Button class=\"full-width-btn\" @click=\"resetImage()\"><IconUndo class=\"btn-icon\" /> 重置样式</Button>\r\n <Button class=\"full-width-btn\" @click=\"setBackgroundImage()\"><IconTheme class=\"btn-icon\" /> 设为背景</Button>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement, Slide } from '@/types/slides'\r\nimport { CLIPPATHS } from '@/configs/imageClip'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ElementFlip from '../common/ElementFlip.vue'\r\n\r\ninterface FilterOption {\r\n label: string;\r\n key: string;\r\n default: number;\r\n value: number;\r\n unit: string;\r\n max: number;\r\n step: number;\r\n}\r\n\r\nconst defaultFilters: FilterOption[] = [\r\n { label: '模糊', key: 'blur', default: 0, value: 0, unit: 'px', max: 10, step: 1 },\r\n { label: '亮度', key: 'brightness', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '对比度', key: 'contrast', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '灰度', key: 'grayscale', default: 0, value: 0, unit: '%', max: 100, step: 5 },\r\n { label: '饱和度', key: 'saturate', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '色相', key: 'hue-rotate', default: 0, value: 0, unit: 'deg', max: 360, step: 10 },\r\n { label: '不透明度', key: 'opacity', default: 100, value: 100, unit: '%', max: 100, step: 5 },\r\n]\r\n\r\nconst shapeClipPathOptions = CLIPPATHS\r\nconst ratioClipOptions = [\r\n {\r\n label: '纵横比(方形)',\r\n children: [\r\n { key: '1:1', ratio: 1 / 1 },\r\n ],\r\n },\r\n {\r\n label: '纵横比(纵向)',\r\n children: [\r\n { key: '2:3', ratio: 3 / 2 },\r\n { key: '3:4', ratio: 4 / 3 },\r\n { key: '3:5', ratio: 5 / 3 },\r\n { key: '4:5', ratio: 5 / 4 },\r\n ],\r\n },\r\n {\r\n label: '纵横比(横向)',\r\n children: [\r\n { key: '3:2', ratio: 2 / 3 },\r\n { key: '4:3', ratio: 3 / 4 },\r\n { key: '5:3', ratio: 3 / 5 },\r\n { key: '5:4', ratio: 4 / 5 },\r\n ],\r\n },\r\n {\r\n children: [\r\n { key: '16:9', ratio: 9 / 16 },\r\n { key: '16:10', ratio: 10 / 16 },\r\n ],\r\n },\r\n]\r\n\r\nexport default defineComponent({\r\n name: 'image-style-panel',\r\n components: {\r\n ElementOutline,\r\n ElementShadow,\r\n ElementFlip,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTImageElement>(() => store.getters.handleElement)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const clipPanelVisible = ref(false)\r\n\r\n const filterOptions = ref<FilterOption[]>(JSON.parse(JSON.stringify(defaultFilters)))\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'image') return\r\n \r\n const filters = handleElement.value.filters\r\n if (filters) {\r\n filterOptions.value = defaultFilters.map(item => {\r\n if (filters[item.key] !== undefined) return { ...item, value: parseInt(filters[item.key]) }\r\n return item\r\n })\r\n }\r\n else filterOptions.value = JSON.parse(JSON.stringify(defaultFilters))\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置滤镜\r\n const updateFilter = (filter: FilterOption, value: number) => {\r\n const originFilters = handleElement.value.filters || {}\r\n const filters = { ...originFilters, [filter.key]: `${value}${filter.unit}` }\r\n const props = { filters }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 打开自由裁剪\r\n const clipImage = () => {\r\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, handleElement.value.id)\r\n clipPanelVisible.value = false\r\n }\r\n\r\n // 获取原始图片的位置大小\r\n const getImageElementDataBeforeClip = () => {\r\n\r\n // 图片当前的位置大小和裁剪范围\r\n const imgWidth = handleElement.value.width\r\n const imgHeight = handleElement.value.height\r\n const imgLeft = handleElement.value.left\r\n const imgTop = handleElement.value.top\r\n const originClipRange = handleElement.value.clip ? handleElement.value.clip.range : [[0, 0], [100, 100]]\r\n\r\n const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)\r\n const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)\r\n const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100)\r\n const originTop = imgTop - originHeight * (originClipRange[0][1] / 100)\r\n\r\n return {\r\n originClipRange,\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n }\r\n }\r\n\r\n // 预设裁剪\r\n const presetImageClip = (shape: string, ratio = 0) => {\r\n const {\r\n originClipRange,\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n } = getImageElementDataBeforeClip()\r\n \r\n // 纵横比裁剪(形状固定为矩形)\r\n if (ratio) {\r\n const imageRatio = originHeight / originWidth\r\n\r\n const min = 0\r\n const max = 100\r\n let range\r\n\r\n if (imageRatio > ratio) {\r\n const distance = ((1 - ratio / imageRatio) / 2) * 100\r\n range = [[min, distance], [max, max - distance]]\r\n }\r\n else {\r\n const distance = ((1 - imageRatio / ratio) / 2) * 100\r\n range = [[distance, min], [max - distance, max]]\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n clip: { ...handleElement.value.clip, shape, range },\r\n left: originLeft + originWidth * (range[0][0] / 100),\r\n top: originTop + originHeight * (range[0][1] / 100),\r\n width: originWidth * (range[1][0] - range[0][0]) / 100,\r\n height: originHeight * (range[1][1] - range[0][1]) / 100,\r\n },\r\n })\r\n }\r\n // 形状裁剪(保持当前裁剪范围)\r\n else {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n clip: { ...handleElement.value.clip, shape, range: originClipRange }\r\n },\r\n })\r\n }\r\n clipImage()\r\n addHistorySnapshot()\r\n }\r\n\r\n // 替换图片(保持当前的样式)\r\n const replaceImage = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => {\r\n const props = { src: dataURL }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 重置图片:清除全部样式\r\n const resetImage = () => {\r\n if (handleElement.value.clip) {\r\n const {\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n } = getImageElementDataBeforeClip()\r\n\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n left: originLeft,\r\n top: originTop,\r\n width: originWidth,\r\n height: originHeight,\r\n },\r\n })\r\n }\r\n\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\r\n id: handleElement.value.id,\r\n propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将图片设置为背景\r\n const setBackgroundImage = () => {\r\n const background = {\r\n ...currentSlide.value.background,\r\n type: 'image',\r\n image: handleElement.value.src,\r\n imageSize: 'cover',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n clipPanelVisible,\r\n shapeClipPathOptions,\r\n ratioClipOptions,\r\n filterOptions,\r\n handleElement,\r\n updateFilter,\r\n clipImage,\r\n presetImageClip,\r\n replaceImage,\r\n resetImage,\r\n setBackgroundImage,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.switch-wrapper {\r\n text-align: right;\r\n}\r\n.origin-image {\r\n height: 100px;\r\n background-size: contain;\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n background-color: $lightGray;\r\n margin-bottom: 10px;\r\n}\r\n.full-width-btn {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n}\r\n.btn-icon {\r\n margin-right: 3px;\r\n}\r\n\r\n.filter {\r\n width: 280px;\r\n font-size: 12px;\r\n}\r\n.filter-item {\r\n padding: 8px 5px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n\r\n .name {\r\n width: 60px;\r\n }\r\n .filter-slider {\r\n flex: 1;\r\n margin: 0 6px;\r\n }\r\n .value {\r\n width: 40px;\r\n text-align: right;\r\n }\r\n}\r\n\r\n.clip {\r\n width: 260px;\r\n font-size: 12px;\r\n\r\n .title {\r\n margin-bottom: 5px;\r\n }\r\n}\r\n.shape-clip {\r\n margin-bottom: 10px;\r\n\r\n @include flex-grid-layout();\r\n}\r\n.shape-clip-item {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n\r\n @include flex-grid-layout-children(5, 16%);\r\n\r\n .shape {\r\n width: 40px;\r\n height: 40px;\r\n background-position: center;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n }\r\n}\r\n</style>","<template>\r\n <div class=\"element-flip\">\r\n <CheckboxButtonGroup class=\"row\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"flip.x === 180\"\r\n @click=\"updateFlip({ x: flip.x === 180 ? 0 : 180, y: flip.y })\"\r\n ><IconFlipVertically /> 水平翻转</CheckboxButton>\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"flip.y === 180\"\r\n @click=\"updateFlip({ x: flip.x, y: flip.y === 180 ? 0 : 180 })\"\r\n ><IconFlipHorizontally /> 垂直翻转</CheckboxButton>\r\n </CheckboxButtonGroup>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement, PPTShapeElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-flip',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTImageElement | PPTShapeElement>(() => store.getters.handleElement)\r\n\r\n const flip = ref({\r\n x: 0,\r\n y: 0,\r\n })\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || !['image', 'shape'].includes(handleElement.value.type)) return\r\n\r\n if (handleElement.value.flip) {\r\n flip.value = {\r\n x: handleElement.value.flip.x || 0,\r\n y: handleElement.value.flip.y || 0,\r\n }\r\n }\r\n else flip.value = { x: 0, y: 0 }\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateFlip = (value: number) => {\r\n const props = { flip: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n flip,\r\n updateFlip,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement, PPTShapeElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-flip',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTImageElement | PPTShapeElement>(() => store.getters.handleElement)\r\n\r\n const flip = ref({\r\n x: 0,\r\n y: 0,\r\n })\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || !['image', 'shape'].includes(handleElement.value.type)) return\r\n\r\n if (handleElement.value.flip) {\r\n flip.value = {\r\n x: handleElement.value.flip.x || 0,\r\n y: handleElement.value.flip.y || 0,\r\n }\r\n }\r\n else flip.value = { x: 0, y: 0 }\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateFlip = (value: number) => {\r\n const props = { flip: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n flip,\r\n updateFlip,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementFlip.vue?vue&type=template&id=b6fdb886&scoped=true\"\nimport script from \"./ElementFlip.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementFlip.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementFlip.vue?vue&type=style&index=0&id=b6fdb886&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b6fdb886\"\n\nexport default script","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTImageElement, Slide } from '@/types/slides'\r\nimport { CLIPPATHS } from '@/configs/imageClip'\r\nimport { getImageDataURL } from '@/utils/image'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ElementFlip from '../common/ElementFlip.vue'\r\n\r\ninterface FilterOption {\r\n label: string;\r\n key: string;\r\n default: number;\r\n value: number;\r\n unit: string;\r\n max: number;\r\n step: number;\r\n}\r\n\r\nconst defaultFilters: FilterOption[] = [\r\n { label: '模糊', key: 'blur', default: 0, value: 0, unit: 'px', max: 10, step: 1 },\r\n { label: '亮度', key: 'brightness', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '对比度', key: 'contrast', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '灰度', key: 'grayscale', default: 0, value: 0, unit: '%', max: 100, step: 5 },\r\n { label: '饱和度', key: 'saturate', default: 100, value: 100, unit: '%', max: 200, step: 5 },\r\n { label: '色相', key: 'hue-rotate', default: 0, value: 0, unit: 'deg', max: 360, step: 10 },\r\n { label: '不透明度', key: 'opacity', default: 100, value: 100, unit: '%', max: 100, step: 5 },\r\n]\r\n\r\nconst shapeClipPathOptions = CLIPPATHS\r\nconst ratioClipOptions = [\r\n {\r\n label: '纵横比(方形)',\r\n children: [\r\n { key: '1:1', ratio: 1 / 1 },\r\n ],\r\n },\r\n {\r\n label: '纵横比(纵向)',\r\n children: [\r\n { key: '2:3', ratio: 3 / 2 },\r\n { key: '3:4', ratio: 4 / 3 },\r\n { key: '3:5', ratio: 5 / 3 },\r\n { key: '4:5', ratio: 5 / 4 },\r\n ],\r\n },\r\n {\r\n label: '纵横比(横向)',\r\n children: [\r\n { key: '3:2', ratio: 2 / 3 },\r\n { key: '4:3', ratio: 3 / 4 },\r\n { key: '5:3', ratio: 3 / 5 },\r\n { key: '5:4', ratio: 4 / 5 },\r\n ],\r\n },\r\n {\r\n children: [\r\n { key: '16:9', ratio: 9 / 16 },\r\n { key: '16:10', ratio: 10 / 16 },\r\n ],\r\n },\r\n]\r\n\r\nexport default defineComponent({\r\n name: 'image-style-panel',\r\n components: {\r\n ElementOutline,\r\n ElementShadow,\r\n ElementFlip,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTImageElement>(() => store.getters.handleElement)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const clipPanelVisible = ref(false)\r\n\r\n const filterOptions = ref<FilterOption[]>(JSON.parse(JSON.stringify(defaultFilters)))\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'image') return\r\n \r\n const filters = handleElement.value.filters\r\n if (filters) {\r\n filterOptions.value = defaultFilters.map(item => {\r\n if (filters[item.key] !== undefined) return { ...item, value: parseInt(filters[item.key]) }\r\n return item\r\n })\r\n }\r\n else filterOptions.value = JSON.parse(JSON.stringify(defaultFilters))\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置滤镜\r\n const updateFilter = (filter: FilterOption, value: number) => {\r\n const originFilters = handleElement.value.filters || {}\r\n const filters = { ...originFilters, [filter.key]: `${value}${filter.unit}` }\r\n const props = { filters }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 打开自由裁剪\r\n const clipImage = () => {\r\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, handleElement.value.id)\r\n clipPanelVisible.value = false\r\n }\r\n\r\n // 获取原始图片的位置大小\r\n const getImageElementDataBeforeClip = () => {\r\n\r\n // 图片当前的位置大小和裁剪范围\r\n const imgWidth = handleElement.value.width\r\n const imgHeight = handleElement.value.height\r\n const imgLeft = handleElement.value.left\r\n const imgTop = handleElement.value.top\r\n const originClipRange = handleElement.value.clip ? handleElement.value.clip.range : [[0, 0], [100, 100]]\r\n\r\n const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)\r\n const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)\r\n const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100)\r\n const originTop = imgTop - originHeight * (originClipRange[0][1] / 100)\r\n\r\n return {\r\n originClipRange,\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n }\r\n }\r\n\r\n // 预设裁剪\r\n const presetImageClip = (shape: string, ratio = 0) => {\r\n const {\r\n originClipRange,\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n } = getImageElementDataBeforeClip()\r\n \r\n // 纵横比裁剪(形状固定为矩形)\r\n if (ratio) {\r\n const imageRatio = originHeight / originWidth\r\n\r\n const min = 0\r\n const max = 100\r\n let range\r\n\r\n if (imageRatio > ratio) {\r\n const distance = ((1 - ratio / imageRatio) / 2) * 100\r\n range = [[min, distance], [max, max - distance]]\r\n }\r\n else {\r\n const distance = ((1 - imageRatio / ratio) / 2) * 100\r\n range = [[distance, min], [max - distance, max]]\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n clip: { ...handleElement.value.clip, shape, range },\r\n left: originLeft + originWidth * (range[0][0] / 100),\r\n top: originTop + originHeight * (range[0][1] / 100),\r\n width: originWidth * (range[1][0] - range[0][0]) / 100,\r\n height: originHeight * (range[1][1] - range[0][1]) / 100,\r\n },\r\n })\r\n }\r\n // 形状裁剪(保持当前裁剪范围)\r\n else {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n clip: { ...handleElement.value.clip, shape, range: originClipRange }\r\n },\r\n })\r\n }\r\n clipImage()\r\n addHistorySnapshot()\r\n }\r\n\r\n // 替换图片(保持当前的样式)\r\n const replaceImage = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => {\r\n const props = { src: dataURL }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 重置图片:清除全部样式\r\n const resetImage = () => {\r\n if (handleElement.value.clip) {\r\n const {\r\n originWidth,\r\n originHeight,\r\n originLeft,\r\n originTop,\r\n } = getImageElementDataBeforeClip()\r\n\r\n store.commit(MutationTypes.UPDATE_ELEMENT, {\r\n id: handleElement.value.id,\r\n props: {\r\n left: originLeft,\r\n top: originTop,\r\n width: originWidth,\r\n height: originHeight,\r\n },\r\n })\r\n }\r\n\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\r\n id: handleElement.value.id,\r\n propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],\r\n })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将图片设置为背景\r\n const setBackgroundImage = () => {\r\n const background = {\r\n ...currentSlide.value.background,\r\n type: 'image',\r\n image: handleElement.value.src,\r\n imageSize: 'cover',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n clipPanelVisible,\r\n shapeClipPathOptions,\r\n ratioClipOptions,\r\n filterOptions,\r\n handleElement,\r\n updateFilter,\r\n clipImage,\r\n presetImageClip,\r\n replaceImage,\r\n resetImage,\r\n setBackgroundImage,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageStylePanel.vue?vue&type=template&id=5685b9e0&scoped=true\"\nimport script from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageStylePanel.vue?vue&type=style&index=0&id=5685b9e0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5685b9e0\"\n\nexport default script","<template>\r\n <div class=\"shape-style-panel\">\r\n <div class=\"row\">\r\n <Select \r\n style=\"flex: 10;\" \r\n :value=\"fillType\" \r\n @change=\"value => updateFillType(value)\"\r\n >\r\n <SelectOption value=\"fill\">纯色填充</SelectOption>\r\n <SelectOption value=\"gradient\">渐变填充</SelectOption>\r\n </Select>\r\n <div style=\"flex: 1;\"></div>\r\n <Popover trigger=\"click\" v-if=\"fillType === 'fill'\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"fill\"\r\n @update:modelValue=\"value => updateFill(value)\"\r\n />\r\n </template>\r\n <ColorButton :color=\"fill\" style=\"flex: 10;\" />\r\n </Popover>\r\n <Select \r\n style=\"flex: 10;\" \r\n :value=\"gradient.type\" \r\n @change=\"value => updateGradient({ type: value })\"\r\n v-else\r\n >\r\n <SelectOption value=\"linear\">线性渐变</SelectOption>\r\n <SelectOption value=\"radial\">径向渐变</SelectOption>\r\n </Select>\r\n </div>\r\n \r\n <template v-if=\"fillType === 'gradient'\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">起点颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"gradient.color[0]\"\r\n @update:modelValue=\"value => updateGradient({ color: [value, gradient.color[1]] })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"gradient.color[0]\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">终点颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"gradient.color[1]\"\r\n @update:modelValue=\"value => updateGradient({ color: [gradient.color[0], value] })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"gradient.color[1]\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\" v-if=\"gradient.type === 'linear'\">\r\n <div style=\"flex: 2;\">渐变角度:</div>\r\n <Slider\r\n :min=\"0\"\r\n :max=\"360\"\r\n :step=\"15\"\r\n :value=\"gradient.rotate\"\r\n style=\"flex: 3;\"\r\n @change=\"value => updateGradient({ rotate: value })\" \r\n />\r\n </div>\r\n </template>\r\n\r\n <ElementFlip />\r\n <Divider />\r\n <ElementOutline />\r\n <Divider />\r\n <ElementShadow />\r\n <Divider />\r\n <ElementOpacity />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTShapeElement, ShapeGradient } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOpacity from '../common/ElementOpacity.vue'\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ElementFlip from '../common/ElementFlip.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'shape-style-panel',\r\n components: {\r\n ElementOpacity,\r\n ElementOutline,\r\n ElementShadow,\r\n ElementFlip,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTShapeElement>(() => store.getters.handleElement)\r\n\r\n const fill = ref<string>()\r\n const gradient = ref<ShapeGradient>()\r\n const fillType = ref('fill')\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'shape') return\r\n fill.value = handleElement.value.fill || '#000'\r\n\r\n gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }\r\n\r\n fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置填充类型:渐变、纯色\r\n const updateFillType = (type: 'gradient' | 'fill') => {\r\n if (type === 'fill') {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\r\n id: handleElement.value.id,\r\n propName: 'gradient',\r\n })\r\n }\r\n else {\r\n const props = { gradient: gradient.value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置渐变填充\r\n const updateGradient = (gradientProps: Partial<ShapeGradient>) => {\r\n const props = { gradient: { ...gradient.value, ...gradientProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置填充色\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n fill,\r\n gradient,\r\n fillType,\r\n updateFillType,\r\n updateFill,\r\n updateGradient,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTShapeElement, ShapeGradient } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOpacity from '../common/ElementOpacity.vue'\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ElementFlip from '../common/ElementFlip.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'shape-style-panel',\r\n components: {\r\n ElementOpacity,\r\n ElementOutline,\r\n ElementShadow,\r\n ElementFlip,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTShapeElement>(() => store.getters.handleElement)\r\n\r\n const fill = ref<string>()\r\n const gradient = ref<ShapeGradient>()\r\n const fillType = ref('fill')\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'shape') return\r\n fill.value = handleElement.value.fill || '#000'\r\n\r\n gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }\r\n\r\n fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置填充类型:渐变、纯色\r\n const updateFillType = (type: 'gradient' | 'fill') => {\r\n if (type === 'fill') {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\r\n id: handleElement.value.id,\r\n propName: 'gradient',\r\n })\r\n }\r\n else {\r\n const props = { gradient: gradient.value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置渐变填充\r\n const updateGradient = (gradientProps: Partial<ShapeGradient>) => {\r\n const props = { gradient: { ...gradient.value, ...gradientProps } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置填充色\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n fill,\r\n gradient,\r\n fillType,\r\n updateFillType,\r\n updateFill,\r\n updateGradient,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ShapeStylePanel.vue?vue&type=template&id=998a7a02&scoped=true\"\nimport script from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapeStylePanel.vue?vue&type=style&index=0&id=998a7a02&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-998a7a02\"\n\nexport default script","<template>\r\n <div class=\"line-style-panel\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">线条样式:</div>\r\n <Select \r\n style=\"flex: 3;\" \r\n :value=\"handleElement.style\" \r\n @change=\"value => updateLine({ style: value })\"\r\n >\r\n <SelectOption value=\"solid\">实线</SelectOption>\r\n <SelectOption value=\"dashed\">虚线</SelectOption>\r\n </Select>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">线条颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"handleElement.color\"\r\n @update:modelValue=\"value => updateLine({ color: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"handleElement.color\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">线条宽度:</div>\r\n <InputNumber \r\n :value=\"handleElement.width\" \r\n @change=\"value => updateLine({ width: value })\" \r\n style=\"flex: 3;\" \r\n />\r\n </div>\r\n \r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">起点样式:</div>\r\n <Select \r\n style=\"flex: 3;\" \r\n :value=\"handleElement.points[0]\" \r\n @change=\"value => updateLine({ points: [value, handleElement.points[1]] })\"\r\n >\r\n <SelectOption value=\"\">无</SelectOption>\r\n <SelectOption value=\"arrow\">箭头</SelectOption>\r\n <SelectOption value=\"dot\">圆点</SelectOption>\r\n </Select>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">终点样式:</div>\r\n <Select \r\n style=\"flex: 3;\" \r\n :value=\"handleElement.points[1]\" \r\n @change=\"value => updateLine({ points: [handleElement.points[0], value] })\"\r\n >\r\n <SelectOption value=\"\">无</SelectOption>\r\n <SelectOption value=\"arrow\">箭头</SelectOption>\r\n <SelectOption value=\"dot\">圆点</SelectOption>\r\n </Select>\r\n </div>\r\n\r\n <Divider />\r\n <ElementShadow />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'line-style-panel',\r\n components: {\r\n ElementShadow,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTLineElement>(() => store.getters.handleElement)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateLine = (props: Partial<PPTLineElement>) => {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n updateLine,\r\n }\r\n }\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.line-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 !important;\r\n\r\n .line-wrapper {\r\n margin-left: 8px;\r\n }\r\n}\r\n.line-wrapper {\r\n overflow: visible;\r\n}\r\n.line-btn-icon {\r\n width: 30px;\r\n font-size: 12px;\r\n margin-top: 2px;\r\n color: #bfbfbf;\r\n}\r\n.preset-point-style {\r\n padding: 0 10px;\r\n\r\n & + .preset-point-style {\r\n margin-top: 10px;\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTLineElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementShadow from '../common/ElementShadow.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'line-style-panel',\r\n components: {\r\n ElementShadow,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTLineElement>(() => store.getters.handleElement)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateLine = (props: Partial<PPTLineElement>) => {\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n updateLine,\r\n }\r\n }\r\n})\r\n","import { render } from \"./LineStylePanel.vue?vue&type=template&id=65b24fb3&scoped=true\"\nimport script from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./LineStylePanel.vue?vue&type=style&index=0&id=65b24fb3&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-65b24fb3\"\n\nexport default script","<template>\r\n <div class=\"chart-style-panel\">\r\n <Button class=\"full-width-btn\" @click=\"chartDataEditorVisible = true\">\r\n <IconEdit class=\"btn-icon\" /> 编辑图表数据\r\n </Button>\r\n\r\n <Divider />\r\n\r\n <template v-if=\"handleElement.chartType === 'line'\">\r\n <div class=\"row\">\r\n <Checkbox \r\n @change=\"e => updateOptions({ showArea: e.target.checked })\"\r\n :checked=\"showArea\" \r\n style=\"flex: 1;\"\r\n >面积图样式</Checkbox>\r\n <Checkbox \r\n @change=\"e => updateOptions({ showLine: !e.target.checked })\"\r\n :checked=\"!showLine\" \r\n style=\"flex: 1;\"\r\n >散点图样式</Checkbox>\r\n </div>\r\n <div class=\"row\">\r\n <Checkbox \r\n @change=\"e => updateOptions({ lineSmooth: e.target.checked })\" \r\n :checked=\"lineSmooth\"\r\n >使用平滑曲线</Checkbox>\r\n </div>\r\n </template>\r\n <div class=\"row\" v-if=\"handleElement.chartType === 'bar'\">\r\n <Checkbox \r\n @change=\"e => updateOptions({ horizontalBars: e.target.checked })\" \r\n :checked=\"horizontalBars\"\r\n >条形图样式</Checkbox>\r\n </div>\r\n <div class=\"row\" v-if=\"handleElement.chartType === 'pie'\">\r\n <Checkbox \r\n @change=\"e => updateOptions({ donut: e.target.checked })\" \r\n :checked=\"donut\"\r\n >环形图样式</Checkbox>\r\n </div>\r\n\r\n <Divider />\r\n\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">背景填充:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"fill\"\r\n @update:modelValue=\"value => updateFill(value)\"\r\n />\r\n </template>\r\n <ColorButton :color=\"fill\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">主题配色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"themeColor\"\r\n @update:modelValue=\"value => updateTheme(value)\"\r\n />\r\n </template>\r\n <ColorButton :color=\"themeColor\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">网格颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"gridColor\"\r\n @update:modelValue=\"value => updateGridColor(value)\"\r\n />\r\n </template>\r\n <ColorButton :color=\"gridColor\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n\r\n <Divider />\r\n <ElementOutline />\r\n\r\n <Modal\r\n v-model:visible=\"chartDataEditorVisible\" \r\n :footer=\"null\" \r\n centered\r\n :closable=\"false\"\r\n :width=\"648\"\r\n destroyOnClose\r\n >\r\n <ChartDataEditor \r\n :data=\"handleElement.data\"\r\n @close=\"chartDataEditorVisible = false\"\r\n @save=\"value => updateData(value)\"\r\n />\r\n </Modal>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ChartData, PPTChartElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '../../common/ElementOutline.vue'\r\nimport ColorButton from '../../common/ColorButton.vue'\r\nimport ChartDataEditor from './ChartDataEditor.vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-style-panel',\r\n components: {\r\n ElementOutline,\r\n ChartDataEditor,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTChartElement>(() => store.getters.handleElement)\r\n\r\n const chartDataEditorVisible = ref(false)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const fill = ref<string>()\r\n\r\n const themeColor = ref<string>('')\r\n const gridColor = ref('')\r\n\r\n const lineSmooth = ref<boolean | Function>(true)\r\n const showLine = ref(true)\r\n const showArea = ref(false)\r\n const horizontalBars = ref(false)\r\n const donut = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'chart') return\r\n fill.value = handleElement.value.fill || '#000'\r\n\r\n if (handleElement.value.options) {\r\n const {\r\n lineSmooth: _lineSmooth,\r\n showLine: _showLine,\r\n showArea: _showArea,\r\n horizontalBars: _horizontalBars,\r\n donut: _donut,\r\n } = handleElement.value.options\r\n\r\n if (_lineSmooth !== undefined) lineSmooth.value = _lineSmooth\r\n if (_showLine !== undefined) showLine.value = _showLine\r\n if (_showArea !== undefined) showArea.value = _showArea\r\n if (_horizontalBars !== undefined) horizontalBars.value = _horizontalBars\r\n if (_donut !== undefined) donut.value = _donut\r\n }\r\n\r\n themeColor.value = handleElement.value.themeColor\r\n gridColor.value = handleElement.value.gridColor || 'rgba(0, 0, 0, 0.4)'\r\n }, { deep: true, immediate: true })\r\n\r\n // 设置图表数据\r\n const updateData = (data: ChartData) => {\r\n chartDataEditorVisible.value = false\r\n const props = { data }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置填充色\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置其他选项:柱状图转条形图、折线图转面积图、折线图转散点图、饼图转环形图、折线图开关平滑曲线\r\n const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => {\r\n const options = handleElement.value.options || {}\r\n const newOptions = { ...options, ...optionProps }\r\n const props = { options: newOptions }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置主题色\r\n const updateTheme = (themeColor: string) => {\r\n const props = { themeColor }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置网格颜色\r\n const updateGridColor = (gridColor: string) => {\r\n const props = { gridColor }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n chartDataEditorVisible,\r\n handleElement,\r\n updateData,\r\n fill,\r\n updateFill,\r\n lineSmooth,\r\n showLine,\r\n showArea,\r\n horizontalBars,\r\n donut,\r\n updateOptions,\r\n themeColor,\r\n gridColor,\r\n updateTheme,\r\n updateGridColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.full-width-btn {\r\n width: 100%;\r\n}\r\n.btn-icon {\r\n margin-right: 3px;\r\n}\r\n</style>","<template>\r\n <div class=\"chart-data-editor\">\r\n <div class=\"editor-content\">\r\n <div class=\"range-box\">\r\n <div \r\n class=\"temp-range\" \r\n :style=\"{\r\n width: tempRangeSize.width + 'px',\r\n height: tempRangeSize.height + 'px',\r\n }\"\r\n ></div>\r\n <div \r\n :class=\"['range-line', line.type]\" \r\n v-for=\"line in rangeLines\" \r\n :key=\"line.type\" \r\n :style=\"line.style\"\r\n ></div>\r\n <div \r\n class=\"resizable\" \r\n :style=\"resizablePointStyle\"\r\n @mousedown.stop=\"changeSelectRange($event)\"\r\n ></div>\r\n </div>\r\n <table>\r\n <tbody>\r\n <tr v-for=\"rowIndex in 30\" :key=\"rowIndex\">\r\n <td v-for=\"colIndex in 7\" :key=\"colIndex\" :class=\"{ 'head': colIndex === 1 && rowIndex <= selectedRange[1] }\">\r\n <input \r\n :class=\"['item', { 'selected': rowIndex <= selectedRange[1] && colIndex <= selectedRange[0] }]\"\r\n :id=\"`cell-${rowIndex - 1}-${colIndex - 1}`\"\r\n autocomplete=\"off\"\r\n >\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"btns\">\r\n <Button class=\"btn\" @click=\"closeEditor()\">取消</Button>\r\n <Button type=\"primary\" class=\"btn\" @click=\"getTableData()\">确认</Button>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { ChartData } from '@/types/slides'\r\nimport { computed, defineComponent, onMounted, PropType, ref } from 'vue'\r\n\r\nconst CELL_WIDTH = 100\r\nconst CELL_HEIGHT = 32\r\n\r\nexport default defineComponent({\r\n name: 'chart-data-editor',\r\n props: {\r\n data: {\r\n type: Object as PropType<ChartData>,\r\n required: true,\r\n }\r\n },\r\n setup(props, { emit }) {\r\n const selectedRange = ref([0, 0])\r\n const tempRangeSize = ref({ width: 0, height: 0 })\r\n\r\n // 当前选区的边框线条位置\r\n const rangeLines = computed(() => {\r\n const width = selectedRange.value[0] * CELL_WIDTH\r\n const height = selectedRange.value[1] * CELL_HEIGHT\r\n return [\r\n { type: 't', style: {width: width + 'px'} },\r\n { type: 'b', style: {top: height + 'px', width: width + 'px'} },\r\n { type: 'l', style: {height: height + 'px'} },\r\n { type: 'r', style: {left: width + 'px', height: height + 'px'} },\r\n ]\r\n })\r\n\r\n // 当前选区的缩放点位置\r\n const resizablePointStyle = computed(() => {\r\n const width = selectedRange.value[0] * CELL_WIDTH\r\n const height = selectedRange.value[1] * CELL_HEIGHT\r\n return { left: width + 'px', top: height + 'px' }\r\n })\r\n\r\n // 初始化图表数据:将数据格式化并填充到DOM\r\n const initData = () => {\r\n const _data: string[][] = []\r\n\r\n const { labels, series } = props.data\r\n const rowCount = labels.length\r\n const colCount = series.length\r\n\r\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\r\n const row = [labels[rowIndex]]\r\n for (let colIndex = 0; colIndex < colCount; colIndex++) {\r\n row.push(series[colIndex][rowIndex] + '')\r\n }\r\n _data.push(row)\r\n }\r\n\r\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\r\n for (let colIndex = 0; colIndex < colCount + 1; colIndex++) {\r\n const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\r\n if (!inputRef) continue\r\n inputRef.value = _data[rowIndex][colIndex] + ''\r\n }\r\n }\r\n\r\n selectedRange.value = [colCount + 1, rowCount]\r\n }\r\n\r\n onMounted(initData)\r\n\r\n // 获取当前图表DOM中的数据,整理格式化后传递出去\r\n const getTableData = () => {\r\n const [col, row] = selectedRange.value\r\n\r\n const labels: string[] = []\r\n const series: number[][] = []\r\n\r\n // 第一列为系列名,实际数据从第二列开始\r\n for (let rowIndex = 0; rowIndex < row; rowIndex++) {\r\n let labelsItem = `类别${rowIndex + 1}`\r\n const labelInputRef = document.querySelector(`#cell-${rowIndex}-0`) as HTMLInputElement\r\n if (labelInputRef && labelInputRef.value) labelsItem = labelInputRef.value\r\n labels.push(labelsItem)\r\n }\r\n\r\n for (let colIndex = 1; colIndex < col; colIndex++) {\r\n const seriesItem = []\r\n for (let rowIndex = 0; rowIndex < row; rowIndex++) {\r\n const valueInputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\r\n let value = 0\r\n if (valueInputRef && valueInputRef.value && !!(+valueInputRef.value)) {\r\n value = +valueInputRef.value\r\n }\r\n seriesItem.push(value)\r\n }\r\n series.push(seriesItem)\r\n }\r\n const data = { labels, series }\r\n emit('save', data)\r\n }\r\n\r\n // 关闭图表数据编辑器\r\n const closeEditor = () => emit('close')\r\n\r\n // 鼠标拖拽修改选中的数据范围\r\n const changeSelectRange = (e: MouseEvent) => {\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n const originWidth = selectedRange.value[0] * CELL_WIDTH\r\n const originHeight = selectedRange.value[1] * CELL_HEIGHT\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const x = currentPageX - startPageX\r\n const y = currentPageY - startPageY\r\n\r\n const width = originWidth + x\r\n const height = originHeight + y\r\n\r\n tempRangeSize.value = { width, height }\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n const endPageX = e.pageX\r\n const endPageY = e.pageY\r\n\r\n if (startPageX === endPageX && startPageY === endPageY) return\r\n\r\n // 拖拽结束时,范围超过格子一半自动扩大到下一格(如拖动到一格半多的位置,会自动扩展到两格,横竖都同理)\r\n let width = tempRangeSize.value.width\r\n let height = tempRangeSize.value.height\r\n if (width % CELL_WIDTH > CELL_WIDTH * 0.5) width = width + (CELL_WIDTH - width % CELL_WIDTH)\r\n if (height % CELL_HEIGHT > CELL_HEIGHT * 0.5) height = height + (CELL_HEIGHT - height % CELL_HEIGHT)\r\n\r\n let row = Math.round(height / CELL_HEIGHT)\r\n let col = Math.round(width / CELL_WIDTH)\r\n\r\n if (row < 3) row = 3\r\n if (col < 2) col = 2\r\n\r\n selectedRange.value = [col, row]\r\n tempRangeSize.value = { width: 0, height: 0 }\r\n }\r\n }\r\n\r\n return {\r\n tempRangeSize,\r\n rangeLines,\r\n resizablePointStyle,\r\n changeSelectRange,\r\n selectedRange,\r\n getTableData,\r\n closeEditor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.chart-data-editor {\r\n width: 600px;\r\n position: relative;\r\n}\r\n.editor-content {\r\n width: 100%;\r\n height: 360px;\r\n overflow: overlay;\r\n position: relative;\r\n border-right: 1px solid #ccc;\r\n border-bottom: 1px solid #ccc;\r\n}\r\n.range-box {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n z-index: 100;\r\n user-select: none;\r\n}\r\n.temp-range {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 0;\r\n height: 0;\r\n background-color: rgba($color: #888, $alpha: .3);\r\n}\r\n.range-line {\r\n position: absolute;\r\n width: 0;\r\n height: 0;\r\n left: 0;\r\n top: 0;\r\n border: 0 solid $themeColor;\r\n\r\n &.t {\r\n border-top-width: 1px;\r\n }\r\n &.b {\r\n border-bottom-width: 1px;\r\n }\r\n &.l {\r\n border-left-width: 1px;\r\n }\r\n &.r {\r\n border-right-width: 1px;\r\n }\r\n}\r\n.resizable {\r\n position: absolute;\r\n width: 12px;\r\n height: 12px;\r\n left: 0;\r\n top: 0;\r\n margin: -9px 0 0 -9px;\r\n cursor: nwse-resize;\r\n\r\n &::after {\r\n content: '';\r\n position: absolute;\r\n width: 4px;\r\n height: 12px;\r\n right: 0;\r\n top: 0;\r\n background-color: $themeColor;\r\n }\r\n &::before {\r\n content: '';\r\n position: absolute;\r\n width: 12px;\r\n height: 4px;\r\n right: 0;\r\n bottom: 0;\r\n background-color: $themeColor;\r\n }\r\n}\r\ntable {\r\n width: 100%;\r\n height: 100%;\r\n user-select: none;\r\n table-layout: fixed;\r\n\r\n td {\r\n text-align: center;\r\n border: 1px solid #ccc;\r\n vertical-align: middle;\r\n width: 100px;\r\n height: 32px;\r\n\r\n &.head {\r\n background-color: rgba($color: $themeColor, $alpha: .1);\r\n }\r\n }\r\n .item {\r\n width: 100%;\r\n height: 100%;\r\n border: 0;\r\n outline: 0;\r\n font-size: 13px;\r\n text-align: center;\r\n background-color: transparent;\r\n\r\n &.selected {\r\n background-color: rgba($color: $themeColor, $alpha: .02);\r\n }\r\n }\r\n}\r\n.btns {\r\n margin-top: 10px;\r\n text-align: right;\r\n\r\n .btn {\r\n margin-left: 10px;\r\n }\r\n}\r\n</style>","\r\nimport { ChartData } from '@/types/slides'\r\nimport { computed, defineComponent, onMounted, PropType, ref } from 'vue'\r\n\r\nconst CELL_WIDTH = 100\r\nconst CELL_HEIGHT = 32\r\n\r\nexport default defineComponent({\r\n name: 'chart-data-editor',\r\n props: {\r\n data: {\r\n type: Object as PropType<ChartData>,\r\n required: true,\r\n }\r\n },\r\n setup(props, { emit }) {\r\n const selectedRange = ref([0, 0])\r\n const tempRangeSize = ref({ width: 0, height: 0 })\r\n\r\n // 当前选区的边框线条位置\r\n const rangeLines = computed(() => {\r\n const width = selectedRange.value[0] * CELL_WIDTH\r\n const height = selectedRange.value[1] * CELL_HEIGHT\r\n return [\r\n { type: 't', style: {width: width + 'px'} },\r\n { type: 'b', style: {top: height + 'px', width: width + 'px'} },\r\n { type: 'l', style: {height: height + 'px'} },\r\n { type: 'r', style: {left: width + 'px', height: height + 'px'} },\r\n ]\r\n })\r\n\r\n // 当前选区的缩放点位置\r\n const resizablePointStyle = computed(() => {\r\n const width = selectedRange.value[0] * CELL_WIDTH\r\n const height = selectedRange.value[1] * CELL_HEIGHT\r\n return { left: width + 'px', top: height + 'px' }\r\n })\r\n\r\n // 初始化图表数据:将数据格式化并填充到DOM\r\n const initData = () => {\r\n const _data: string[][] = []\r\n\r\n const { labels, series } = props.data\r\n const rowCount = labels.length\r\n const colCount = series.length\r\n\r\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\r\n const row = [labels[rowIndex]]\r\n for (let colIndex = 0; colIndex < colCount; colIndex++) {\r\n row.push(series[colIndex][rowIndex] + '')\r\n }\r\n _data.push(row)\r\n }\r\n\r\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\r\n for (let colIndex = 0; colIndex < colCount + 1; colIndex++) {\r\n const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\r\n if (!inputRef) continue\r\n inputRef.value = _data[rowIndex][colIndex] + ''\r\n }\r\n }\r\n\r\n selectedRange.value = [colCount + 1, rowCount]\r\n }\r\n\r\n onMounted(initData)\r\n\r\n // 获取当前图表DOM中的数据,整理格式化后传递出去\r\n const getTableData = () => {\r\n const [col, row] = selectedRange.value\r\n\r\n const labels: string[] = []\r\n const series: number[][] = []\r\n\r\n // 第一列为系列名,实际数据从第二列开始\r\n for (let rowIndex = 0; rowIndex < row; rowIndex++) {\r\n let labelsItem = `类别${rowIndex + 1}`\r\n const labelInputRef = document.querySelector(`#cell-${rowIndex}-0`) as HTMLInputElement\r\n if (labelInputRef && labelInputRef.value) labelsItem = labelInputRef.value\r\n labels.push(labelsItem)\r\n }\r\n\r\n for (let colIndex = 1; colIndex < col; colIndex++) {\r\n const seriesItem = []\r\n for (let rowIndex = 0; rowIndex < row; rowIndex++) {\r\n const valueInputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\r\n let value = 0\r\n if (valueInputRef && valueInputRef.value && !!(+valueInputRef.value)) {\r\n value = +valueInputRef.value\r\n }\r\n seriesItem.push(value)\r\n }\r\n series.push(seriesItem)\r\n }\r\n const data = { labels, series }\r\n emit('save', data)\r\n }\r\n\r\n // 关闭图表数据编辑器\r\n const closeEditor = () => emit('close')\r\n\r\n // 鼠标拖拽修改选中的数据范围\r\n const changeSelectRange = (e: MouseEvent) => {\r\n let isMouseDown = true\r\n\r\n const startPageX = e.pageX\r\n const startPageY = e.pageY\r\n\r\n const originWidth = selectedRange.value[0] * CELL_WIDTH\r\n const originHeight = selectedRange.value[1] * CELL_HEIGHT\r\n\r\n document.onmousemove = e => {\r\n if (!isMouseDown) return\r\n\r\n const currentPageX = e.pageX\r\n const currentPageY = e.pageY\r\n\r\n const x = currentPageX - startPageX\r\n const y = currentPageY - startPageY\r\n\r\n const width = originWidth + x\r\n const height = originHeight + y\r\n\r\n tempRangeSize.value = { width, height }\r\n }\r\n\r\n document.onmouseup = e => {\r\n isMouseDown = false\r\n document.onmousemove = null\r\n document.onmouseup = null\r\n\r\n const endPageX = e.pageX\r\n const endPageY = e.pageY\r\n\r\n if (startPageX === endPageX && startPageY === endPageY) return\r\n\r\n // 拖拽结束时,范围超过格子一半自动扩大到下一格(如拖动到一格半多的位置,会自动扩展到两格,横竖都同理)\r\n let width = tempRangeSize.value.width\r\n let height = tempRangeSize.value.height\r\n if (width % CELL_WIDTH > CELL_WIDTH * 0.5) width = width + (CELL_WIDTH - width % CELL_WIDTH)\r\n if (height % CELL_HEIGHT > CELL_HEIGHT * 0.5) height = height + (CELL_HEIGHT - height % CELL_HEIGHT)\r\n\r\n let row = Math.round(height / CELL_HEIGHT)\r\n let col = Math.round(width / CELL_WIDTH)\r\n\r\n if (row < 3) row = 3\r\n if (col < 2) col = 2\r\n\r\n selectedRange.value = [col, row]\r\n tempRangeSize.value = { width: 0, height: 0 }\r\n }\r\n }\r\n\r\n return {\r\n tempRangeSize,\r\n rangeLines,\r\n resizablePointStyle,\r\n changeSelectRange,\r\n selectedRange,\r\n getTableData,\r\n closeEditor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ChartDataEditor.vue?vue&type=template&id=08aba838&scoped=true\"\nimport script from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartDataEditor.vue?vue&type=style&index=0&id=08aba838&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-08aba838\"\n\nexport default script","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ChartData, PPTChartElement } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ElementOutline from '../../common/ElementOutline.vue'\r\nimport ColorButton from '../../common/ColorButton.vue'\r\nimport ChartDataEditor from './ChartDataEditor.vue'\r\n\r\nexport default defineComponent({\r\n name: 'chart-style-panel',\r\n components: {\r\n ElementOutline,\r\n ChartDataEditor,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTChartElement>(() => store.getters.handleElement)\r\n\r\n const chartDataEditorVisible = ref(false)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const fill = ref<string>()\r\n\r\n const themeColor = ref<string>('')\r\n const gridColor = ref('')\r\n\r\n const lineSmooth = ref<boolean | Function>(true)\r\n const showLine = ref(true)\r\n const showArea = ref(false)\r\n const horizontalBars = ref(false)\r\n const donut = ref(false)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'chart') return\r\n fill.value = handleElement.value.fill || '#000'\r\n\r\n if (handleElement.value.options) {\r\n const {\r\n lineSmooth: _lineSmooth,\r\n showLine: _showLine,\r\n showArea: _showArea,\r\n horizontalBars: _horizontalBars,\r\n donut: _donut,\r\n } = handleElement.value.options\r\n\r\n if (_lineSmooth !== undefined) lineSmooth.value = _lineSmooth\r\n if (_showLine !== undefined) showLine.value = _showLine\r\n if (_showArea !== undefined) showArea.value = _showArea\r\n if (_horizontalBars !== undefined) horizontalBars.value = _horizontalBars\r\n if (_donut !== undefined) donut.value = _donut\r\n }\r\n\r\n themeColor.value = handleElement.value.themeColor\r\n gridColor.value = handleElement.value.gridColor || 'rgba(0, 0, 0, 0.4)'\r\n }, { deep: true, immediate: true })\r\n\r\n // 设置图表数据\r\n const updateData = (data: ChartData) => {\r\n chartDataEditorVisible.value = false\r\n const props = { data }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置填充色\r\n const updateFill = (value: string) => {\r\n const props = { fill: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置其他选项:柱状图转条形图、折线图转面积图、折线图转散点图、饼图转环形图、折线图开关平滑曲线\r\n const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => {\r\n const options = handleElement.value.options || {}\r\n const newOptions = { ...options, ...optionProps }\r\n const props = { options: newOptions }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置主题色\r\n const updateTheme = (themeColor: string) => {\r\n const props = { themeColor }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置网格颜色\r\n const updateGridColor = (gridColor: string) => {\r\n const props = { gridColor }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n chartDataEditorVisible,\r\n handleElement,\r\n updateData,\r\n fill,\r\n updateFill,\r\n lineSmooth,\r\n showLine,\r\n showArea,\r\n horizontalBars,\r\n donut,\r\n updateOptions,\r\n themeColor,\r\n gridColor,\r\n updateTheme,\r\n updateGridColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=4dd87e36&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=4dd87e36&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4dd87e36\"\n\nexport default script","<template>\r\n <div class=\"table-style-panel\">\r\n <InputGroup compact class=\"row\">\r\n <Select\r\n style=\"flex: 3;\"\r\n :value=\"textAttrs.fontname\"\r\n @change=\"value => updateTextAttrs({ fontname: value })\"\r\n >\r\n <template #suffixIcon><IconFontSize /></template>\r\n <SelectOption v-for=\"font in availableFonts\" :key=\"font.en\" :value=\"font.en\">\r\n <span :style=\"{ fontFamily: font.en }\">{{font.zh}}</span>\r\n </SelectOption>\r\n </Select>\r\n <Select\r\n style=\"flex: 2;\"\r\n :value=\"textAttrs.fontsize\"\r\n @change=\"value => updateTextAttrs({ fontsize: value })\"\r\n >\r\n <template #suffixIcon><IconAddText /></template>\r\n <SelectOption v-for=\"fontsize in fontSizeOptions\" :key=\"fontsize\" :value=\"fontsize\">\r\n {{fontsize}}\r\n </SelectOption>\r\n </Select>\r\n </InputGroup>\r\n\r\n <ButtonGroup class=\"row\">\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"textAttrs.color\"\r\n @update:modelValue=\"value => updateTextAttrs({ color: value })\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"文字颜色\">\r\n <Button class=\"text-color-btn\" style=\"flex: 1;\">\r\n <IconText />\r\n <div class=\"text-color-block\" :style=\"{ backgroundColor: textAttrs.color }\"></div>\r\n </Button>\r\n </Tooltip>\r\n </Popover>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"textAttrs.backcolor\"\r\n @update:modelValue=\"value => updateTextAttrs({ backcolor: value })\"\r\n />\r\n </template>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"单元格填充\">\r\n <Button class=\"text-color-btn\" style=\"flex: 1;\">\r\n <IconFill />\r\n <div class=\"text-color-block\" :style=\"{ backgroundColor: textAttrs.backcolor }\"></div>\r\n </Button>\r\n </Tooltip>\r\n </Popover>\r\n </ButtonGroup>\r\n\r\n <CheckboxButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"加粗\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"textAttrs.bold\"\r\n @click=\"updateTextAttrs({ bold: !textAttrs.bold })\"\r\n ><IconTextBold /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"斜体\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"textAttrs.em\"\r\n @click=\"updateTextAttrs({ em: !textAttrs.em })\"\r\n ><IconTextItalic /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下划线\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"textAttrs.underline\"\r\n @click=\"updateTextAttrs({ underline: !textAttrs.underline })\"\r\n ><IconTextUnderline /></CheckboxButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"删除线\">\r\n <CheckboxButton \r\n style=\"flex: 1;\"\r\n :checked=\"textAttrs.strikethrough\"\r\n @click=\"updateTextAttrs({ strikethrough: !textAttrs.strikethrough })\"\r\n ><IconStrikethrough /></CheckboxButton>\r\n </Tooltip>\r\n </CheckboxButtonGroup>\r\n\r\n <RadioGroup \r\n class=\"row\" \r\n button-style=\"solid\" \r\n :value=\"textAttrs.align\"\r\n @change=\"e => updateTextAttrs({ align: e.target.value })\"\r\n >\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"左对齐\">\r\n <RadioButton value=\"left\" style=\"flex: 1;\"><IconAlignTextLeft /></RadioButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"居中\">\r\n <RadioButton value=\"center\" style=\"flex: 1;\"><IconAlignTextCenter /></RadioButton>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"右对齐\">\r\n <RadioButton value=\"right\" style=\"flex: 1;\"><IconAlignTextRight /></RadioButton>\r\n </Tooltip>\r\n </RadioGroup>\r\n\r\n <Divider />\r\n\r\n <ElementOutline :fixed=\"true\" />\r\n\r\n <Divider />\r\n\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">行数:</div>\r\n <InputNumber \r\n :min=\"minRowCount\"\r\n :max=\"20\"\r\n v-model:value=\"rowCount\" \r\n @pressEnter=\"e => setTableRow(e)\"\r\n @blur=\"e => setTableRow(e)\"\r\n style=\"flex: 3;\" \r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">列数:</div>\r\n <InputNumber \r\n :min=\"minColCount\"\r\n :max=\"20\"\r\n v-model:value=\"colCount\" \r\n @pressEnter=\"e => setTableCol(e)\"\r\n @blur=\"e => setTableCol(e)\"\r\n style=\"flex: 3;\" \r\n />\r\n </div>\r\n\r\n <Divider />\r\n\r\n <div class=\"row theme-switch\">\r\n <div style=\"flex: 2;\">启用主题表格:</div>\r\n <div class=\"switch-wrapper\" style=\"flex: 3;\">\r\n <Switch \r\n :checked=\"hasTheme\" \r\n @change=\"checked => toggleTheme(checked)\" \r\n />\r\n </div>\r\n </div>\r\n\r\n <template v-if=\"hasTheme\">\r\n <div class=\"row\">\r\n <Checkbox \r\n @change=\"e => updateTheme({ rowHeader: e.target.checked })\" \r\n :checked=\"theme.rowHeader\" \r\n style=\"flex: 1;\"\r\n >标题行</Checkbox>\r\n <Checkbox \r\n @change=\"e => updateTheme({ rowFooter: e.target.checked })\" \r\n :checked=\"theme.rowFooter\" \r\n style=\"flex: 1;\"\r\n >汇总行</Checkbox>\r\n </div>\r\n <div class=\"row\">\r\n <Checkbox \r\n @change=\"e => updateTheme({ colHeader: e.target.checked })\" \r\n :checked=\"theme.colHeader\" \r\n style=\"flex: 1;\"\r\n >第一列</Checkbox>\r\n <Checkbox \r\n @change=\"e => updateTheme({ colFooter: e.target.checked })\" \r\n :checked=\"theme.colFooter\" \r\n style=\"flex: 1;\"\r\n >最后一列</Checkbox>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">主题颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"theme.color\"\r\n @update:modelValue=\"value => updateTheme({ color: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"theme.color\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTableElement, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport { message } from 'ant-design-vue'\r\n\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-style-panel',\r\n components: {\r\n ElementOutline,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTTableElement>(() => store.getters.handleElement)\r\n \r\n const availableFonts = computed(() => store.state.availableFonts)\r\n const fontSizeOptions = [\r\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\r\n ]\r\n\r\n const textAttrs = ref({\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '12px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n })\r\n\r\n const theme = ref<TableTheme>()\r\n const hasTheme = ref(false)\r\n const rowCount = ref(0)\r\n const colCount = ref(0)\r\n const minRowCount = ref(0)\r\n const minColCount = ref(0)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'table') return\r\n \r\n theme.value = handleElement.value.theme\r\n hasTheme.value = !!theme.value\r\n\r\n rowCount.value = handleElement.value.data.length\r\n colCount.value = handleElement.value.data[0].length\r\n\r\n minRowCount.value = handleElement.value.data.length\r\n minColCount.value = handleElement.value.data[0].length\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const selectedCells = ref<string[]>([])\r\n\r\n // 更新当前选中单元格的文本样式状态\r\n const updateTextAttrState = () => {\r\n if (!handleElement.value) return\r\n\r\n let rowIndex = 0\r\n let colIndex = 0\r\n if (selectedCells.value.length) {\r\n const selectedCell = selectedCells.value[0]\r\n rowIndex = +selectedCell.split('_')[0]\r\n colIndex = +selectedCell.split('_')[1]\r\n }\r\n const style = handleElement.value.data[rowIndex][colIndex].style\r\n\r\n if (!style) {\r\n textAttrs.value = {\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '12px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n }\r\n }\r\n else {\r\n textAttrs.value = {\r\n bold: !!style.bold,\r\n em: !!style.em,\r\n underline: !!style.underline,\r\n strikethrough: !!style.strikethrough,\r\n color: style.color || '#000',\r\n backcolor: style.backcolor || '#000',\r\n fontsize: style.fontsize || '12px',\r\n fontname: style.fontname || '微软雅黑',\r\n align: style.align || 'left',\r\n }\r\n }\r\n }\r\n\r\n // 监听并更新当前选中的单元格\r\n const updateSelectedCells = (cells: string[]) => {\r\n selectedCells.value = cells\r\n updateTextAttrState()\r\n }\r\n\r\n emitter.on(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\r\n })\r\n\r\n // 设置单元格内容文本样式\r\n const updateTextAttrs = (textAttrProp: Partial<TableCellStyle>) => {\r\n const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n for (let j = 0; j < data[i].length; j++) {\r\n if (!selectedCells.value.length || selectedCells.value.includes(`${i}_${j}`)) {\r\n const style = data[i][j].style || {}\r\n data[i][j].style = { ...style, ...textAttrProp }\r\n }\r\n }\r\n }\r\n const props = { data }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n\r\n addHistorySnapshot()\r\n updateTextAttrState()\r\n }\r\n\r\n // 更新表格主题:主题色、标题行、汇总行、第一列、最后一列\r\n const updateTheme = (themeProp: Partial<TableTheme>) => {\r\n const currentTheme = theme.value || {}\r\n const props = { theme: { ...currentTheme, ...themeProp } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 开启/关闭表格主题\r\n const toggleTheme = (checked: boolean) => {\r\n if (checked) {\r\n const props = {\r\n theme: {\r\n color: '#d14424',\r\n rowHeader: true,\r\n rowFooter: false,\r\n colHeader: false,\r\n colFooter: false,\r\n }\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'theme' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置表格行数(只能增加)\r\n const setTableRow = (e: KeyboardEvent) => {\r\n const value = +(e.target as HTMLInputElement).value\r\n const rowCount = handleElement.value.data.length\r\n\r\n if (value === rowCount) return\r\n if (value < rowCount) return message.warning('设置行数不能少于当前值')\r\n\r\n const rowCells: TableCell[] = new Array(colCount.value).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\r\n const newTableCells: TableCell[][] = new Array(value - rowCount).fill(rowCells)\r\n\r\n const tableCells: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\r\n tableCells.push(...newTableCells)\r\n\r\n const props = { data: tableCells }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n\r\n // 设置表格列数(只能增加)\r\n const setTableCol = (e: KeyboardEvent) => {\r\n const value = +(e.target as HTMLInputElement).value\r\n const colCount = handleElement.value.data[0].length\r\n\r\n if (value === colCount) return\r\n if (value < colCount) return message.warning('设置列数不能少于当前值')\r\n\r\n const tableCells = handleElement.value.data.map(item => {\r\n const cells: TableCell[] = new Array(value - colCount).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\r\n item.push(...cells)\r\n return item\r\n })\r\n\r\n const colSizeList = handleElement.value.colWidths.map(item => item * handleElement.value.width)\r\n const newColSizeList = new Array(value - colCount).fill(100)\r\n colSizeList.push(...newColSizeList)\r\n\r\n const width = handleElement.value.width + 100 * (value - colCount)\r\n const colWidths = colSizeList.map(item => item / width)\r\n\r\n const props = {\r\n width,\r\n data: tableCells,\r\n colWidths,\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n availableFonts,\r\n fontSizeOptions,\r\n textAttrs,\r\n updateTextAttrs,\r\n theme,\r\n rowCount,\r\n colCount,\r\n minRowCount,\r\n minColCount,\r\n hasTheme,\r\n toggleTheme,\r\n updateTheme,\r\n setTableRow,\r\n setTableCol,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.theme-switch {\r\n margin-bottom: 18px;\r\n}\r\n.switch-wrapper {\r\n text-align: right;\r\n}\r\n.text-color-btn {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n.text-color-block {\r\n width: 16px;\r\n height: 3px;\r\n margin-top: 1px;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTTableElement, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\r\nimport emitter, { EmitterEvents } from '@/utils/emitter'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport { message } from 'ant-design-vue'\r\n\r\nimport ElementOutline from '../common/ElementOutline.vue'\r\nimport ColorButton from '../common/ColorButton.vue'\r\n\r\nexport default defineComponent({\r\n name: 'table-style-panel',\r\n components: {\r\n ElementOutline,\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTTableElement>(() => store.getters.handleElement)\r\n \r\n const availableFonts = computed(() => store.state.availableFonts)\r\n const fontSizeOptions = [\r\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\r\n ]\r\n\r\n const textAttrs = ref({\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '12px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n })\r\n\r\n const theme = ref<TableTheme>()\r\n const hasTheme = ref(false)\r\n const rowCount = ref(0)\r\n const colCount = ref(0)\r\n const minRowCount = ref(0)\r\n const minColCount = ref(0)\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value || handleElement.value.type !== 'table') return\r\n \r\n theme.value = handleElement.value.theme\r\n hasTheme.value = !!theme.value\r\n\r\n rowCount.value = handleElement.value.data.length\r\n colCount.value = handleElement.value.data[0].length\r\n\r\n minRowCount.value = handleElement.value.data.length\r\n minColCount.value = handleElement.value.data[0].length\r\n }, { deep: true, immediate: true })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const selectedCells = ref<string[]>([])\r\n\r\n // 更新当前选中单元格的文本样式状态\r\n const updateTextAttrState = () => {\r\n if (!handleElement.value) return\r\n\r\n let rowIndex = 0\r\n let colIndex = 0\r\n if (selectedCells.value.length) {\r\n const selectedCell = selectedCells.value[0]\r\n rowIndex = +selectedCell.split('_')[0]\r\n colIndex = +selectedCell.split('_')[1]\r\n }\r\n const style = handleElement.value.data[rowIndex][colIndex].style\r\n\r\n if (!style) {\r\n textAttrs.value = {\r\n bold: false,\r\n em: false,\r\n underline: false,\r\n strikethrough: false,\r\n color: '#000',\r\n backcolor: '#000',\r\n fontsize: '12px',\r\n fontname: '微软雅黑',\r\n align: 'left',\r\n }\r\n }\r\n else {\r\n textAttrs.value = {\r\n bold: !!style.bold,\r\n em: !!style.em,\r\n underline: !!style.underline,\r\n strikethrough: !!style.strikethrough,\r\n color: style.color || '#000',\r\n backcolor: style.backcolor || '#000',\r\n fontsize: style.fontsize || '12px',\r\n fontname: style.fontname || '微软雅黑',\r\n align: style.align || 'left',\r\n }\r\n }\r\n }\r\n\r\n // 监听并更新当前选中的单元格\r\n const updateSelectedCells = (cells: string[]) => {\r\n selectedCells.value = cells\r\n updateTextAttrState()\r\n }\r\n\r\n emitter.on(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\r\n onUnmounted(() => {\r\n emitter.off(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\r\n })\r\n\r\n // 设置单元格内容文本样式\r\n const updateTextAttrs = (textAttrProp: Partial<TableCellStyle>) => {\r\n const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n for (let j = 0; j < data[i].length; j++) {\r\n if (!selectedCells.value.length || selectedCells.value.includes(`${i}_${j}`)) {\r\n const style = data[i][j].style || {}\r\n data[i][j].style = { ...style, ...textAttrProp }\r\n }\r\n }\r\n }\r\n const props = { data }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n\r\n addHistorySnapshot()\r\n updateTextAttrState()\r\n }\r\n\r\n // 更新表格主题:主题色、标题行、汇总行、第一列、最后一列\r\n const updateTheme = (themeProp: Partial<TableTheme>) => {\r\n const currentTheme = theme.value || {}\r\n const props = { theme: { ...currentTheme, ...themeProp } }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 开启/关闭表格主题\r\n const toggleTheme = (checked: boolean) => {\r\n if (checked) {\r\n const props = {\r\n theme: {\r\n color: '#d14424',\r\n rowHeader: true,\r\n rowFooter: false,\r\n colHeader: false,\r\n colFooter: false,\r\n }\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n }\r\n else {\r\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'theme' })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置表格行数(只能增加)\r\n const setTableRow = (e: KeyboardEvent) => {\r\n const value = +(e.target as HTMLInputElement).value\r\n const rowCount = handleElement.value.data.length\r\n\r\n if (value === rowCount) return\r\n if (value < rowCount) return message.warning('设置行数不能少于当前值')\r\n\r\n const rowCells: TableCell[] = new Array(colCount.value).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\r\n const newTableCells: TableCell[][] = new Array(value - rowCount).fill(rowCells)\r\n\r\n const tableCells: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\r\n tableCells.push(...newTableCells)\r\n\r\n const props = { data: tableCells }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n\r\n // 设置表格列数(只能增加)\r\n const setTableCol = (e: KeyboardEvent) => {\r\n const value = +(e.target as HTMLInputElement).value\r\n const colCount = handleElement.value.data[0].length\r\n\r\n if (value === colCount) return\r\n if (value < colCount) return message.warning('设置列数不能少于当前值')\r\n\r\n const tableCells = handleElement.value.data.map(item => {\r\n const cells: TableCell[] = new Array(value - colCount).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\r\n item.push(...cells)\r\n return item\r\n })\r\n\r\n const colSizeList = handleElement.value.colWidths.map(item => item * handleElement.value.width)\r\n const newColSizeList = new Array(value - colCount).fill(100)\r\n colSizeList.push(...newColSizeList)\r\n\r\n const width = handleElement.value.width + 100 * (value - colCount)\r\n const colWidths = colSizeList.map(item => item / width)\r\n\r\n const props = {\r\n width,\r\n data: tableCells,\r\n colWidths,\r\n }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n availableFonts,\r\n fontSizeOptions,\r\n textAttrs,\r\n updateTextAttrs,\r\n theme,\r\n rowCount,\r\n colCount,\r\n minRowCount,\r\n minColCount,\r\n hasTheme,\r\n toggleTheme,\r\n updateTheme,\r\n setTableRow,\r\n setTableCol,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TableStylePanel.vue?vue&type=template&id=90d47588&scoped=true\"\nimport script from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TableStylePanel.vue?vue&type=style&index=0&id=90d47588&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-90d47588\"\n\nexport default script","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement } from '@/types/slides'\r\n\r\nimport TextStylePanel from './TextStylePanel.vue'\r\nimport ImageStylePanel from './ImageStylePanel.vue'\r\nimport ShapeStylePanel from './ShapeStylePanel.vue'\r\nimport LineStylePanel from './LineStylePanel.vue'\r\nimport ChartStylePanel from './ChartStylePanel/index.vue'\r\nimport TableStylePanel from './TableStylePanel.vue'\r\n\r\nexport default defineComponent({\r\n name: 'element-style-panel',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const currentPanelComponent = computed(() => {\r\n if (!handleElement.value) return null\r\n \r\n const panelMap = {\r\n [ElementTypes.TEXT]: TextStylePanel,\r\n [ElementTypes.IMAGE]: ImageStylePanel,\r\n [ElementTypes.SHAPE]: ShapeStylePanel,\r\n [ElementTypes.LINE]: LineStylePanel,\r\n [ElementTypes.CHART]: ChartStylePanel,\r\n [ElementTypes.TABLE]: TableStylePanel,\r\n }\r\n return panelMap[handleElement.value.type] || null\r\n })\r\n\r\n return {\r\n handleElement,\r\n currentPanelComponent,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=3eb3d748\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <div class=\"element-positopn-panel\">\r\n <ButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"置顶层\">\r\n <Button style=\"flex: 1;\" @click=\"orderElement(handleElement, 'top')\"><IconSendToBack /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"置底层\">\r\n <Button style=\"flex: 1;\" @click=\"orderElement(handleElement, 'bottom')\"><IconBringToFrontOne /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"上移一层\">\r\n <Button style=\"flex: 1;\" @click=\"orderElement(handleElement, 'up')\"><IconBringToFront /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下移一层\">\r\n <Button style=\"flex: 1;\" @click=\"orderElement(handleElement, 'down')\"><IconSentToBack /></Button>\r\n </Tooltip>\r\n </ButtonGroup>\r\n <ButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"左对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('left')\"><IconAlignLeft /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"水平居中\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('horizontal')\"><IconAlignVertically /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"右对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('right')\"><IconAlignRight /></Button>\r\n </Tooltip>\r\n </ButtonGroup>\r\n <ButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"上对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('top')\"><IconAlignTop /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"垂直居中\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('vertical')\"><IconAlignHorizontally /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignElementToCanvas('bottom')\"><IconAlignBottom /></Button>\r\n </Tooltip>\r\n </ButtonGroup>\r\n\r\n <Divider />\r\n\r\n <div class=\"row\">\r\n <div style=\"flex: 3;\">位置:</div>\r\n <InputNumber\r\n :step=\"5\"\r\n :value=\"left\"\r\n @change=\"value => updateLeft(value)\"\r\n style=\"flex: 4;\"\r\n />\r\n <div style=\"flex: 1;\"></div>\r\n <InputNumber\r\n :step=\"5\"\r\n :value=\"top\"\r\n @change=\"value => updateTop(value)\"\r\n style=\"flex: 4;\"\r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 3;\"></div>\r\n <div style=\"flex: 4;\" class=\"label\">X</div>\r\n <div style=\"flex: 1;\"></div>\r\n <div style=\"flex: 4;\" class=\"label\">Y</div>\r\n </div>\r\n\r\n <template v-if=\"handleElement.type !== 'line'\">\r\n <div class=\"row\">\r\n <div style=\"flex: 3;\">大小:</div>\r\n <InputNumber\r\n :min=\"minSize\"\r\n :max=\"1500\"\r\n :step=\"5\"\r\n :value=\"width\"\r\n @change=\"value => updateWidth(value)\"\r\n style=\"flex: 4;\"\r\n />\r\n <template v-if=\"['image', 'shape'].includes(handleElement.type)\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"解除宽高比锁定\" v-if=\"fixedRatio\">\r\n <IconLock style=\"flex: 1;\" class=\"icon-btn\" @click=\"updateFixedRatio(false)\" />\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"宽高比锁定\" v-else>\r\n <IconUnlock style=\"flex: 1;\" class=\"icon-btn\" @click=\"updateFixedRatio(true)\" />\r\n </Tooltip>\r\n </template>\r\n <div style=\"flex: 1;\" v-else></div>\r\n <InputNumber \r\n :min=\"minSize\"\r\n :max=\"800\"\r\n :step=\"5\"\r\n :disabled=\"handleElement.type === 'text'\" \r\n :value=\"height\" \r\n @change=\"value => updateHeight(value)\"\r\n style=\"flex: 4;\"\r\n />\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 3;\"></div>\r\n <div style=\"flex: 4;\" class=\"label\">宽</div>\r\n <div style=\"flex: 1;\"></div>\r\n <div style=\"flex: 4;\" class=\"label\">高</div>\r\n </div>\r\n </template>\r\n\r\n <template v-if=\"['text', 'image', 'shape'].includes(handleElement.type)\">\r\n <Divider />\r\n\r\n <div class=\"row\">\r\n <div style=\"flex: 3;\">旋转:</div>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"逆时针旋转\">\r\n <IconRotate class=\"icon-btn\" @click=\"updateRotate45('-')\" style=\"flex: 2;\" />\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"顺时针旋转\">\r\n <IconRotate \r\n class=\"icon-btn\" \r\n @click=\"updateRotate45('+')\" \r\n :style=\"{\r\n flex: 2,\r\n transform: 'rotateY(180deg)',\r\n }\" \r\n />\r\n </Tooltip>\r\n <div style=\"flex: 1;\"></div>\r\n <InputNumber \r\n :min=\"-180\"\r\n :max=\"180\"\r\n :step=\"5\"\r\n :value=\"rotate\" \r\n @change=\"value => updateRotate(value)\" \r\n style=\"flex: 4;\" \r\n />\r\n </div>\r\n </template>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport round from 'lodash/round'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { MIN_SIZE } from '@/configs/element'\r\nimport useOrderElement from '@/hooks/useOrderElement'\r\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-positopn-panel',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const left = ref(0)\r\n const top = ref(0)\r\n const width = ref(0)\r\n const height = ref(0)\r\n const rotate = ref(0)\r\n const fixedRatio = ref(false)\r\n\r\n const minSize = computed(() => {\r\n if (!handleElement.value) return 20\r\n return MIN_SIZE[handleElement.value.type] || 20\r\n })\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n\r\n left.value = round(handleElement.value.left, 1)\r\n top.value = round(handleElement.value.top, 1)\r\n\r\n fixedRatio.value = 'fixedRatio' in handleElement.value && !!handleElement.value.fixedRatio\r\n\r\n if (handleElement.value.type !== 'line') {\r\n width.value = round(handleElement.value.width, 1)\r\n height.value = round(handleElement.value.height, 1)\r\n rotate.value = 'rotate' in handleElement.value && handleElement.value.rotate !== undefined ? round(handleElement.value.rotate, 1) : 0\r\n }\r\n }, { deep: true, immediate: true })\r\n\r\n const { orderElement } = useOrderElement()\r\n const { alignElementToCanvas } = useAlignElementToCanvas()\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置元素位置\r\n const updateLeft = (value: number) => {\r\n const props = { left: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateTop = (value: number) => {\r\n const props = { top: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置元素宽度、高度、旋转角度\r\n const updateWidth = (value: number) => {\r\n const props = { width: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateHeight = (value: number) => {\r\n const props = { height: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateRotate = (value: number) => {\r\n const props = { rotate: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 固定元素的宽高比\r\n const updateFixedRatio = (value: boolean) => {\r\n const props = { fixedRatio: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将元素旋转45度(顺时针或逆时针)\r\n const updateRotate45 = (command: '+' | '-') => {\r\n let _rotate = Math.floor(rotate.value / 45) * 45\r\n if (command === '+') _rotate = _rotate + 45\r\n else if (command === '-') _rotate = _rotate - 45\r\n\r\n if (_rotate < -180) _rotate = -180\r\n if (_rotate > 180) _rotate = 180\r\n\r\n const props = { rotate: _rotate }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n orderElement,\r\n alignElementToCanvas,\r\n left,\r\n top,\r\n width,\r\n height,\r\n rotate,\r\n fixedRatio,\r\n minSize,\r\n updateLeft,\r\n updateTop,\r\n updateWidth,\r\n updateHeight,\r\n updateRotate,\r\n updateFixedRatio,\r\n updateRotate45,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.label {\r\n text-align: center;\r\n}\r\n.icon-btn {\r\n cursor: pointer;\r\n}\r\n</style>","\r\nimport { computed, defineComponent, ref, watch } from 'vue'\r\nimport round from 'lodash/round'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement } from '@/types/slides'\r\nimport { MIN_SIZE } from '@/configs/element'\r\nimport useOrderElement from '@/hooks/useOrderElement'\r\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'element-positopn-panel',\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n\r\n const left = ref(0)\r\n const top = ref(0)\r\n const width = ref(0)\r\n const height = ref(0)\r\n const rotate = ref(0)\r\n const fixedRatio = ref(false)\r\n\r\n const minSize = computed(() => {\r\n if (!handleElement.value) return 20\r\n return MIN_SIZE[handleElement.value.type] || 20\r\n })\r\n\r\n watch(handleElement, () => {\r\n if (!handleElement.value) return\r\n\r\n left.value = round(handleElement.value.left, 1)\r\n top.value = round(handleElement.value.top, 1)\r\n\r\n fixedRatio.value = 'fixedRatio' in handleElement.value && !!handleElement.value.fixedRatio\r\n\r\n if (handleElement.value.type !== 'line') {\r\n width.value = round(handleElement.value.width, 1)\r\n height.value = round(handleElement.value.height, 1)\r\n rotate.value = 'rotate' in handleElement.value && handleElement.value.rotate !== undefined ? round(handleElement.value.rotate, 1) : 0\r\n }\r\n }, { deep: true, immediate: true })\r\n\r\n const { orderElement } = useOrderElement()\r\n const { alignElementToCanvas } = useAlignElementToCanvas()\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置元素位置\r\n const updateLeft = (value: number) => {\r\n const props = { left: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateTop = (value: number) => {\r\n const props = { top: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置元素宽度、高度、旋转角度\r\n const updateWidth = (value: number) => {\r\n const props = { width: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateHeight = (value: number) => {\r\n const props = { height: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n const updateRotate = (value: number) => {\r\n const props = { rotate: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 固定元素的宽高比\r\n const updateFixedRatio = (value: boolean) => {\r\n const props = { fixedRatio: value }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将元素旋转45度(顺时针或逆时针)\r\n const updateRotate45 = (command: '+' | '-') => {\r\n let _rotate = Math.floor(rotate.value / 45) * 45\r\n if (command === '+') _rotate = _rotate + 45\r\n else if (command === '-') _rotate = _rotate - 45\r\n\r\n if (_rotate < -180) _rotate = -180\r\n if (_rotate > 180) _rotate = 180\r\n\r\n const props = { rotate: _rotate }\r\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n handleElement,\r\n orderElement,\r\n alignElementToCanvas,\r\n left,\r\n top,\r\n width,\r\n height,\r\n rotate,\r\n fixedRatio,\r\n minSize,\r\n updateLeft,\r\n updateTop,\r\n updateWidth,\r\n updateHeight,\r\n updateRotate,\r\n updateFixedRatio,\r\n updateRotate45,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementPositionPanel.vue?vue&type=template&id=15c9ddcc&scoped=true\"\nimport script from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementPositionPanel.vue?vue&type=style&index=0&id=15c9ddcc&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-15c9ddcc\"\n\nexport default script","<template>\r\n <div class=\"element-animation-panel\">\r\n <div class=\"element-animation\" v-if=\"handleElement\">\r\n <Popover trigger=\"click\" v-model:visible=\"animationPoolVisible\">\r\n <template #content>\r\n <div class=\"animation-pool\">\r\n <div class=\"pool-type\" v-for=\"type in animations\" :key=\"type.name\">\r\n <div class=\"type-title\">{{type.name}}:</div>\r\n <div class=\"pool-item-wrapper\">\r\n <div \r\n class=\"pool-item\" \r\n v-for=\"item in type.children\" :key=\"item.name\"\r\n @mouseenter=\"hoverPreviewAnimation = item.value\"\r\n @mouseleave=\"hoverPreviewAnimation = ''\"\r\n @click=\"addAnimation(item.value)\"\r\n >\r\n <div \r\n class=\"animation-box\"\r\n :class=\"[\r\n 'animate__animated',\r\n 'animate__faster',\r\n hoverPreviewAnimation === item.value && `animate__${item.value}`,\r\n ]\"\r\n >\r\n {{item.name}}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </template>\r\n <Button class=\"element-animation-btn\">\r\n <IconEffects style=\"margin-right: 5px;\" /> {{handleElementAnimation || '点击选择动画'}}\r\n </Button>\r\n </Popover>\r\n </div>\r\n\r\n <div class=\"tip\" v-else><IconClick /> 选中画布中的元素添加动画</div>\r\n \r\n <Divider />\r\n\r\n <Draggable \r\n class=\"animation-sequence\"\r\n :modelValue=\"animationSequence\"\r\n :animation=\"300\"\r\n :scroll=\"true\"\r\n :scrollSensitivity=\"50\"\r\n @end=\"handleDragEnd\"\r\n itemKey=\"id\"\r\n >\r\n <template #item=\"{ element, index }\">\r\n <div class=\"sequence-item\" :class=\"{ 'active': handleElement?.id === element.elId }\">\r\n <div class=\"index\">{{index + 1}}</div>\r\n <div class=\"text\">【{{element.elType}}】{{element.animationType}}</div>\r\n <div class=\"handler\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"预览\">\r\n <IconPlayOne class=\"handler-btn\" @click=\"runAnimation(element.elId, element.type)\" />\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"删除\">\r\n <IconCloseSmall class=\"handler-btn\" @click=\"deleteAnimation(element.elId)\" />\r\n </Tooltip>\r\n </div>\r\n </div>\r\n </template>\r\n </Draggable>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTAnimation, PPTElement, Slide } from '@/types/slides'\r\nimport { ANIMATIONS } from '@/configs/animation'\r\nimport { ELEMENT_TYPE_ZH } from '@/configs/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport Draggable from 'vuedraggable'\r\n\r\nconst animationTypes: { [key: string]: string } = {}\r\nfor (const type of ANIMATIONS) {\r\n for (const animation of type.children) {\r\n animationTypes[animation.value] = animation.name\r\n }\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'element-animation-panel',\r\n components: {\r\n Draggable,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n const currentSlideAnimations = computed<PPTAnimation[] | null>(() => store.getters.currentSlideAnimations)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const hoverPreviewAnimation = ref('')\r\n const animationPoolVisible = ref(false)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const animations = ANIMATIONS\r\n\r\n // 当前页面的动画列表\r\n const animationSequence = computed(() => {\r\n if (!currentSlideAnimations.value) return []\r\n const animationSequence = []\r\n for (const animation of currentSlideAnimations.value) {\r\n const el = currentSlide.value.elements.find(el => el.id === animation.elId)\r\n if (!el) continue\r\n const elType = ELEMENT_TYPE_ZH[el.type]\r\n const animationType = animationTypes[animation.type]\r\n\r\n animationSequence.push({\r\n ...animation,\r\n elType,\r\n animationType,\r\n })\r\n }\r\n return animationSequence\r\n })\r\n\r\n // 当前选中元素的入场动画信息\r\n const handleElementAnimation = computed(() => {\r\n if (!handleElement.value) return null\r\n const animations = currentSlideAnimations.value || []\r\n const animation = animations.find(item => item.elId === handleElement.value.id)\r\n if (!animation) return null\r\n return animationTypes[animation.type]\r\n })\r\n\r\n // 删除元素入场动画\r\n const deleteAnimation = (elId: string) => {\r\n const animations = (currentSlideAnimations.value as PPTAnimation[]).filter(item => item.elId !== elId)\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 拖拽修改入场动画顺序后同步数据\r\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\r\n const { newIndex, oldIndex } = eventData\r\n if (oldIndex === newIndex) return\r\n\r\n const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value))\r\n const animation = animations[oldIndex]\r\n animations.splice(oldIndex, 1)\r\n animations.splice(newIndex, 0, animation)\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 执行入场动画预览\r\n const runAnimation = (elId: string, animationType: string) => {\r\n const prefix = 'animate__'\r\n const elRef = document.querySelector(`#editable-element-${elId} [class^=editable-element-]`)\r\n if (elRef) {\r\n const animationName = `${prefix}${animationType}`\r\n elRef.classList.add(`${prefix}animated`, animationName)\r\n\r\n const handleAnimationEnd = () => {\r\n elRef.classList.remove(`${prefix}animated`, animationName)\r\n }\r\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\r\n }\r\n }\r\n\r\n // 修改元素入场动画,并执行一次预览\r\n const updateElementAnimation = (type: string) => {\r\n const animations = (currentSlideAnimations.value as PPTAnimation[]).map(item => {\r\n if (item.elId === handleElement.value.id) return { ...item, type }\r\n return item\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n animationPoolVisible.value = false\r\n addHistorySnapshot()\r\n\r\n runAnimation(handleElement.value.id, type)\r\n }\r\n\r\n // 添加元素入场动画,并执行一次预览\r\n const addAnimation = (type: string) => {\r\n if (handleElementAnimation.value) {\r\n updateElementAnimation(type)\r\n return\r\n }\r\n const animations: PPTAnimation[] = currentSlideAnimations.value ? JSON.parse(JSON.stringify(currentSlideAnimations.value)) : []\r\n animations.push({\r\n elId: handleElement.value.id,\r\n type,\r\n duration: 1000,\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n animationPoolVisible.value = false\r\n addHistorySnapshot()\r\n\r\n runAnimation(handleElement.value.id, type)\r\n }\r\n\r\n return {\r\n handleElement,\r\n animationPoolVisible,\r\n animations,\r\n animationSequence,\r\n hoverPreviewAnimation,\r\n handleElementAnimation,\r\n addAnimation,\r\n deleteAnimation,\r\n handleDragEnd,\r\n runAnimation,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.element-animation-btn {\r\n width: 100%;\r\n}\r\n.tip {\r\n text-align: center;\r\n font-style: italic;\r\n padding-top: 12px;\r\n}\r\n.animation-pool {\r\n width: 400px;\r\n height: 500px;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n font-size: 12px;\r\n margin-right: -12px;\r\n padding-right: 12px;\r\n}\r\n.type-title {\r\n width: 100%;\r\n font-size: 13px;\r\n margin-bottom: 10px;\r\n border-left: 4px solid #aaa;\r\n background-color: #eee;\r\n padding: 2px 0 2px 10px;\r\n}\r\n.pool-item-wrapper {\r\n @include flex-grid-layout();\r\n}\r\n.pool-item {\r\n @include flex-grid-layout-children(4, 24%);\r\n\r\n margin-bottom: 10px;\r\n height: 40px;\r\n line-height: 40px;\r\n text-align: center;\r\n cursor: pointer;\r\n}\r\n.animation-box {\r\n background-color: $lightGray;\r\n}\r\n\r\n.sequence-item {\r\n height: 36px;\r\n display: flex;\r\n align-items: center;\r\n border: 1px solid $borderColor;\r\n padding: 6px;\r\n border-radius: $borderRadius;\r\n margin-bottom: 8px;\r\n cursor: grab;\r\n\r\n &:active {\r\n cursor: grabbing;\r\n }\r\n\r\n &.active {\r\n border-color: $themeColor;\r\n }\r\n\r\n .index {\r\n flex: 1;\r\n }\r\n .text {\r\n flex: 6;\r\n }\r\n .handler {\r\n flex: 2;\r\n font-size: 15px;\r\n text-align: right;\r\n }\r\n .handler-btn {\r\n margin-left: 8px;\r\n cursor: pointer;\r\n }\r\n}\r\n</style>","export const ANIMATIONS = [\r\n {\r\n type: 'bounce',\r\n name: '弹跳',\r\n children: [\r\n { name: '弹入', value: 'bounceIn' },\r\n { name: '向右弹入', value: 'bounceInLeft' },\r\n { name: '向左弹入', value: 'bounceInRight' },\r\n { name: '向上弹入', value: 'bounceInUp' },\r\n { name: '向下弹入', value: 'bounceInDown' },\r\n ],\r\n },\r\n {\r\n type: 'fade',\r\n name: '浮现',\r\n children: [\r\n { name: '浮入', value: 'fadeIn' },\r\n { name: '向下浮入', value: 'fadeInDown' },\r\n { name: '向下长距浮入', value: 'fadeInDownBig' },\r\n { name: '向右浮入', value: 'fadeInLeft' },\r\n { name: '向右长距浮入', value: 'fadeInLeftBig' },\r\n { name: '向左浮入', value: 'fadeInRight' },\r\n { name: '向左长距浮入', value: 'fadeInRightBig' },\r\n { name: '向上浮入', value: 'fadeInUp' },\r\n { name: '向上长距浮入', value: 'fadeInUpBig' },\r\n { name: '从左上浮入', value: 'fadeInTopLeft' },\r\n { name: '从右上浮入', value: 'fadeInTopRight' },\r\n { name: '从左下浮入', value: 'fadeInBottomLeft' },\r\n { name: '从右下浮入', value: 'fadeInBottomRight' },\r\n ],\r\n },\r\n {\r\n type: 'rotate',\r\n name: '旋转',\r\n children: [\r\n { name: '旋转进入', value: 'rotateIn' },\r\n { name: '绕左下旋转进入', value: 'rotateInDownLeft' },\r\n { name: '绕右下旋转进入', value: 'rotateInDownRight' },\r\n { name: '绕左上旋转进入', value: 'rotateInUpLeft' },\r\n { name: '绕右上旋转进入', value: 'rotateInUpRight' },\r\n ],\r\n },\r\n {\r\n type: 'zoom',\r\n name: '缩放',\r\n children: [\r\n { name: '放大进入', value: 'zoomIn' },\r\n { name: '向下放大进入', value: 'zoomInDown' },\r\n { name: '从左放大进入', value: 'zoomInLeft' },\r\n { name: '从右放大进入', value: 'zoomInRight' },\r\n { name: '向上放大进入', value: 'zoomInUp' },\r\n ],\r\n },\r\n {\r\n type: 'slide',\r\n name: '滑入',\r\n children: [\r\n { name: '向下滑入', value: 'slideInDown' },\r\n { name: '从右滑入', value: 'slideInLeft' },\r\n { name: '从左滑入', value: 'slideInRight' },\r\n { name: '向上滑入', value: 'slideInUp' },\r\n ],\r\n },\r\n {\r\n type: 'flip',\r\n name: '翻转',\r\n children: [\r\n { name: 'X轴翻转进入', value: 'flipInX' },\r\n { name: 'Y轴翻转进入', value: 'flipInY' },\r\n ],\r\n },\r\n {\r\n type: 'back',\r\n name: '放大滑入',\r\n children: [\r\n { name: '向下放大滑入', value: 'backInDown' },\r\n { name: '从左放大滑入', value: 'backInLeft' },\r\n { name: '从右放大滑入', value: 'backInRight' },\r\n { name: '向上放大滑入', value: 'backInUp' },\r\n ],\r\n },\r\n {\r\n type: 'lightSpeed',\r\n name: '飞入',\r\n children: [\r\n { name: '从右飞入', value: 'lightSpeedInRight' },\r\n { name: '从左飞入', value: 'lightSpeedInLeft' },\r\n ],\r\n },\r\n]","\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTAnimation, PPTElement, Slide } from '@/types/slides'\r\nimport { ANIMATIONS } from '@/configs/animation'\r\nimport { ELEMENT_TYPE_ZH } from '@/configs/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport Draggable from 'vuedraggable'\r\n\r\nconst animationTypes: { [key: string]: string } = {}\r\nfor (const type of ANIMATIONS) {\r\n for (const animation of type.children) {\r\n animationTypes[animation.value] = animation.name\r\n }\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'element-animation-panel',\r\n components: {\r\n Draggable,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const handleElement = computed<PPTElement>(() => store.getters.handleElement)\r\n const currentSlideAnimations = computed<PPTAnimation[] | null>(() => store.getters.currentSlideAnimations)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const hoverPreviewAnimation = ref('')\r\n const animationPoolVisible = ref(false)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const animations = ANIMATIONS\r\n\r\n // 当前页面的动画列表\r\n const animationSequence = computed(() => {\r\n if (!currentSlideAnimations.value) return []\r\n const animationSequence = []\r\n for (const animation of currentSlideAnimations.value) {\r\n const el = currentSlide.value.elements.find(el => el.id === animation.elId)\r\n if (!el) continue\r\n const elType = ELEMENT_TYPE_ZH[el.type]\r\n const animationType = animationTypes[animation.type]\r\n\r\n animationSequence.push({\r\n ...animation,\r\n elType,\r\n animationType,\r\n })\r\n }\r\n return animationSequence\r\n })\r\n\r\n // 当前选中元素的入场动画信息\r\n const handleElementAnimation = computed(() => {\r\n if (!handleElement.value) return null\r\n const animations = currentSlideAnimations.value || []\r\n const animation = animations.find(item => item.elId === handleElement.value.id)\r\n if (!animation) return null\r\n return animationTypes[animation.type]\r\n })\r\n\r\n // 删除元素入场动画\r\n const deleteAnimation = (elId: string) => {\r\n const animations = (currentSlideAnimations.value as PPTAnimation[]).filter(item => item.elId !== elId)\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 拖拽修改入场动画顺序后同步数据\r\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\r\n const { newIndex, oldIndex } = eventData\r\n if (oldIndex === newIndex) return\r\n\r\n const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value))\r\n const animation = animations[oldIndex]\r\n animations.splice(oldIndex, 1)\r\n animations.splice(newIndex, 0, animation)\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 执行入场动画预览\r\n const runAnimation = (elId: string, animationType: string) => {\r\n const prefix = 'animate__'\r\n const elRef = document.querySelector(`#editable-element-${elId} [class^=editable-element-]`)\r\n if (elRef) {\r\n const animationName = `${prefix}${animationType}`\r\n elRef.classList.add(`${prefix}animated`, animationName)\r\n\r\n const handleAnimationEnd = () => {\r\n elRef.classList.remove(`${prefix}animated`, animationName)\r\n }\r\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\r\n }\r\n }\r\n\r\n // 修改元素入场动画,并执行一次预览\r\n const updateElementAnimation = (type: string) => {\r\n const animations = (currentSlideAnimations.value as PPTAnimation[]).map(item => {\r\n if (item.elId === handleElement.value.id) return { ...item, type }\r\n return item\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n animationPoolVisible.value = false\r\n addHistorySnapshot()\r\n\r\n runAnimation(handleElement.value.id, type)\r\n }\r\n\r\n // 添加元素入场动画,并执行一次预览\r\n const addAnimation = (type: string) => {\r\n if (handleElementAnimation.value) {\r\n updateElementAnimation(type)\r\n return\r\n }\r\n const animations: PPTAnimation[] = currentSlideAnimations.value ? JSON.parse(JSON.stringify(currentSlideAnimations.value)) : []\r\n animations.push({\r\n elId: handleElement.value.id,\r\n type,\r\n duration: 1000,\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\r\n animationPoolVisible.value = false\r\n addHistorySnapshot()\r\n\r\n runAnimation(handleElement.value.id, type)\r\n }\r\n\r\n return {\r\n handleElement,\r\n animationPoolVisible,\r\n animations,\r\n animationSequence,\r\n hoverPreviewAnimation,\r\n handleElementAnimation,\r\n addAnimation,\r\n deleteAnimation,\r\n handleDragEnd,\r\n runAnimation,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ElementAnimationPanel.vue?vue&type=template&id=79c3f50b&scoped=true\"\nimport script from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementAnimationPanel.vue?vue&type=style&index=0&id=79c3f50b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-79c3f50b\"\n\nexport default script","<template>\r\n <div class=\"slide-style-panel\">\r\n <div class=\"title\">背景填充</div>\r\n <div class=\"row\">\r\n <Select \r\n style=\"flex: 10;\" \r\n :value=\"background.type\" \r\n @change=\"value => updateBackgroundType(value)\"\r\n >\r\n <SelectOption value=\"solid\">纯色填充</SelectOption>\r\n <SelectOption value=\"image\">图片填充</SelectOption>\r\n <SelectOption value=\"gradient\">渐变填充</SelectOption>\r\n </Select>\r\n <div style=\"flex: 1;\"></div>\r\n\r\n <Popover trigger=\"click\" v-if=\"background.type === 'solid'\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"background.color\"\r\n @update:modelValue=\"color => updateBackground({ color })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"background.color || '#fff'\" style=\"flex: 10;\" />\r\n </Popover>\r\n\r\n <Select \r\n style=\"flex: 10;\" \r\n :value=\"background.size || 'cover'\" \r\n @change=\"value => updateBackground({ imageSize: value })\"\r\n v-else-if=\"background.type === 'image'\"\r\n >\r\n <SelectOption value=\"initial\">原始大小</SelectOption>\r\n <SelectOption value=\"contain\">缩放</SelectOption>\r\n <SelectOption value=\"repeat\">拼贴</SelectOption>\r\n <SelectOption value=\"cover\">缩放铺满</SelectOption>\r\n </Select>\r\n\r\n <Select \r\n style=\"flex: 10;\" \r\n :value=\"background.gradientType\" \r\n @change=\"value => updateBackground({ gradientType: value })\"\r\n v-else\r\n >\r\n <SelectOption value=\"linear\">线性渐变</SelectOption>\r\n <SelectOption value=\"radial\">径向渐变</SelectOption>\r\n </Select>\r\n </div>\r\n\r\n <div class=\"background-image-wrapper\" v-if=\"background.type === 'image'\">\r\n <FileInput @change=\"files => uploadBackgroundImage(files)\">\r\n <div class=\"background-image\">\r\n <div class=\"content\" :style=\"{ backgroundImage: `url(${background.image})` }\">\r\n <IconPlus />\r\n </div>\r\n </div>\r\n </FileInput>\r\n </div>\r\n\r\n <div class=\"background-gradient-wrapper\" v-if=\"background.type === 'gradient'\">\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">起点颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"background.gradientColor[0]\"\r\n @update:modelValue=\"value => updateBackground({ gradientColor: [value, background.gradientColor[1]] })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"background.gradientColor[0]\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">终点颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"background.gradientColor[1]\"\r\n @update:modelValue=\"value => updateBackground({ gradientColor: [background.gradientColor[0], value] })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"background.gradientColor[1]\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\" v-if=\"background.gradientType === 'linear'\">\r\n <div style=\"flex: 2;\">渐变角度:</div>\r\n <Slider\r\n :min=\"0\"\r\n :max=\"360\"\r\n :step=\"15\"\r\n :value=\"background.gradientRotate\"\r\n style=\"flex: 3;\"\r\n @change=\"value => updateBackground({ gradientRotate: value })\" \r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"row\"><Button style=\"flex: 1;\" @click=\"applyBackgroundAllSlide()\">应用背景到全部</Button></div>\r\n\r\n <Divider />\r\n\r\n <div class=\"title\">全局主题</div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">字体:</div>\r\n <Select\r\n style=\"flex: 3;\"\r\n :value=\"theme.fontName\"\r\n @change=\"value => updateTheme({ fontName: value })\"\r\n >\r\n <SelectOptGroup label=\"系统字体\">\r\n <SelectOption v-for=\"font in availableFonts\" :key=\"font.value\" :value=\"font.value\">\r\n <span :style=\"{ fontFamily: font.value }\">{{font.label}}</span>\r\n </SelectOption>\r\n </SelectOptGroup>\r\n <SelectOptGroup label=\"在线字体\">\r\n <SelectOption v-for=\"font in webFonts\" :key=\"font.value\" :value=\"font.value\">\r\n <span>{{font.label}}</span>\r\n </SelectOption>\r\n </SelectOptGroup>\r\n </Select>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">字体颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"theme.fontColor\"\r\n @update:modelValue=\"value => updateTheme({ fontColor: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"theme.fontColor\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">背景颜色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"theme.backgroundColor\"\r\n @update:modelValue=\"value => updateTheme({ backgroundColor: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"theme.backgroundColor\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n <div class=\"row\">\r\n <div style=\"flex: 2;\">主题色:</div>\r\n <Popover trigger=\"click\">\r\n <template #content>\r\n <ColorPicker\r\n :modelValue=\"theme.themeColor\"\r\n @update:modelValue=\"value => updateTheme({ themeColor: value })\"\r\n />\r\n </template>\r\n <ColorButton :color=\"theme.themeColor\" style=\"flex: 3;\" />\r\n </Popover>\r\n </div>\r\n\r\n <div class=\"title\" style=\"margin-top: 20px;\">预置主题:</div>\r\n <div class=\"theme-list\">\r\n <div \r\n class=\"theme-item\" \r\n v-for=\"(item, index) in themes\" \r\n :key=\"index\"\r\n :style=\"{ backgroundColor: item.background }\"\r\n @click=\"updateTheme({\r\n fontColor: item.text,\r\n backgroundColor: item.background,\r\n themeColor: item.color,\r\n })\"\r\n >\r\n <div class=\"theme-item-content\">\r\n <div class=\"text\" :style=\"{ color: item.text }\">Aa</div>\r\n <div class=\"color-block\" :style=\"{ backgroundColor: item.color }\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row\"><Button style=\"flex: 1;\" @click=\"applyThemeAllSlide()\">应用主题到全部</Button></div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide, SlideBackground, SlideTheme } from '@/types/slides'\r\nimport { PRESET_THEMES } from '@/configs/theme'\r\nimport { WEB_FONTS } from '@/configs/font'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './common/ColorButton.vue'\r\nimport { getImageDataURL } from '@/utils/image'\r\n\r\nconst themes = PRESET_THEMES\r\nconst webFonts = WEB_FONTS\r\n\r\nexport default defineComponent({\r\n name: 'slide-style-panel',\r\n components: {\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const theme = computed(() => store.state.theme)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n const availableFonts = computed(() => store.state.availableFonts)\r\n\r\n const background = computed(() => {\r\n if (!currentSlide.value.background) {\r\n return {\r\n type: 'solid',\r\n value: '#fff',\r\n } as SlideBackground\r\n }\r\n return currentSlide.value.background\r\n })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置背景模式:纯色、图片、渐变色\r\n const updateBackgroundType = (type: 'solid' | 'image' | 'gradient') => {\r\n if (type === 'solid') {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'solid',\r\n color: background.value.color || '#fff',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n else if (type === 'image') {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'image',\r\n image: background.value.image || '',\r\n imageSize: background.value.imageSize || 'cover',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n else {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'gradient',\r\n gradientType: background.value.gradientType || 'linear',\r\n gradientColor: background.value.gradientColor || ['#fff', '#fff'],\r\n gradientRotate: background.value.gradientRotate || 0,\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置背景图片\r\n const updateBackground = (props: Partial<SlideBackground>) => {\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 上传背景图片\r\n const uploadBackgroundImage = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => updateBackground({ image: dataURL }))\r\n }\r\n\r\n // 应用当前页背景到全部页面\r\n const applyBackgroundAllSlide = () => {\r\n const newSlides = slides.value.map(slide => {\r\n return {\r\n ...slide,\r\n background: currentSlide.value.background,\r\n }\r\n })\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置主题\r\n const updateTheme = (themeProps: Partial<SlideTheme>) => {\r\n store.commit(MutationTypes.SET_THEME, themeProps)\r\n }\r\n\r\n // 将当前主题应用到全部页面\r\n const applyThemeAllSlide = () => {\r\n const newSlides: Slide[] = JSON.parse(JSON.stringify(slides.value))\r\n const { themeColor, backgroundColor, fontColor } = theme.value\r\n\r\n for (const slide of newSlides) {\r\n if (!slide.background || slide.background.type !== 'image') {\r\n slide.background = {\r\n ...slide.background,\r\n type: 'solid',\r\n color: backgroundColor\r\n }\r\n }\r\n\r\n const elements = slide.elements\r\n for (const el of elements) {\r\n if (el.type === 'shape') el.fill = themeColor\r\n else if (el.type === 'line') el.color = themeColor\r\n else if (el.type === 'text') {\r\n if (el.fill) el.fill = themeColor\r\n }\r\n else if (el.type === 'table') {\r\n if (el.theme) el.theme.color = themeColor\r\n }\r\n else if (el.type === 'chart') {\r\n el.themeColor = themeColor\r\n el.gridColor = fontColor\r\n }\r\n }\r\n }\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n availableFonts,\r\n background,\r\n updateBackgroundType,\r\n updateBackground,\r\n uploadBackgroundImage,\r\n applyBackgroundAllSlide,\r\n themes,\r\n theme,\r\n webFonts,\r\n updateTheme,\r\n applyThemeAllSlide,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n.title {\r\n margin-bottom: 10px;\r\n}\r\n.background-image-wrapper {\r\n margin-bottom: 10px;\r\n}\r\n.background-image {\r\n height: 0;\r\n padding-bottom: 56.25%;\r\n border: 1px dashed $borderColor;\r\n border-radius: $borderRadius;\r\n position: relative;\r\n transition: all .2s;\r\n\r\n &:hover {\r\n border-color: $themeColor;\r\n color: $themeColor;\r\n }\r\n\r\n .content {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n background-position: center;\r\n background-size: contain;\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n }\r\n}\r\n\r\n.theme-list {\r\n @include flex-grid-layout();\r\n}\r\n.theme-item {\r\n @include flex-grid-layout-children(4, 22%);\r\n\r\n padding-bottom: 22%;\r\n border-radius: $borderRadius;\r\n position: relative;\r\n cursor: pointer;\r\n\r\n .theme-item-content {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n transition: box-shadow .2s;\r\n\r\n &:hover {\r\n box-shadow: 0 0 4px #888;\r\n }\r\n }\r\n\r\n .text {\r\n font-size: 16px;\r\n }\r\n\r\n .color-block {\r\n width: 28px;\r\n height: 10px;\r\n margin-top: 5px;\r\n }\r\n}\r\n</style>","export const PRESET_THEMES = [\r\n { color: '#d14424', background: '#ffffff', text: '#333' },\r\n { color: '#42464b', background: '#ffffff', text: '#333' },\r\n { color: '#5d82ba', background: '#ffffff', text: '#333' },\r\n { color: '#005a6f', background: '#ffffff', text: '#333' },\r\n { color: '#d0614c', background: '#dfb044', text: '#333' },\r\n { color: '#86a1ad', background: '#dfdbd4', text: '#333' },\r\n { color: '#697586', background: '#d5c4a4', text: '#333' },\r\n { color: '#333333', background: '#7acfa6', text: '#333' },\r\n { color: '#42464b', background: '#415065', text: '#fff' },\r\n { color: '#0c5999', background: '#35a2cd', text: '#fff' },\r\n { color: '#c49a41', background: '#8c4357', text: '#fff' },\r\n { color: '#dfaa00', background: '#2e4e7d', text: '#fff' },\r\n { color: '#d1ad88', background: '#f99070', text: '#fff' },\r\n { color: '#464d52', background: '#657984', text: '#fff' },\r\n { color: '#ffcfb6', background: '#1e4c6f', text: '#fff' },\r\n { color: '#c3a043', background: '#43292a', text: '#fff' },\r\n { color: '#ffffff', background: '#171925', text: '#fff' },\r\n { color: '#df9636', background: '#5b89a0', text: '#fff' },\r\n { color: '#b898a4', background: '#93716b', text: '#fff' },\r\n { color: '#c47a11', background: '#187db1', text: '#fff' },\r\n { color: '#333333', background: '#759564', text: '#fff' },\r\n { color: '#355b5e', background: '#424b50', text: '#fff' },\r\n { color: '#d29090', background: '#942a32', text: '#fff' },\r\n { color: '#00cfdf', background: '#3b434d', text: '#fff' },\r\n { color: '#424246', background: '#c70042', text: '#fff' },\r\n { color: '#2e4155', background: '#b35d44', text: '#fff' },\r\n { color: '#11bfce', background: '#8f98aa', text: '#fff' },\r\n { color: '#333333', background: '#549688', text: '#fff' },\r\n]","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide, SlideBackground, SlideTheme } from '@/types/slides'\r\nimport { PRESET_THEMES } from '@/configs/theme'\r\nimport { WEB_FONTS } from '@/configs/font'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nimport ColorButton from './common/ColorButton.vue'\r\nimport { getImageDataURL } from '@/utils/image'\r\n\r\nconst themes = PRESET_THEMES\r\nconst webFonts = WEB_FONTS\r\n\r\nexport default defineComponent({\r\n name: 'slide-style-panel',\r\n components: {\r\n ColorButton,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const theme = computed(() => store.state.theme)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n const availableFonts = computed(() => store.state.availableFonts)\r\n\r\n const background = computed(() => {\r\n if (!currentSlide.value.background) {\r\n return {\r\n type: 'solid',\r\n value: '#fff',\r\n } as SlideBackground\r\n }\r\n return currentSlide.value.background\r\n })\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 设置背景模式:纯色、图片、渐变色\r\n const updateBackgroundType = (type: 'solid' | 'image' | 'gradient') => {\r\n if (type === 'solid') {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'solid',\r\n color: background.value.color || '#fff',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n else if (type === 'image') {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'image',\r\n image: background.value.image || '',\r\n imageSize: background.value.imageSize || 'cover',\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n else {\r\n const newBackground: SlideBackground = {\r\n ...background.value,\r\n type: 'gradient',\r\n gradientType: background.value.gradientType || 'linear',\r\n gradientColor: background.value.gradientColor || ['#fff', '#fff'],\r\n gradientRotate: background.value.gradientRotate || 0,\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\r\n }\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置背景图片\r\n const updateBackground = (props: Partial<SlideBackground>) => {\r\n store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 上传背景图片\r\n const uploadBackgroundImage = (files: File[]) => {\r\n const imageFile = files[0]\r\n if (!imageFile) return\r\n getImageDataURL(imageFile).then(dataURL => updateBackground({ image: dataURL }))\r\n }\r\n\r\n // 应用当前页背景到全部页面\r\n const applyBackgroundAllSlide = () => {\r\n const newSlides = slides.value.map(slide => {\r\n return {\r\n ...slide,\r\n background: currentSlide.value.background,\r\n }\r\n })\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n // 设置主题\r\n const updateTheme = (themeProps: Partial<SlideTheme>) => {\r\n store.commit(MutationTypes.SET_THEME, themeProps)\r\n }\r\n\r\n // 将当前主题应用到全部页面\r\n const applyThemeAllSlide = () => {\r\n const newSlides: Slide[] = JSON.parse(JSON.stringify(slides.value))\r\n const { themeColor, backgroundColor, fontColor } = theme.value\r\n\r\n for (const slide of newSlides) {\r\n if (!slide.background || slide.background.type !== 'image') {\r\n slide.background = {\r\n ...slide.background,\r\n type: 'solid',\r\n color: backgroundColor\r\n }\r\n }\r\n\r\n const elements = slide.elements\r\n for (const el of elements) {\r\n if (el.type === 'shape') el.fill = themeColor\r\n else if (el.type === 'line') el.color = themeColor\r\n else if (el.type === 'text') {\r\n if (el.fill) el.fill = themeColor\r\n }\r\n else if (el.type === 'table') {\r\n if (el.theme) el.theme.color = themeColor\r\n }\r\n else if (el.type === 'chart') {\r\n el.themeColor = themeColor\r\n el.gridColor = fontColor\r\n }\r\n }\r\n }\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n availableFonts,\r\n background,\r\n updateBackgroundType,\r\n updateBackground,\r\n uploadBackgroundImage,\r\n applyBackgroundAllSlide,\r\n themes,\r\n theme,\r\n webFonts,\r\n updateTheme,\r\n applyThemeAllSlide,\r\n }\r\n },\r\n})\r\n","import { render } from \"./SlideStylePanel.vue?vue&type=template&id=5069f2f0&scoped=true\"\nimport script from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideStylePanel.vue?vue&type=style&index=0&id=5069f2f0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5069f2f0\"\n\nexport default script","<template>\r\n <div class=\"slide-animation-panel\">\r\n <div class=\"animation-pool\">\r\n <div \r\n class=\"animation-item\" \r\n :class=\"{ 'active': currentTurningMode === item.value }\" \r\n v-for=\"item in animations\" \r\n :key=\"item.label\"\r\n @click=\"updateTurningMode(item.value)\"\r\n >\r\n <div :class=\"['animation-block', item.value]\"></div>\r\n <div class=\"animation-text\">{{item.label}}</div>\r\n </div>\r\n </div>\r\n <Button style=\"width: 100%;\" @click=\"applyAllSlide()\">应用到全部</Button>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'slide-animation-panel',\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')\r\n\r\n const animations = [\r\n { label: '无', value: 'no' },\r\n { label: '淡入淡出', value: 'fade' },\r\n { label: '左右推移', value: 'slideX' },\r\n { label: '上下推移', value: 'slideY' },\r\n ]\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 修改播放时的切换页面方式\r\n const updateTurningMode = (mode: string) => {\r\n if (mode === currentTurningMode.value) return\r\n store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将当前页的切换页面方式应用到全部页面\r\n const applyAllSlide = () => {\r\n const newSlides = slides.value.map(slide => {\r\n return {\r\n ...slide,\r\n turningMode: currentSlide.value.turningMode,\r\n }\r\n })\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n currentTurningMode,\r\n animations,\r\n updateTurningMode,\r\n applyAllSlide,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.animation-pool {\r\n display: flex;\r\n flex-wrap: wrap;\r\n margin-bottom: 10px;\r\n}\r\n.animation-item {\r\n width: 50%;\r\n height: 115px;\r\n border: solid 1px #d6d6d6;\r\n box-sizing: border-box;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 25px 0 15px 0;\r\n position: relative;\r\n cursor: pointer;\r\n\r\n &.active {\r\n border-color: $themeColor;\r\n z-index: 1;\r\n }\r\n\r\n &:nth-child(2n) {\r\n margin-left: -1px;\r\n }\r\n &:nth-child(n+3) {\r\n margin-top: -1px;\r\n }\r\n}\r\n.animation-block {\r\n width: 64px;\r\n height: 36px;\r\n background: #666;\r\n position: relative;\r\n overflow: hidden;\r\n\r\n @mixin elAnimation($animationType) {\r\n content: '';\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n background-color: #d9dadb;\r\n animation: $animationType .3s linear;\r\n }\r\n\r\n &.fade:hover {\r\n &::after {\r\n @include elAnimation(fade);\r\n }\r\n }\r\n &.slideX:hover {\r\n &::after {\r\n @include elAnimation(slideX);\r\n }\r\n }\r\n &.slideY:hover {\r\n &::after {\r\n @include elAnimation(slideY);\r\n }\r\n }\r\n}\r\n.animation-text {\r\n font-size: 12px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n@keyframes fade {\r\n 0% {\r\n opacity: 0;\r\n }\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n@keyframes slideX {\r\n 0% {\r\n transform: translateX(100%);\r\n }\r\n 100% {\r\n transform: translateX(0);\r\n }\r\n}\r\n@keyframes slideY {\r\n 0% {\r\n transform: translateY(100%);\r\n }\r\n 100% {\r\n transform: translateY(0);\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default defineComponent({\r\n name: 'slide-animation-panel',\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')\r\n\r\n const animations = [\r\n { label: '无', value: 'no' },\r\n { label: '淡入淡出', value: 'fade' },\r\n { label: '左右推移', value: 'slideX' },\r\n { label: '上下推移', value: 'slideY' },\r\n ]\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n // 修改播放时的切换页面方式\r\n const updateTurningMode = (mode: string) => {\r\n if (mode === currentTurningMode.value) return\r\n store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })\r\n addHistorySnapshot()\r\n }\r\n\r\n // 将当前页的切换页面方式应用到全部页面\r\n const applyAllSlide = () => {\r\n const newSlides = slides.value.map(slide => {\r\n return {\r\n ...slide,\r\n turningMode: currentSlide.value.turningMode,\r\n }\r\n })\r\n store.commit(MutationTypes.SET_SLIDES, newSlides)\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n currentTurningMode,\r\n animations,\r\n updateTurningMode,\r\n applyAllSlide,\r\n }\r\n },\r\n})\r\n","import { render } from \"./SlideAnimationPanel.vue?vue&type=template&id=6e3028f1&scoped=true\"\nimport script from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideAnimationPanel.vue?vue&type=style&index=0&id=6e3028f1&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6e3028f1\"\n\nexport default script","<template>\r\n <div class=\"multi-position-panel\">\r\n <ButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"左对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('left')\"><IconAlignLeft /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"水平居中\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('horizontal')\"><IconAlignVertically /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"右对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('right')\"><IconAlignRight /></Button>\r\n </Tooltip>\r\n </ButtonGroup>\r\n <ButtonGroup class=\"row\">\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"上对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('top')\"><IconAlignTop /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"垂直居中\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('vertical')\"><IconAlignHorizontally /></Button>\r\n </Tooltip>\r\n <Tooltip :mouseLeaveDelay=\"0\" :mouseEnterDelay=\"0.5\" title=\"下对齐\">\r\n <Button style=\"flex: 1;\" @click=\"alignActiveElement('bottom')\"><IconAlignBottom /></Button>\r\n </Tooltip>\r\n </ButtonGroup>\r\n\r\n <Divider />\r\n\r\n <ButtonGroup class=\"row\">\r\n <Button :disabled=\"!canCombine\" @click=\"combineElements()\" style=\"flex: 1;\"><IconGroup style=\"margin-right: 3px;\" />组合</Button>\r\n <Button :disabled=\"canCombine\" @click=\"uncombineElements()\" style=\"flex: 1;\"><IconUngroup style=\"margin-right: 3px;\" />取消组合</Button>\r\n </ButtonGroup>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\r\nimport { getElementListRange } from '@/utils/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\nimport useCombineElement from '@/hooks/useCombineElement'\r\n\r\nexport default defineComponent({\r\n name: 'multi-position-panel',\r\n setup() {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n const { combineElements, uncombineElements } = useCombineElement()\r\n\r\n // 判断当前多选的几个元素是否可以组合\r\n const canCombine = computed(() => {\r\n const firstGroupId = activeElementList.value[0].groupId\r\n if (!firstGroupId) return true\r\n\r\n const inSameGroup = activeElementList.value.every(el => (el.groupId && el.groupId) === firstGroupId)\r\n return !inSameGroup\r\n })\r\n\r\n // 对齐选中的元素\r\n const alignActiveElement = (command: ElementAlignCommand) => {\r\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\r\n const elementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n\r\n // 如果所选择的元素为组合元素的成员,需要计算该组合的整体范围\r\n const groupElementRangeMap = {}\r\n for (const activeElement of activeElementList.value) {\r\n if (activeElement.groupId && !groupElementRangeMap[activeElement.groupId]) {\r\n const groupElements = activeElementList.value.filter(item => item.groupId === activeElement.groupId)\r\n groupElementRangeMap[activeElement.groupId] = getElementListRange(groupElements)\r\n }\r\n }\r\n\r\n // 根据不同的命令,计算对齐的位置\r\n if (command === ElementAlignCommands.LEFT) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) element.left = minX\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.minX - minX\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.RIGHT) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\r\n element.left = maxX - elWidth\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.maxX - maxX\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.TOP) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) element.top = minY\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.minY - minY\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.BOTTOM) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\r\n element.top = maxY - elHeight\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.maxY - maxY\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.HORIZONTAL) {\r\n const horizontalCenter = (minX + maxX) / 2\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\r\n element.left = horizontalCenter - elWidth / 2\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const center = (range.maxX + range.minX) / 2\r\n const offset = center - horizontalCenter\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.VERTICAL) {\r\n const verticalCenter = (minY + maxY) / 2\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\r\n element.top = verticalCenter - elHeight / 2\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const center = (range.maxY + range.minY) / 2\r\n const offset = center - verticalCenter\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n canCombine,\r\n combineElements,\r\n uncombineElements,\r\n alignActiveElement,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.row {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n}\r\n</style>","\r\nimport { computed, defineComponent } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { PPTElement, Slide } from '@/types/slides'\r\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\r\nimport { getElementListRange } from '@/utils/element'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\nimport useCombineElement from '@/hooks/useCombineElement'\r\n\r\nexport default defineComponent({\r\n name: 'multi-position-panel',\r\n setup() {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n const { combineElements, uncombineElements } = useCombineElement()\r\n\r\n // 判断当前多选的几个元素是否可以组合\r\n const canCombine = computed(() => {\r\n const firstGroupId = activeElementList.value[0].groupId\r\n if (!firstGroupId) return true\r\n\r\n const inSameGroup = activeElementList.value.every(el => (el.groupId && el.groupId) === firstGroupId)\r\n return !inSameGroup\r\n })\r\n\r\n // 对齐选中的元素\r\n const alignActiveElement = (command: ElementAlignCommand) => {\r\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\r\n const elementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\r\n\r\n // 如果所选择的元素为组合元素的成员,需要计算该组合的整体范围\r\n const groupElementRangeMap = {}\r\n for (const activeElement of activeElementList.value) {\r\n if (activeElement.groupId && !groupElementRangeMap[activeElement.groupId]) {\r\n const groupElements = activeElementList.value.filter(item => item.groupId === activeElement.groupId)\r\n groupElementRangeMap[activeElement.groupId] = getElementListRange(groupElements)\r\n }\r\n }\r\n\r\n // 根据不同的命令,计算对齐的位置\r\n if (command === ElementAlignCommands.LEFT) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) element.left = minX\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.minX - minX\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.RIGHT) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\r\n element.left = maxX - elWidth\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.maxX - maxX\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.TOP) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) element.top = minY\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.minY - minY\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.BOTTOM) {\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\r\n element.top = maxY - elHeight\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const offset = range.maxY - maxY\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.HORIZONTAL) {\r\n const horizontalCenter = (minX + maxX) / 2\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\r\n element.left = horizontalCenter - elWidth / 2\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const center = (range.maxX + range.minX) / 2\r\n const offset = center - horizontalCenter\r\n element.left = element.left - offset\r\n }\r\n }\r\n })\r\n }\r\n else if (command === ElementAlignCommands.VERTICAL) {\r\n const verticalCenter = (minY + maxY) / 2\r\n elementList.forEach(element => {\r\n if (activeElementIdList.value.includes(element.id)) {\r\n if (!element.groupId) {\r\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\r\n element.top = verticalCenter - elHeight / 2\r\n }\r\n else {\r\n const range = groupElementRangeMap[element.groupId]\r\n const center = (range.maxY + range.minY) / 2\r\n const offset = center - verticalCenter\r\n element.top = element.top - offset\r\n }\r\n }\r\n })\r\n }\r\n \r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n canCombine,\r\n combineElements,\r\n uncombineElements,\r\n alignActiveElement,\r\n }\r\n },\r\n})\r\n","import { render } from \"./MultiPositionPanel.vue?vue&type=template&id=540e3d06&scoped=true\"\nimport script from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiPositionPanel.vue?vue&type=style&index=0&id=540e3d06&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-540e3d06\"\n\nexport default script","\r\nimport { computed, defineComponent, watch } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { ToolbarState, ToolbarStates } from '@/types/toolbar'\r\n\r\nimport ElementStylePanel from './ElementStylePanel/index.vue'\r\nimport ElementPositionPanel from './ElementPositionPanel.vue'\r\nimport ElementAnimationPanel from './ElementAnimationPanel.vue'\r\nimport SlideStylePanel from './SlideStylePanel.vue'\r\nimport SlideAnimationPanel from './SlideAnimationPanel.vue'\r\nimport MultiPositionPanel from './MultiPositionPanel.vue'\r\n\r\nexport default defineComponent({\r\n name: 'toolbar',\r\n setup() {\r\n const store = useStore()\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n\r\n const elementTabs = [\r\n { label: '样式', value: ToolbarStates.EL_STYLE },\r\n { label: '位置', value: ToolbarStates.EL_POSITION },\r\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\r\n ]\r\n const slideTabs = [\r\n { label: '页面样式', value: ToolbarStates.SLIDE_STYLE },\r\n { label: '切换', value: ToolbarStates.SLIDE_ANIMATION },\r\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\r\n ]\r\n const multiSelectTabs = [\r\n { label: '位置', value: ToolbarStates.MULTI_POSITION },\r\n { label: '样式', value: ToolbarStates.EL_STYLE },\r\n ]\r\n\r\n const setToolbarState = (value: ToolbarState) => {\r\n store.commit(MutationTypes.SET_TOOLBAR_STATE, value)\r\n }\r\n\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentTabs = computed(() => {\r\n if (!activeElementIdList.value.length) return slideTabs\r\n else if (activeElementIdList.value.length > 1) return multiSelectTabs\r\n return elementTabs\r\n })\r\n\r\n watch(currentTabs, () => {\r\n const currentTabsValue = currentTabs.value.map(tab => tab.value)\r\n if (!currentTabsValue.includes(toolbarState.value)) {\r\n store.commit(MutationTypes.SET_TOOLBAR_STATE, currentTabsValue[0])\r\n }\r\n })\r\n\r\n const currentPanelComponent = computed(() => {\r\n const panelMap = {\r\n [ToolbarStates.EL_STYLE]: ElementStylePanel,\r\n [ToolbarStates.EL_POSITION]: ElementPositionPanel,\r\n [ToolbarStates.EL_ANIMATION]: ElementAnimationPanel,\r\n [ToolbarStates.SLIDE_STYLE]: SlideStylePanel,\r\n [ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,\r\n [ToolbarStates.MULTI_POSITION]: MultiPositionPanel,\r\n }\r\n return panelMap[toolbarState.value] || null\r\n })\r\n\r\n return {\r\n toolbarState,\r\n currentTabs,\r\n setToolbarState,\r\n currentPanelComponent,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=58d77c92&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=58d77c92&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-58d77c92\"\n\nexport default script","\r\nimport { defineComponent } from 'vue'\r\n\r\nimport useGlobalHotkey from '@/hooks/useGlobalHotkey'\r\nimport usePasteEvent from '@/hooks/usePasteEvent'\r\n\r\nimport EditorHeader from './EditorHeader/index.vue'\r\nimport Canvas from './Canvas/index.vue'\r\nimport CanvasTool from './CanvasTool/index.vue'\r\nimport Thumbnails from './Thumbnails/index.vue'\r\nimport Toolbar from './Toolbar/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editor',\r\n components: {\r\n EditorHeader,\r\n Canvas,\r\n CanvasTool,\r\n Thumbnails,\r\n Toolbar,\r\n },\r\n setup() {\r\n useGlobalHotkey()\r\n usePasteEvent()\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=5186b40b&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=5186b40b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5186b40b\"\n\nexport default script","<template>\r\n <div class=\"hamster-ppt-screen\">\r\n <div \r\n class=\"slide-list\"\r\n @mousewheel=\"$event => mousewheelListener($event)\"\r\n v-contextmenu=\"contextmenus\"\r\n >\r\n <div \r\n :class=\"[\r\n 'slide-item', \r\n `turning-mode-${slide.turningMode || 'slideY'}`,\r\n {\r\n 'current': index === slideIndex,\r\n 'before': index < slideIndex,\r\n 'after': index > slideIndex,\r\n 'hide': (index === slideIndex - 1 || index === slideIndex + 1) && slide.turningMode !== currentSlide.turningMode,\r\n }\r\n ]\"\r\n v-for=\"(slide, index) in slides\" \r\n :key=\"slide.id\"\r\n >\r\n <div \r\n class=\"slide-content\" \r\n :style=\"{\r\n width: slideWidth + 'px',\r\n height: slideHeight + 'px',\r\n }\"\r\n >\r\n <ScreenSlide \r\n :slide=\"slide\" \r\n :scale=\"scale\"\r\n :animationIndex=\"animationIndex\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <SlideThumbnails \r\n v-if=\"slideThumbnailModelVisible\" \r\n :turnSlideToIndex=\"turnSlideToIndex\" \r\n @close=\"slideThumbnailModelVisible = false\"\r\n />\r\n\r\n <div class=\"tools\">\r\n <IconLeftC class=\"tool-btn\" @click=\"execPrev()\" />\r\n <IconRightC class=\"tool-btn\" @click=\"execNext()\" />\r\n <IconSearch class=\"tool-btn\" @click=\"slideThumbnailModelVisible = true\" />\r\n <Popover trigger=\"click\" v-model:visible=\"writingBoardToolVisible\">\r\n <template #content>\r\n <WritingBoardTool @close=\"writingBoardToolVisible = false\" />\r\n </template>\r\n <IconWrite class=\"tool-btn\" />\r\n </Popover>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onMounted, onUnmounted, provide, ref } from 'vue'\r\nimport throttle from 'lodash/throttle'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { isFullscreen } from '@/utils/fullscreen'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport ScreenSlide from './ScreenSlide.vue'\r\nimport SlideThumbnails from './SlideThumbnails.vue'\r\nimport WritingBoardTool from './WritingBoardTool.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen',\r\n components: {\r\n ScreenSlide,\r\n SlideThumbnails,\r\n WritingBoardTool,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const slideWidth = ref(0)\r\n const slideHeight = ref(0)\r\n\r\n const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)\r\n\r\n const slideThumbnailModelVisible = ref(false)\r\n\r\n const writingBoardToolVisible = ref(false)\r\n\r\n // 计算和更新幻灯片内容的尺寸(按比例自适应屏幕)\r\n const setSlideContentSize = () => {\r\n const winWidth = document.body.clientWidth\r\n const winHeight = document.body.clientHeight\r\n let width, height\r\n\r\n if (winHeight / winWidth === VIEWPORT_ASPECT_RATIO) {\r\n width = winWidth\r\n height = winHeight\r\n }\r\n else if (winHeight / winWidth > VIEWPORT_ASPECT_RATIO) {\r\n width = winWidth\r\n height = winWidth * VIEWPORT_ASPECT_RATIO\r\n }\r\n else {\r\n width = winHeight / VIEWPORT_ASPECT_RATIO\r\n height = winHeight\r\n }\r\n slideWidth.value = width\r\n slideHeight.value = height\r\n }\r\n\r\n // 窗口尺寸变化监听:窗口发生变化时更新幻灯片的大小\r\n // 如果退出了全屏,需要返回到编辑模式\r\n const { exitScreening } = useScreening()\r\n\r\n const windowResizeListener = () => {\r\n setSlideContentSize()\r\n if (!isFullscreen()) exitScreening()\r\n }\r\n\r\n onMounted(() => {\r\n window.addEventListener('resize', windowResizeListener)\r\n })\r\n onUnmounted(() => {\r\n window.removeEventListener('resize', windowResizeListener)\r\n })\r\n\r\n // 当前页的元素动画列表和当前执行到的位置\r\n const animations = computed(() => currentSlide.value.animations || [])\r\n const animationIndex = ref(0)\r\n\r\n // 执行元素的入场动画\r\n const runAnimation = () => {\r\n const prefix = 'animate__'\r\n const animation = animations.value[animationIndex.value]\r\n animationIndex.value += 1\r\n\r\n const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`)\r\n if (elRef) {\r\n const animationName = `${prefix}${animation.type}`\r\n elRef.classList.add(`${prefix}animated`, animationName)\r\n\r\n const handleAnimationEnd = () => {\r\n elRef.classList.remove(`${prefix}animated`, animationName)\r\n }\r\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\r\n }\r\n }\r\n\r\n // 向上/向下播放\r\n // 遇到元素动画时,优先执行动画播放,无动画则执行翻页\r\n // 向上播放遇到动画时,仅撤销到动画执行前的状态,不需要反向播放动画\r\n const execPrev = () => {\r\n if (animations.value.length && animationIndex.value > 0) {\r\n animationIndex.value -= 1\r\n }\r\n else if (slideIndex.value > 0) {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\r\n const lastIndex = animations.value ? animations.value.length : 0\r\n animationIndex.value = lastIndex\r\n }\r\n }\r\n const execNext = () => {\r\n if (animations.value.length && animationIndex.value < animations.value.length) {\r\n runAnimation()\r\n }\r\n else if (slideIndex.value < slides.value.length - 1) {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\r\n animationIndex.value = 0\r\n }\r\n }\r\n\r\n // 鼠标滚动翻页\r\n const mousewheelListener = throttle(function(e: WheelEvent) {\r\n if (e.deltaY < 0) execPrev()\r\n else if (e.deltaY > 0) execNext()\r\n }, 500, { leading: true, trailing: false })\r\n\r\n // 快捷键翻页\r\n const keydownListener = (e: KeyboardEvent) => {\r\n const key = e.key.toUpperCase()\r\n if (key === KEYS.UP || key === KEYS.LEFT) execPrev()\r\n else if (\r\n key === KEYS.DOWN || \r\n key === KEYS.RIGHT ||\r\n key === KEYS.SPACE || \r\n key === KEYS.ENTER\r\n ) execNext()\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('keydown', keydownListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keydownListener)\r\n })\r\n\r\n // 切换到上一张/上一张幻灯片(无视元素的入场动画)\r\n const turnPrevSlide = () => {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\r\n animationIndex.value = 0\r\n }\r\n const turnNextSlide = () => {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\r\n animationIndex.value = 0\r\n }\r\n\r\n // 切换幻灯片到指定的页面\r\n const turnSlideToIndex = (index: number) => {\r\n slideThumbnailModelVisible.value = false\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n animationIndex.value = 0\r\n }\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '上一张',\r\n subText: '↑、←',\r\n disable: slideIndex.value <= 0,\r\n handler: () => turnPrevSlide(),\r\n },\r\n {\r\n text: '下一张',\r\n subText: '↓、→',\r\n disable: slideIndex.value >= slides.value.length - 1,\r\n handler: () => turnNextSlide(),\r\n },\r\n { divider: true },\r\n {\r\n text: '查看所有幻灯片',\r\n handler: () => slideThumbnailModelVisible.value = true,\r\n },\r\n { divider: true },\r\n {\r\n text: '结束放映',\r\n subText: 'ESC',\r\n handler: exitScreening,\r\n },\r\n ]\r\n }\r\n \r\n provide('slideScale', scale)\r\n\r\n return {\r\n slides,\r\n slideIndex,\r\n currentSlide,\r\n slideWidth,\r\n slideHeight,\r\n scale,\r\n mousewheelListener,\r\n animationIndex,\r\n contextmenus,\r\n execPrev,\r\n execNext,\r\n slideThumbnailModelVisible,\r\n turnSlideToIndex,\r\n writingBoardToolVisible,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.hamster-ppt-screen {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n background-color: #111;\r\n}\r\n.slide-list {\r\n background: #1d1d1d;\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n.slide-item {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n\r\n &.current {\r\n z-index: 2;\r\n }\r\n\r\n &.hide {\r\n opacity: 0;\r\n }\r\n\r\n &.turning-mode-no {\r\n &.before {\r\n transform: translateY(-100%);\r\n }\r\n &.after {\r\n transform: translateY(100%);\r\n }\r\n }\r\n &.turning-mode-fade {\r\n transition: opacity .75s;\r\n &.before {\r\n pointer-events: none;\r\n opacity: 0;\r\n }\r\n &.after {\r\n pointer-events: none;\r\n opacity: 0;\r\n }\r\n }\r\n &.turning-mode-slideX {\r\n transition: transform .35s;\r\n &.before {\r\n transform: translateX(-100%);\r\n }\r\n &.after {\r\n transform: translateX(100%);\r\n }\r\n }\r\n &.turning-mode-slideY {\r\n transition: transform .35s;\r\n &.before {\r\n transform: translateY(-100%);\r\n }\r\n &.after {\r\n transform: translateY(100%);\r\n }\r\n }\r\n}\r\n.slide-content {\r\n background-color: #fff;\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.tools {\r\n position: fixed;\r\n bottom: 8px;\r\n left: 8px;\r\n font-size: 25px;\r\n color: #666;\r\n z-index: 10;\r\n cursor: pointer;\r\n}\r\n.tool-btn {\r\n opacity: .35;\r\n\r\n &:hover {\r\n opacity: .7;\r\n }\r\n & + .tool-btn {\r\n margin-left: 8px;\r\n }\r\n}\r\n</style>","<template>\r\n <div \r\n class=\"screen-slide\"\r\n :style=\"{\r\n width: VIEWPORT_SIZE + 'px',\r\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO + 'px',\r\n transform: `scale(${scale})`,\r\n }\"\r\n >\r\n <div class=\"background\" :style=\"{ ...backgroundStyle }\"></div>\r\n <ScreenElement\r\n :id=\"`screen-element-${element.id}`\"\r\n v-for=\"(element, index) in slide.elements\"\r\n :key=\"element.id\"\r\n :elementInfo=\"element\"\r\n :elementIndex=\"index + 1\"\r\n :animationIndex=\"animationIndex\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nimport ScreenElement from './ScreenElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-slide',\r\n components: {\r\n ScreenElement,\r\n },\r\n props: {\r\n slide: {\r\n type: Object as PropType<Slide>,\r\n required: true,\r\n },\r\n scale: {\r\n type: Number,\r\n required: true,\r\n },\r\n animationIndex: {\r\n type: Number,\r\n default: -1,\r\n },\r\n },\r\n setup(props) {\r\n const background = computed(() => props.slide.background)\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n return {\r\n backgroundStyle,\r\n VIEWPORT_SIZE,\r\n VIEWPORT_ASPECT_RATIO,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.screen-slide {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n transform-origin: 0 0;\r\n}\r\n.background {\r\n width: 100%;\r\n height: 100%;\r\n background-position: center;\r\n position: absolute;\r\n}\r\n</style>","<template>\r\n <div \r\n class=\"screen-element\"\r\n :style=\"{\r\n zIndex: elementIndex,\r\n color: theme.fontColor,\r\n fontFamily: theme.fontName,\r\n visibility: needWaitAnimation ? 'hidden' : 'visible',\r\n }\"\r\n >\r\n <component\r\n :is=\"currentElementComponent\"\r\n :elementInfo=\"elementInfo\"\r\n ></component>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\n\r\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\r\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\r\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\r\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\r\nimport ScreenChartElement from '@/views/components/element/ChartElement/ScreenChartElement.vue'\r\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n animationIndex: {\r\n type: Number,\r\n default: -1,\r\n },\r\n },\r\n setup(props) {\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: BaseImageElement,\r\n [ElementTypes.TEXT]: BaseTextElement,\r\n [ElementTypes.SHAPE]: BaseShapeElement,\r\n [ElementTypes.LINE]: BaseLineElement,\r\n [ElementTypes.CHART]: ScreenChartElement,\r\n [ElementTypes.TABLE]: BaseTableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n // 判断元素是否需要等待执行入场动画:等待执行的元素需要先隐藏\r\n const needWaitAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n const elementIndexInAnimation = animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n if (elementIndexInAnimation !== -1 && elementIndexInAnimation >= props.animationIndex) return true\r\n return false \r\n })\r\n\r\n return {\r\n currentElementComponent,\r\n needWaitAnimation,\r\n theme,\r\n }\r\n },\r\n})\r\n</script>","<template>\r\n <div class=\"screen-element-chart\"\r\n :style=\"{\r\n top: elementInfo.top + 'px',\r\n left: elementInfo.left + 'px',\r\n width: elementInfo.width + 'px',\r\n height: elementInfo.height + 'px',\r\n }\"\r\n >\r\n <div \r\n class=\"element-content\"\r\n :style=\"{\r\n backgroundColor: elementInfo.fill,\r\n }\"\r\n >\r\n <ElementOutline\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :outline=\"elementInfo.outline\"\r\n />\r\n <Chart\r\n :width=\"elementInfo.width\"\r\n :height=\"elementInfo.height\"\r\n :type=\"elementInfo.chartType\"\r\n :data=\"elementInfo.data\"\r\n :options=\"elementInfo.options\"\r\n :themeColor=\"elementInfo.themeColor\"\r\n :gridColor=\"elementInfo.gridColor\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.screen-element-chart {\r\n position: absolute;\r\n}\r\n\r\n.element-content {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n</style>\r\n","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTChartElement>,\r\n required: true,\r\n },\r\n },\r\n})\r\n","import { render } from \"./ScreenChartElement.vue?vue&type=template&id=1423f8c2&scoped=true\"\nimport script from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenChartElement.vue?vue&type=style&index=0&id=1423f8c2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1423f8c2\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\n\r\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\r\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\r\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\r\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\r\nimport ScreenChartElement from '@/views/components/element/ChartElement/ScreenChartElement.vue'\r\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-element',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType<PPTElement>,\r\n required: true,\r\n },\r\n elementIndex: {\r\n type: Number,\r\n required: true,\r\n },\r\n animationIndex: {\r\n type: Number,\r\n default: -1,\r\n },\r\n },\r\n setup(props) {\r\n const currentElementComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: BaseImageElement,\r\n [ElementTypes.TEXT]: BaseTextElement,\r\n [ElementTypes.SHAPE]: BaseShapeElement,\r\n [ElementTypes.LINE]: BaseLineElement,\r\n [ElementTypes.CHART]: ScreenChartElement,\r\n [ElementTypes.TABLE]: BaseTableElement,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const store = useStore()\r\n const theme = computed(() => store.state.theme)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n // 判断元素是否需要等待执行入场动画:等待执行的元素需要先隐藏\r\n const needWaitAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n const elementIndexInAnimation = animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n if (elementIndexInAnimation !== -1 && elementIndexInAnimation >= props.animationIndex) return true\r\n return false \r\n })\r\n\r\n return {\r\n currentElementComponent,\r\n needWaitAnimation,\r\n theme,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ScreenElement.vue?vue&type=template&id=d0933d74\"\nimport script from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { computed, PropType, defineComponent } from 'vue'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\r\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\r\n\r\nimport ScreenElement from './ScreenElement.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen-slide',\r\n components: {\r\n ScreenElement,\r\n },\r\n props: {\r\n slide: {\r\n type: Object as PropType<Slide>,\r\n required: true,\r\n },\r\n scale: {\r\n type: Number,\r\n required: true,\r\n },\r\n animationIndex: {\r\n type: Number,\r\n default: -1,\r\n },\r\n },\r\n setup(props) {\r\n const background = computed(() => props.slide.background)\r\n const { backgroundStyle } = useSlideBackgroundStyle(background)\r\n\r\n return {\r\n backgroundStyle,\r\n VIEWPORT_SIZE,\r\n VIEWPORT_ASPECT_RATIO,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ScreenSlide.vue?vue&type=template&id=5e193d56&scoped=true\"\nimport script from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenSlide.vue?vue&type=style&index=0&id=5e193d56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5e193d56\"\n\nexport default script","<template>\r\n <div class=\"slide-thumbnails\">\r\n <div class=\"return-button\">\r\n <IconArrowCircleLeft class=\"icon\" @click=\"close()\" />\r\n </div>\r\n <div class=\"slide-thumbnails-content\">\r\n <div \r\n class=\"thumbnail\"\r\n :class=\"{ 'active': index === slideIndex }\"\r\n v-for=\"(slide, index) in slides\" \r\n :key=\"slide.id\"\r\n @click=\"turnSlideToIndex(index)\"\r\n >\r\n <ThumbnailSlide :slide=\"slide\" :size=\"150\" />\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'slide-thumbnails',\r\n components: {\r\n ThumbnailSlide,\r\n },\r\n props: {\r\n turnSlideToIndex: {\r\n type: Function as PropType<(index: number) => void>,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n\r\n const close = () => emit('close')\r\n\r\n return {\r\n slides,\r\n slideIndex,\r\n close,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.slide-thumbnails {\r\n width: 100%;\r\n height: 100%;\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n background-color: #1a1a1a;\r\n z-index: 99;\r\n}\r\n.return-button {\r\n height: 60px;\r\n padding: 20px 30px 0;\r\n\r\n .icon {\r\n color: #fff;\r\n font-size: 36px;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n color: $themeColor;\r\n }\r\n }\r\n}\r\n.slide-thumbnails-content {\r\n height: calc(100% - 100px);\r\n padding: 20px 30px 30px 30px;\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-content: flex-start;\r\n overflow: overlay;\r\n\r\n .thumbnail {\r\n width: 150px;\r\n outline: 2px solid #aaa;\r\n margin-right: 12px;\r\n margin-bottom: 12px;\r\n\r\n &:hover {\r\n outline-color: $themeColor;\r\n }\r\n\r\n &.active {\r\n outline-width: 3px;\r\n outline-color: $themeColor;\r\n }\r\n }\r\n}\r\n</style>","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'slide-thumbnails',\r\n components: {\r\n ThumbnailSlide,\r\n },\r\n props: {\r\n turnSlideToIndex: {\r\n type: Function as PropType<(index: number) => void>,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n\r\n const close = () => emit('close')\r\n\r\n return {\r\n slides,\r\n slideIndex,\r\n close,\r\n }\r\n },\r\n})\r\n","import { render } from \"./SlideThumbnails.vue?vue&type=template&id=49960bc8&scoped=true\"\nimport script from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideThumbnails.vue?vue&type=style&index=0&id=49960bc8&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-49960bc8\"\n\nexport default script","<template>\r\n <div class=\"writing-board-tool\">\r\n <teleport to=\"body\">\r\n <WritingBoard \r\n ref=\"writingBoardRef\" \r\n :color=\"writingBoardColor\" \r\n :model=\"writingBoardModel\" \r\n v-if=\"writingBoardVisible\" \r\n v-contextmenu=\"contextmenus\"\r\n />\r\n </teleport>\r\n\r\n <div class=\"tools\">\r\n <div class=\"btn\" @click=\"changePen()\">画笔</div>\r\n <div class=\"btn\" @click=\"changeEraser()\">橡皮擦</div>\r\n <div class=\"btn\" @click=\"clearCanvas()\">擦除所有墨迹</div>\r\n <div class=\"btn\" @click=\"closeWritingBoard()\">退出画笔</div>\r\n <div class=\"colors\">\r\n <div \r\n class=\"color\" \r\n :class=\"{ 'active': color === writingBoardColor }\"\r\n v-for=\"color in writingBoardColors\"\r\n :key=\"color\"\r\n :style=\"{ backgroundColor: color }\"\r\n @click=\"changeColor(color)\"\r\n ></div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, ref } from 'vue'\r\nimport WritingBoard from '@/components/WritingBoard.vue'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nconst writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\r\n\r\nexport default defineComponent({\r\n name: 'writing-board-tool',\r\n components: {\r\n WritingBoard,\r\n },\r\n setup(props, { emit }) {\r\n const writingBoardRef = ref()\r\n const writingBoardVisible = ref(false)\r\n const writingBoardColor = ref('#e2534d')\r\n const writingBoardModel = ref('pen')\r\n\r\n // 切换到画笔状态\r\n const changePen = () => {\r\n if (!writingBoardVisible.value) writingBoardVisible.value = true\r\n writingBoardModel.value = 'pen'\r\n emit('close')\r\n }\r\n\r\n // 切换到橡皮状态\r\n const changeEraser = () => {\r\n writingBoardModel.value = 'eraser'\r\n emit('close')\r\n }\r\n\r\n // 清除画布上的墨迹\r\n const clearCanvas = () => {\r\n writingBoardRef.value.clearCanvas()\r\n emit('close')\r\n }\r\n\r\n // 修改画笔颜色,如果当前不处于画笔状态则先切换到画笔状态\r\n const changeColor = (color: string) => {\r\n if (writingBoardModel.value !== 'pen') writingBoardModel.value = 'pen'\r\n writingBoardColor.value = color\r\n emit('close')\r\n }\r\n \r\n // 关闭写字板\r\n const closeWritingBoard = () => {\r\n writingBoardVisible.value = false\r\n emit('close')\r\n }\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '画笔',\r\n handler: changePen,\r\n disable: writingBoardModel.value === 'pen',\r\n },\r\n {\r\n text: '橡皮擦',\r\n handler: changeEraser,\r\n disable: writingBoardModel.value === 'eraser',\r\n },\r\n {\r\n text: '擦除所有墨迹',\r\n handler: clearCanvas,\r\n },\r\n {\r\n text: '退出画笔',\r\n handler: closeWritingBoard,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n writingBoardRef,\r\n writingBoardVisible,\r\n writingBoardColors,\r\n writingBoardColor,\r\n writingBoardModel,\r\n changePen,\r\n changeEraser,\r\n clearCanvas,\r\n changeColor,\r\n closeWritingBoard,\r\n contextmenus,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.writing-board-tool {\r\n font-size: 12px;\r\n\r\n .btn {\r\n padding: 3px 10px;\r\n margin: 0 -10px;\r\n margin-bottom: 3px;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n background-color: rgba($color: $themeColor, $alpha: .2);\r\n }\r\n }\r\n .colors {\r\n display: flex;\r\n margin-top: 8px;\r\n }\r\n .color {\r\n width: 15px;\r\n height: 15px;\r\n outline: 1px solid #ccc;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n transform: scale(1.1);\r\n }\r\n &.active {\r\n outline: 2px solid $themeColor;\r\n }\r\n\r\n & + .color {\r\n margin-left: 5px;\r\n }\r\n }\r\n}\r\n</style>","<template>\r\n <div class=\"writing-board\" ref=\"writingBoardRef\">\r\n <canvas class=\"canvas\" ref=\"canvasRef\"\r\n @mousedown=\"$event => handleMousedown($event)\"\r\n @mousemove=\"$event => handleMousemove($event)\"\r\n @mouseup=\"handleMouseup()\"\r\n @mouseleave=\"handleMouseup(); mouseInCanvas = false\"\r\n @mouseenter=\"mouseInCanvas = true\"\r\n ></canvas>\r\n\r\n <div \r\n class=\"pen\"\r\n :style=\"{\r\n left: mouse.x - penSize / 2 + 'px',\r\n top: mouse.y - 36 + penSize / 2 + 'px',\r\n color: color,\r\n }\"\r\n v-if=\"mouseInCanvas && model === 'pen'\"\r\n ><IconWrite class=\"icon\" size=\"36\" /></div>\r\n \r\n <div \r\n class=\"eraser\"\r\n :style=\"{\r\n left: mouse.x - rubberSize / 2 + 'px',\r\n top: mouse.y - rubberSize / 2 + 'px',\r\n width: rubberSize + 'px',\r\n height: rubberSize + 'px',\r\n }\"\r\n v-if=\"mouseInCanvas && model === 'eraser'\"\r\n ></div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, onMounted, PropType, reactive, ref } from 'vue'\r\n\r\nconst penSize = 6\r\nconst rubberSize = 80\r\n\r\nexport default defineComponent({\r\n name: 'writing-board',\r\n props: {\r\n color: {\r\n type: String,\r\n default: '#ffcc00',\r\n },\r\n model: {\r\n type: String as PropType<'pen' | 'eraser'>,\r\n default: 'pen',\r\n },\r\n },\r\n setup(props) {\r\n let ctx: CanvasRenderingContext2D | null = null\r\n const writingBoardRef = ref<HTMLElement>()\r\n const canvasRef = ref<HTMLCanvasElement>()\r\n\r\n let lastPos = {\r\n x: 0,\r\n y: 0,\r\n }\r\n let isMouseDown = false\r\n let lastTime = 0\r\n let lastLineWidth = -1\r\n\r\n // 鼠标位置坐标:用于画笔或橡皮位置跟随\r\n const mouse = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n // 更新鼠标位置坐标\r\n const updateMousePosition = (e: MouseEvent) => {\r\n mouse.x = e.pageX\r\n mouse.y = e.pageY\r\n }\r\n \r\n // 鼠标是否处在画布范围内:处在范围内才会显示画笔或橡皮\r\n const mouseInCanvas = ref(false)\r\n\r\n\r\n // 初始化画布\r\n const initCanvas = () => {\r\n if (!canvasRef.value || !writingBoardRef.value) return\r\n\r\n ctx = canvasRef.value.getContext('2d')\r\n if (!ctx) return\r\n\r\n canvasRef.value.width = writingBoardRef.value.clientWidth\r\n canvasRef.value.height = writingBoardRef.value.clientHeight\r\n\r\n canvasRef.value.style.width = writingBoardRef.value.clientWidth + 'px'\r\n canvasRef.value.style.height = writingBoardRef.value.clientHeight + 'px'\r\n\r\n ctx.lineCap = 'round'\r\n ctx.lineJoin = 'round'\r\n }\r\n onMounted(initCanvas)\r\n\r\n // 绘制画笔墨迹方法\r\n const draw = (posX: number, posY: number, lineWidth: number) => {\r\n if (!ctx) return\r\n\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n ctx.lineWidth = lineWidth\r\n ctx.strokeStyle = props.color\r\n ctx.beginPath()\r\n ctx.moveTo(lastPosX, lastPosY)\r\n ctx.lineTo(posX, posY)\r\n ctx.stroke()\r\n ctx.closePath()\r\n }\r\n\r\n // 擦除墨迹方法\r\n const erase = (posX: number, posY: number) => {\r\n if (!ctx || !canvasRef.value) return\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n const radius = rubberSize / 2\r\n\r\n const sinRadius = radius * Math.sin(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const cosRadius = radius * Math.cos(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const rectPoint1: [number, number] = [lastPosX + sinRadius, lastPosY - cosRadius]\r\n const rectPoint2: [number, number] = [lastPosX - sinRadius, lastPosY + cosRadius]\r\n const rectPoint3: [number, number] = [posX + sinRadius, posY - cosRadius]\r\n const rectPoint4: [number, number] = [posX - sinRadius, posY + cosRadius]\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.arc(posX, posY, radius, 0, Math.PI * 2)\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.moveTo(...rectPoint1)\r\n ctx.lineTo(...rectPoint3)\r\n ctx.lineTo(...rectPoint4)\r\n ctx.lineTo(...rectPoint2)\r\n ctx.closePath()\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n }\r\n\r\n // 准备开始绘制/擦除墨迹(落笔)\r\n const handleMousedown = (e: MouseEvent) => {\r\n isMouseDown = true\r\n lastPos = { x: e.offsetX, y: e.offsetY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n // 计算鼠标两次移动之间的距离\r\n const getDistance = (posX: number, posY: number) => {\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n return Math.sqrt((posX - lastPosX) * (posX - lastPosX) + (posY - lastPosY) * (posY - lastPosY))\r\n }\r\n\r\n // 根据鼠标两次移动之间的距离s和时间t计算绘制速度,速度越快,墨迹越细\r\n const getLineWidth = (s: number, t: number) => {\r\n const maxV = 10\r\n const minV = 0.1\r\n const maxWidth = penSize\r\n const minWidth = 3\r\n const v = s / t\r\n let lineWidth\r\n\r\n if (v <= minV) lineWidth = maxWidth\r\n else if (v >= maxV) lineWidth = minWidth\r\n else lineWidth = maxWidth - v / maxV * maxWidth\r\n\r\n if (lastLineWidth === -1) return lineWidth\r\n return lineWidth * 1 / 3 + lastLineWidth * 2 / 3\r\n }\r\n\r\n // 开始绘制/擦除墨迹(移动)\r\n const handleMousemove = (e: MouseEvent) => {\r\n updateMousePosition(e)\r\n\r\n if (!isMouseDown) return\r\n \r\n const time = new Date().getTime()\r\n\r\n if (props.model === 'pen') {\r\n const s = getDistance(e.offsetX, e.offsetY)\r\n const t = time - lastTime\r\n const lineWidth = getLineWidth(s, t)\r\n \r\n draw(e.offsetX, e.offsetY, lineWidth)\r\n lastLineWidth = lineWidth\r\n }\r\n else erase(e.offsetX, e.offsetY)\r\n\r\n lastPos = { x: e.offsetX, y: e.offsetY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n // 结束绘制/擦除墨迹(停笔)\r\n const handleMouseup = () => {\r\n if (!isMouseDown) return\r\n isMouseDown = false\r\n }\r\n\r\n // 清空画布\r\n const clearCanvas = () => {\r\n if (!ctx || !canvasRef.value) return\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n }\r\n\r\n return {\r\n mouse,\r\n mouseInCanvas,\r\n penSize,\r\n rubberSize,\r\n writingBoardRef,\r\n canvasRef,\r\n handleMousedown,\r\n handleMousemove,\r\n handleMouseup,\r\n clearCanvas,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.writing-board {\r\n position: fixed;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 8;\r\n cursor: none;\r\n}\r\n.eraser, .pen {\r\n pointer-events: none;\r\n position: fixed;\r\n z-index: 9;\r\n\r\n .icon {\r\n filter: drop-shadow(2px 2px 2px #555);\r\n }\r\n}\r\n.eraser {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n border-radius: 50%;\r\n border: 4px solid rgba($color: #555, $alpha: .15);\r\n color: rgba($color: #555, $alpha: .75);\r\n}\r\n</style>","\r\nimport { defineComponent, onMounted, PropType, reactive, ref } from 'vue'\r\n\r\nconst penSize = 6\r\nconst rubberSize = 80\r\n\r\nexport default defineComponent({\r\n name: 'writing-board',\r\n props: {\r\n color: {\r\n type: String,\r\n default: '#ffcc00',\r\n },\r\n model: {\r\n type: String as PropType<'pen' | 'eraser'>,\r\n default: 'pen',\r\n },\r\n },\r\n setup(props) {\r\n let ctx: CanvasRenderingContext2D | null = null\r\n const writingBoardRef = ref<HTMLElement>()\r\n const canvasRef = ref<HTMLCanvasElement>()\r\n\r\n let lastPos = {\r\n x: 0,\r\n y: 0,\r\n }\r\n let isMouseDown = false\r\n let lastTime = 0\r\n let lastLineWidth = -1\r\n\r\n // 鼠标位置坐标:用于画笔或橡皮位置跟随\r\n const mouse = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n // 更新鼠标位置坐标\r\n const updateMousePosition = (e: MouseEvent) => {\r\n mouse.x = e.pageX\r\n mouse.y = e.pageY\r\n }\r\n \r\n // 鼠标是否处在画布范围内:处在范围内才会显示画笔或橡皮\r\n const mouseInCanvas = ref(false)\r\n\r\n\r\n // 初始化画布\r\n const initCanvas = () => {\r\n if (!canvasRef.value || !writingBoardRef.value) return\r\n\r\n ctx = canvasRef.value.getContext('2d')\r\n if (!ctx) return\r\n\r\n canvasRef.value.width = writingBoardRef.value.clientWidth\r\n canvasRef.value.height = writingBoardRef.value.clientHeight\r\n\r\n canvasRef.value.style.width = writingBoardRef.value.clientWidth + 'px'\r\n canvasRef.value.style.height = writingBoardRef.value.clientHeight + 'px'\r\n\r\n ctx.lineCap = 'round'\r\n ctx.lineJoin = 'round'\r\n }\r\n onMounted(initCanvas)\r\n\r\n // 绘制画笔墨迹方法\r\n const draw = (posX: number, posY: number, lineWidth: number) => {\r\n if (!ctx) return\r\n\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n ctx.lineWidth = lineWidth\r\n ctx.strokeStyle = props.color\r\n ctx.beginPath()\r\n ctx.moveTo(lastPosX, lastPosY)\r\n ctx.lineTo(posX, posY)\r\n ctx.stroke()\r\n ctx.closePath()\r\n }\r\n\r\n // 擦除墨迹方法\r\n const erase = (posX: number, posY: number) => {\r\n if (!ctx || !canvasRef.value) return\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n const radius = rubberSize / 2\r\n\r\n const sinRadius = radius * Math.sin(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const cosRadius = radius * Math.cos(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const rectPoint1: [number, number] = [lastPosX + sinRadius, lastPosY - cosRadius]\r\n const rectPoint2: [number, number] = [lastPosX - sinRadius, lastPosY + cosRadius]\r\n const rectPoint3: [number, number] = [posX + sinRadius, posY - cosRadius]\r\n const rectPoint4: [number, number] = [posX - sinRadius, posY + cosRadius]\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.arc(posX, posY, radius, 0, Math.PI * 2)\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.moveTo(...rectPoint1)\r\n ctx.lineTo(...rectPoint3)\r\n ctx.lineTo(...rectPoint4)\r\n ctx.lineTo(...rectPoint2)\r\n ctx.closePath()\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n }\r\n\r\n // 准备开始绘制/擦除墨迹(落笔)\r\n const handleMousedown = (e: MouseEvent) => {\r\n isMouseDown = true\r\n lastPos = { x: e.offsetX, y: e.offsetY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n // 计算鼠标两次移动之间的距离\r\n const getDistance = (posX: number, posY: number) => {\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n return Math.sqrt((posX - lastPosX) * (posX - lastPosX) + (posY - lastPosY) * (posY - lastPosY))\r\n }\r\n\r\n // 根据鼠标两次移动之间的距离s和时间t计算绘制速度,速度越快,墨迹越细\r\n const getLineWidth = (s: number, t: number) => {\r\n const maxV = 10\r\n const minV = 0.1\r\n const maxWidth = penSize\r\n const minWidth = 3\r\n const v = s / t\r\n let lineWidth\r\n\r\n if (v <= minV) lineWidth = maxWidth\r\n else if (v >= maxV) lineWidth = minWidth\r\n else lineWidth = maxWidth - v / maxV * maxWidth\r\n\r\n if (lastLineWidth === -1) return lineWidth\r\n return lineWidth * 1 / 3 + lastLineWidth * 2 / 3\r\n }\r\n\r\n // 开始绘制/擦除墨迹(移动)\r\n const handleMousemove = (e: MouseEvent) => {\r\n updateMousePosition(e)\r\n\r\n if (!isMouseDown) return\r\n \r\n const time = new Date().getTime()\r\n\r\n if (props.model === 'pen') {\r\n const s = getDistance(e.offsetX, e.offsetY)\r\n const t = time - lastTime\r\n const lineWidth = getLineWidth(s, t)\r\n \r\n draw(e.offsetX, e.offsetY, lineWidth)\r\n lastLineWidth = lineWidth\r\n }\r\n else erase(e.offsetX, e.offsetY)\r\n\r\n lastPos = { x: e.offsetX, y: e.offsetY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n // 结束绘制/擦除墨迹(停笔)\r\n const handleMouseup = () => {\r\n if (!isMouseDown) return\r\n isMouseDown = false\r\n }\r\n\r\n // 清空画布\r\n const clearCanvas = () => {\r\n if (!ctx || !canvasRef.value) return\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n }\r\n\r\n return {\r\n mouse,\r\n mouseInCanvas,\r\n penSize,\r\n rubberSize,\r\n writingBoardRef,\r\n canvasRef,\r\n handleMousedown,\r\n handleMousemove,\r\n handleMouseup,\r\n clearCanvas,\r\n }\r\n },\r\n})\r\n","import { render } from \"./WritingBoard.vue?vue&type=template&id=4ddc4b2c&scoped=true\"\nimport script from \"./WritingBoard.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoard.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoard.vue?vue&type=style&index=0&id=4ddc4b2c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4ddc4b2c\"\n\nexport default script","\r\nimport { defineComponent, ref } from 'vue'\r\nimport WritingBoard from '@/components/WritingBoard.vue'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nconst writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\r\n\r\nexport default defineComponent({\r\n name: 'writing-board-tool',\r\n components: {\r\n WritingBoard,\r\n },\r\n setup(props, { emit }) {\r\n const writingBoardRef = ref()\r\n const writingBoardVisible = ref(false)\r\n const writingBoardColor = ref('#e2534d')\r\n const writingBoardModel = ref('pen')\r\n\r\n // 切换到画笔状态\r\n const changePen = () => {\r\n if (!writingBoardVisible.value) writingBoardVisible.value = true\r\n writingBoardModel.value = 'pen'\r\n emit('close')\r\n }\r\n\r\n // 切换到橡皮状态\r\n const changeEraser = () => {\r\n writingBoardModel.value = 'eraser'\r\n emit('close')\r\n }\r\n\r\n // 清除画布上的墨迹\r\n const clearCanvas = () => {\r\n writingBoardRef.value.clearCanvas()\r\n emit('close')\r\n }\r\n\r\n // 修改画笔颜色,如果当前不处于画笔状态则先切换到画笔状态\r\n const changeColor = (color: string) => {\r\n if (writingBoardModel.value !== 'pen') writingBoardModel.value = 'pen'\r\n writingBoardColor.value = color\r\n emit('close')\r\n }\r\n \r\n // 关闭写字板\r\n const closeWritingBoard = () => {\r\n writingBoardVisible.value = false\r\n emit('close')\r\n }\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '画笔',\r\n handler: changePen,\r\n disable: writingBoardModel.value === 'pen',\r\n },\r\n {\r\n text: '橡皮擦',\r\n handler: changeEraser,\r\n disable: writingBoardModel.value === 'eraser',\r\n },\r\n {\r\n text: '擦除所有墨迹',\r\n handler: clearCanvas,\r\n },\r\n {\r\n text: '退出画笔',\r\n handler: closeWritingBoard,\r\n },\r\n ]\r\n }\r\n\r\n return {\r\n writingBoardRef,\r\n writingBoardVisible,\r\n writingBoardColors,\r\n writingBoardColor,\r\n writingBoardModel,\r\n changePen,\r\n changeEraser,\r\n clearCanvas,\r\n changeColor,\r\n closeWritingBoard,\r\n contextmenus,\r\n }\r\n },\r\n})\r\n","import { render } from \"./WritingBoardTool.vue?vue&type=template&id=0bfb345d&scoped=true\"\nimport script from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoardTool.vue?vue&type=style&index=0&id=0bfb345d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0bfb345d\"\n\nexport default script","\r\nimport { computed, defineComponent, onMounted, onUnmounted, provide, ref } from 'vue'\r\nimport throttle from 'lodash/throttle'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\nimport { isFullscreen } from '@/utils/fullscreen'\r\nimport useScreening from '@/hooks/useScreening'\r\n\r\nimport ScreenSlide from './ScreenSlide.vue'\r\nimport SlideThumbnails from './SlideThumbnails.vue'\r\nimport WritingBoardTool from './WritingBoardTool.vue'\r\n\r\nexport default defineComponent({\r\n name: 'screen',\r\n components: {\r\n ScreenSlide,\r\n SlideThumbnails,\r\n WritingBoardTool,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const slides = computed(() => store.state.slides)\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n const currentSlide = computed<Slide>(() => store.getters.currentSlide)\r\n\r\n const slideWidth = ref(0)\r\n const slideHeight = ref(0)\r\n\r\n const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)\r\n\r\n const slideThumbnailModelVisible = ref(false)\r\n\r\n const writingBoardToolVisible = ref(false)\r\n\r\n // 计算和更新幻灯片内容的尺寸(按比例自适应屏幕)\r\n const setSlideContentSize = () => {\r\n const winWidth = document.body.clientWidth\r\n const winHeight = document.body.clientHeight\r\n let width, height\r\n\r\n if (winHeight / winWidth === VIEWPORT_ASPECT_RATIO) {\r\n width = winWidth\r\n height = winHeight\r\n }\r\n else if (winHeight / winWidth > VIEWPORT_ASPECT_RATIO) {\r\n width = winWidth\r\n height = winWidth * VIEWPORT_ASPECT_RATIO\r\n }\r\n else {\r\n width = winHeight / VIEWPORT_ASPECT_RATIO\r\n height = winHeight\r\n }\r\n slideWidth.value = width\r\n slideHeight.value = height\r\n }\r\n\r\n // 窗口尺寸变化监听:窗口发生变化时更新幻灯片的大小\r\n // 如果退出了全屏,需要返回到编辑模式\r\n const { exitScreening } = useScreening()\r\n\r\n const windowResizeListener = () => {\r\n setSlideContentSize()\r\n if (!isFullscreen()) exitScreening()\r\n }\r\n\r\n onMounted(() => {\r\n window.addEventListener('resize', windowResizeListener)\r\n })\r\n onUnmounted(() => {\r\n window.removeEventListener('resize', windowResizeListener)\r\n })\r\n\r\n // 当前页的元素动画列表和当前执行到的位置\r\n const animations = computed(() => currentSlide.value.animations || [])\r\n const animationIndex = ref(0)\r\n\r\n // 执行元素的入场动画\r\n const runAnimation = () => {\r\n const prefix = 'animate__'\r\n const animation = animations.value[animationIndex.value]\r\n animationIndex.value += 1\r\n\r\n const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`)\r\n if (elRef) {\r\n const animationName = `${prefix}${animation.type}`\r\n elRef.classList.add(`${prefix}animated`, animationName)\r\n\r\n const handleAnimationEnd = () => {\r\n elRef.classList.remove(`${prefix}animated`, animationName)\r\n }\r\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\r\n }\r\n }\r\n\r\n // 向上/向下播放\r\n // 遇到元素动画时,优先执行动画播放,无动画则执行翻页\r\n // 向上播放遇到动画时,仅撤销到动画执行前的状态,不需要反向播放动画\r\n const execPrev = () => {\r\n if (animations.value.length && animationIndex.value > 0) {\r\n animationIndex.value -= 1\r\n }\r\n else if (slideIndex.value > 0) {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\r\n const lastIndex = animations.value ? animations.value.length : 0\r\n animationIndex.value = lastIndex\r\n }\r\n }\r\n const execNext = () => {\r\n if (animations.value.length && animationIndex.value < animations.value.length) {\r\n runAnimation()\r\n }\r\n else if (slideIndex.value < slides.value.length - 1) {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\r\n animationIndex.value = 0\r\n }\r\n }\r\n\r\n // 鼠标滚动翻页\r\n const mousewheelListener = throttle(function(e: WheelEvent) {\r\n if (e.deltaY < 0) execPrev()\r\n else if (e.deltaY > 0) execNext()\r\n }, 500, { leading: true, trailing: false })\r\n\r\n // 快捷键翻页\r\n const keydownListener = (e: KeyboardEvent) => {\r\n const key = e.key.toUpperCase()\r\n if (key === KEYS.UP || key === KEYS.LEFT) execPrev()\r\n else if (\r\n key === KEYS.DOWN || \r\n key === KEYS.RIGHT ||\r\n key === KEYS.SPACE || \r\n key === KEYS.ENTER\r\n ) execNext()\r\n }\r\n\r\n onMounted(() => {\r\n document.addEventListener('keydown', keydownListener)\r\n })\r\n onUnmounted(() => {\r\n document.removeEventListener('keydown', keydownListener)\r\n })\r\n\r\n // 切换到上一张/上一张幻灯片(无视元素的入场动画)\r\n const turnPrevSlide = () => {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\r\n animationIndex.value = 0\r\n }\r\n const turnNextSlide = () => {\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\r\n animationIndex.value = 0\r\n }\r\n\r\n // 切换幻灯片到指定的页面\r\n const turnSlideToIndex = (index: number) => {\r\n slideThumbnailModelVisible.value = false\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\r\n animationIndex.value = 0\r\n }\r\n\r\n const contextmenus = (): ContextmenuItem[] => {\r\n return [\r\n {\r\n text: '上一张',\r\n subText: '↑、←',\r\n disable: slideIndex.value <= 0,\r\n handler: () => turnPrevSlide(),\r\n },\r\n {\r\n text: '下一张',\r\n subText: '↓、→',\r\n disable: slideIndex.value >= slides.value.length - 1,\r\n handler: () => turnNextSlide(),\r\n },\r\n { divider: true },\r\n {\r\n text: '查看所有幻灯片',\r\n handler: () => slideThumbnailModelVisible.value = true,\r\n },\r\n { divider: true },\r\n {\r\n text: '结束放映',\r\n subText: 'ESC',\r\n handler: exitScreening,\r\n },\r\n ]\r\n }\r\n \r\n provide('slideScale', scale)\r\n\r\n return {\r\n slides,\r\n slideIndex,\r\n currentSlide,\r\n slideWidth,\r\n slideHeight,\r\n scale,\r\n mousewheelListener,\r\n animationIndex,\r\n contextmenus,\r\n execPrev,\r\n execNext,\r\n slideThumbnailModelVisible,\r\n turnSlideToIndex,\r\n writingBoardToolVisible,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=7ab5e859&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=7ab5e859&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7ab5e859\"\n\nexport default script","\r\nimport { computed, defineComponent, onMounted } from 'vue'\r\nimport { MutationTypes, ActionTypes, useStore } from '@/store'\r\n\r\nimport Editor from './views/Editor/index.vue'\r\nimport Screen from './views/Screen/index.vue'\r\n\r\nexport default defineComponent({\r\n name: 'app',\r\n components: {\r\n Editor,\r\n Screen,\r\n },\r\n setup() {\r\n const store = useStore()\r\n const screening = computed(() => store.state.screening)\r\n\r\n onMounted(() => {\r\n store.commit(MutationTypes.SET_AVAILABLE_FONTS)\r\n store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)\r\n })\r\n\r\n return {\r\n screening,\r\n }\r\n },\r\n})\r\n","import { render } from \"./App.vue?vue&type=template&id=7fa1c35b\"\nimport script from \"./App.vue?vue&type=script&lang=ts\"\nexport * from \"./App.vue?vue&type=script&lang=ts\"\n\nimport \"./App.vue?vue&type=style&index=0&id=7fa1c35b&lang=scss\"\nscript.render = render\n\nexport default script","<template>\r\n <div \r\n class=\"mask\"\r\n @contextmenu.prevent=\"removeContextmenu()\"\r\n @mousedown=\"removeContextmenu()\"\r\n ></div>\r\n\r\n <div \r\n class=\"contextmenu\"\r\n :style=\"{\r\n left: style.left + 'px',\r\n top: style.top + 'px',\r\n }\"\r\n @contextmenu.prevent\r\n >\r\n <MenuContent \r\n :menus=\"menus\"\r\n :handleClickMenuItem=\"handleClickMenuItem\" \r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { ContextmenuItem, Axis } from './types'\r\n\r\nimport MenuContent from './MenuContent.vue'\r\n\r\nexport default defineComponent({\r\n name: 'contextmenu',\r\n components: {\r\n MenuContent,\r\n },\r\n props: {\r\n axis: {\r\n type: Object as PropType<Axis>,\r\n required: true,\r\n },\r\n el: {\r\n type: Object as PropType<HTMLElement>,\r\n required: true,\r\n },\r\n menus: {\r\n type: Array as PropType<ContextmenuItem[]>,\r\n required: true,\r\n },\r\n removeContextmenu: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const style = computed(() => {\r\n const MENU_WIDTH = 170\r\n const MENU_HEIGHT = 30\r\n const DIVIDER_HEIGHT = 11\r\n const PADDING = 5\r\n\r\n const { x, y } = props.axis\r\n const menuCount = props.menus.filter(menu => !(menu.divider || menu.hide)).length\r\n const dividerCount = props.menus.filter(menu => menu.divider).length\r\n\r\n const menuWidth = MENU_WIDTH\r\n const menuHeight = menuCount * MENU_HEIGHT + dividerCount * DIVIDER_HEIGHT + PADDING * 2\r\n\r\n const screenWidth = document.body.clientWidth\r\n const screenHeight = document.body.clientHeight\r\n\r\n return {\r\n left: screenWidth <= x + menuWidth ? x - menuWidth : x,\r\n top: screenHeight <= y + menuHeight ? y - menuHeight : y,\r\n }\r\n })\r\n\r\n const handleClickMenuItem = (item: ContextmenuItem) => {\r\n if (item.disable || item.children) return\r\n if (item.handler) item.handler(props.el)\r\n props.removeContextmenu()\r\n }\r\n\r\n return {\r\n style,\r\n handleClickMenuItem,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n.mask {\r\n position: fixed;\r\n left: 0;\r\n top: 0;\r\n width: 100vw;\r\n height: 100vh;\r\n z-index: 9998;\r\n}\r\n.contextmenu {\r\n position: fixed;\r\n z-index: 9999;\r\n user-select: none;\r\n}\r\n</style>","<template>\r\n <ul class=\"menu-content\">\r\n <template v-for=\"(menu, index) in menus\" :key=\"menu.text || index\">\r\n <li\r\n v-if=\"!menu.hide\"\r\n class=\"menu-item\"\r\n @click.stop=\"handleClickMenuItem(menu)\"\r\n :class=\"{'divider': menu.divider, 'disable': menu.disable}\"\r\n >\r\n <div class=\"menu-item-content\" :class=\"{'has-children': menu.children}\" v-if=\"!menu.divider\">\r\n <span class=\"text\">{{menu.text}}</span>\r\n <span class=\"sub-text\" v-if=\"menu.subText && !menu.children\">{{menu.subText}}</span>\r\n\r\n <menu-content \r\n class=\"sub-menu\"\r\n :menus=\"menu.children\" \r\n v-if=\"menu.children && menu.children.length\"\r\n :handleClickMenuItem=\"handleClickMenuItem\" \r\n />\r\n </div>\r\n </li>\r\n </template>\r\n </ul>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { PropType, defineComponent } from 'vue'\r\nimport { ContextmenuItem } from './types'\r\n\r\nexport default defineComponent({\r\n name: 'menu-content',\r\n props: {\r\n menus: {\r\n type: Array as PropType<ContextmenuItem[]>,\r\n required: true,\r\n },\r\n handleClickMenuItem: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n$menuWidth: 170px;\r\n$menuHeight: 30px;\r\n$subMenuWidth: 120px;\r\n\r\n.menu-content {\r\n width: $menuWidth;\r\n padding: 5px 0;\r\n background: #fff;\r\n border: 1px solid $borderColor;\r\n box-shadow: $boxShadow;\r\n border-radius: 2px;\r\n list-style: none;\r\n margin: 0;\r\n}\r\n.menu-item {\r\n padding: 0 20px;\r\n color: #555;\r\n font-size: 12px;\r\n transition: all .1s;\r\n white-space: nowrap;\r\n height: $menuHeight;\r\n line-height: $menuHeight;\r\n background-color: #fff;\r\n cursor: pointer;\r\n\r\n &:not(.disable):hover > .menu-item-content > .sub-menu {\r\n display: block;\r\n }\r\n\r\n &:hover:not(.disable) {\r\n background-color: rgba($color: $themeColor, $alpha: .2);\r\n }\r\n\r\n &.divider {\r\n height: 1px;\r\n overflow: hidden;\r\n margin: 5px;\r\n background-color: #e5e5e5;\r\n line-height: 0;\r\n padding: 0;\r\n }\r\n\r\n &.disable {\r\n color: #b1b1b1;\r\n cursor: no-drop;\r\n }\r\n}\r\n.menu-item-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n position: relative;\r\n\r\n &.has-children::before {\r\n content: '';\r\n display: inline-block;\r\n width: 8px;\r\n height: 8px;\r\n border-width: 1px;\r\n border-style: solid;\r\n border-color: #666 #666 transparent transparent;\r\n position: absolute;\r\n right: 0;\r\n top: 50%;\r\n transform: translateY(-50%) rotate(45deg);\r\n }\r\n .sub-text {\r\n opacity: 0.6;\r\n }\r\n .sub-menu {\r\n width: $subMenuWidth;\r\n position: absolute;\r\n display: none;\r\n left: 112%;\r\n top: -6px;\r\n }\r\n}\r\n</style>","\r\nimport { PropType, defineComponent } from 'vue'\r\nimport { ContextmenuItem } from './types'\r\n\r\nexport default defineComponent({\r\n name: 'menu-content',\r\n props: {\r\n menus: {\r\n type: Array as PropType<ContextmenuItem[]>,\r\n required: true,\r\n },\r\n handleClickMenuItem: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n})\r\n","import { render } from \"./MenuContent.vue?vue&type=template&id=d08042ec&scoped=true\"\nimport script from \"./MenuContent.vue?vue&type=script&lang=ts\"\nexport * from \"./MenuContent.vue?vue&type=script&lang=ts\"\n\nimport \"./MenuContent.vue?vue&type=style&index=0&id=d08042ec&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d08042ec\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { ContextmenuItem, Axis } from './types'\r\n\r\nimport MenuContent from './MenuContent.vue'\r\n\r\nexport default defineComponent({\r\n name: 'contextmenu',\r\n components: {\r\n MenuContent,\r\n },\r\n props: {\r\n axis: {\r\n type: Object as PropType<Axis>,\r\n required: true,\r\n },\r\n el: {\r\n type: Object as PropType<HTMLElement>,\r\n required: true,\r\n },\r\n menus: {\r\n type: Array as PropType<ContextmenuItem[]>,\r\n required: true,\r\n },\r\n removeContextmenu: {\r\n type: Function,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const style = computed(() => {\r\n const MENU_WIDTH = 170\r\n const MENU_HEIGHT = 30\r\n const DIVIDER_HEIGHT = 11\r\n const PADDING = 5\r\n\r\n const { x, y } = props.axis\r\n const menuCount = props.menus.filter(menu => !(menu.divider || menu.hide)).length\r\n const dividerCount = props.menus.filter(menu => menu.divider).length\r\n\r\n const menuWidth = MENU_WIDTH\r\n const menuHeight = menuCount * MENU_HEIGHT + dividerCount * DIVIDER_HEIGHT + PADDING * 2\r\n\r\n const screenWidth = document.body.clientWidth\r\n const screenHeight = document.body.clientHeight\r\n\r\n return {\r\n left: screenWidth <= x + menuWidth ? x - menuWidth : x,\r\n top: screenHeight <= y + menuHeight ? y - menuHeight : y,\r\n }\r\n })\r\n\r\n const handleClickMenuItem = (item: ContextmenuItem) => {\r\n if (item.disable || item.children) return\r\n if (item.handler) item.handler(props.el)\r\n props.removeContextmenu()\r\n }\r\n\r\n return {\r\n style,\r\n handleClickMenuItem,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=71468c62\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=71468c62&lang=scss\"\nscript.render = render\n\nexport default script","import { Directive, createVNode, render, DirectiveBinding } from 'vue'\r\nimport ContextmenuComponent from '@/components/Contextmenu/index.vue'\r\n\r\nconst CTX_CONTEXTMENU_HANDLER = 'CTX_CONTEXTMENU_HANDLER'\r\n\r\nconst contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\r\n event.stopPropagation()\r\n event.preventDefault()\r\n\r\n const menus = binding.value(el)\r\n if (!menus) return\r\n\r\n let container: HTMLDivElement | null = null\r\n\r\n // 移除右键菜单并取消相关的事件监听\r\n const removeContextmenu = () => {\r\n if (container) {\r\n document.body.removeChild(container)\r\n container = null\r\n }\r\n el.classList.remove('contextmenu-active')\r\n document.body.removeEventListener('scroll', removeContextmenu) \r\n window.removeEventListener('resize', removeContextmenu)\r\n }\r\n\r\n // 创建自定义菜单\r\n const options = {\r\n axis: { x: event.x, y: event.y },\r\n el,\r\n menus,\r\n removeContextmenu,\r\n }\r\n container = document.createElement('div')\r\n const vm = createVNode(ContextmenuComponent, options, null)\r\n render(vm, container)\r\n document.body.appendChild(container)\r\n\r\n // 为目标节点添加菜单激活状态的className\r\n el.classList.add('contextmenu-active')\r\n\r\n // 页面变化时移除菜单\r\n document.body.addEventListener('scroll', removeContextmenu)\r\n window.addEventListener('resize', removeContextmenu)\r\n}\r\n\r\nconst ContextmenuDirective: Directive = {\r\n mounted(el: HTMLElement, binding) {\r\n el[CTX_CONTEXTMENU_HANDLER] = (event: MouseEvent) => contextmenuListener(el, event, binding)\r\n el.addEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\r\n },\r\n\r\n unmounted(el: HTMLElement) {\r\n if (el && el[CTX_CONTEXTMENU_HANDLER]) {\r\n el.removeEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\r\n delete el[CTX_CONTEXTMENU_HANDLER]\r\n }\r\n },\r\n}\r\n\r\nexport default ContextmenuDirective","import { Directive, DirectiveBinding } from 'vue'\r\n\r\nconst CTX_CLICK_OUTSIDE_HANDLER = 'CTX_CLICK_OUTSIDE_HANDLER'\r\n\r\nconst clickListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\r\n const handler = binding.value\r\n\r\n const path = event.composedPath()\r\n const isClickOutside = path ? path.indexOf(el) < 0 : !el.contains(event.target as HTMLElement)\r\n\r\n if (!isClickOutside) return\r\n handler(event)\r\n}\r\n\r\nconst ClickOutsideDirective: Directive = {\r\n mounted(el: HTMLElement, binding) {\r\n el[CTX_CLICK_OUTSIDE_HANDLER] = (event: MouseEvent) => clickListener(el, event, binding)\r\n setTimeout(() => {\r\n document.addEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\r\n }, 0)\r\n },\r\n \r\n unmounted(el: HTMLElement) {\r\n if (el[CTX_CLICK_OUTSIDE_HANDLER]) {\r\n document.removeEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\r\n delete el[CTX_CLICK_OUTSIDE_HANDLER]\r\n }\r\n },\r\n}\r\n\r\nexport default ClickOutsideDirective","// https://iconpark.bytedance.com/official\r\n\r\nimport { App } from 'vue'\r\nimport {\r\n PlayOne,\r\n Lock,\r\n Unlock,\r\n Search,\r\n Ppt,\r\n Format,\r\n Picture,\r\n FullScreen,\r\n List,\r\n OrderedList,\r\n Helpcenter,\r\n FlipVertically,\r\n FlipHorizontally,\r\n FontSize,\r\n Code,\r\n TextBold,\r\n TextItalic,\r\n TextUnderline,\r\n Strikethrough,\r\n Edit,\r\n Quote,\r\n BackgroundColor,\r\n Group,\r\n Ungroup,\r\n Back,\r\n Next,\r\n Fullwidth,\r\n AlignTop,\r\n AlignLeft,\r\n AlignRight,\r\n AlignBottom,\r\n AlignVertically,\r\n AlignHorizontally,\r\n BringToFront,\r\n SendToBack,\r\n AlignTextLeft,\r\n AlignTextRight,\r\n AlignTextCenter,\r\n RowHeight,\r\n Write,\r\n InsertTable,\r\n AddText,\r\n Fill,\r\n Tailoring,\r\n Effects,\r\n ColorFilter,\r\n Down,\r\n Plus,\r\n Minus,\r\n Connection,\r\n BringToFrontOne,\r\n SentToBack,\r\n Github,\r\n ChartLine,\r\n ChartHistogram,\r\n ChartProportion,\r\n PentagonOne,\r\n Text,\r\n Rotate,\r\n LeftC,\r\n RightC,\r\n Platte,\r\n UpOne,\r\n DownOne,\r\n CloseSmall,\r\n Undo,\r\n Transform,\r\n Click,\r\n Theme,\r\n ArrowCircleLeft,\r\n} from '@icon-park/vue-next'\r\n\r\nexport default {\r\n install(app: App) {\r\n // 插入元素\r\n app.component('IconFontSize', FontSize)\r\n app.component('IconPicture', Picture)\r\n app.component('IconPentagonOne', PentagonOne)\r\n app.component('IconConnection', Connection)\r\n app.component('IconInsertTable', InsertTable)\r\n\r\n // 锁定与解锁\r\n app.component('IconLock', Lock)\r\n app.component('IconUnlock', Unlock)\r\n\r\n // 全屏\r\n app.component('IconFullScreen', FullScreen)\r\n\r\n // 撤销重做\r\n app.component('IconBack', Back)\r\n app.component('IconNext', Next) \r\n \r\n // 对齐\r\n app.component('IconAlignTop', AlignTop)\r\n app.component('IconAlignLeft', AlignLeft)\r\n app.component('IconAlignRight', AlignRight)\r\n app.component('IconAlignBottom', AlignBottom)\r\n app.component('IconAlignVertically', AlignVertically)\r\n app.component('IconAlignHorizontally', AlignHorizontally)\r\n\r\n // 层级\r\n app.component('IconBringToFront', BringToFront)\r\n app.component('IconSentToBack', SentToBack)\r\n app.component('IconBringToFrontOne', BringToFrontOne)\r\n app.component('IconSendToBack', SendToBack)\r\n\r\n // 组合\r\n app.component('IconGroup', Group)\r\n app.component('IconUngroup', Ungroup)\r\n\r\n // 通用元素编辑\r\n app.component('IconFill', Fill)\r\n app.component('IconBackgroundColor', BackgroundColor)\r\n app.component('IconPlatte', Platte)\r\n \r\n // 图片编辑\r\n app.component('IconTailoring', Tailoring)\r\n app.component('IconColorFilter', ColorFilter)\r\n app.component('IconFlipVertically', FlipVertically)\r\n app.component('IconFlipHorizontally', FlipHorizontally)\r\n\r\n // 文字编辑\r\n app.component('IconText', Text)\r\n app.component('IconAddText', AddText)\r\n app.component('IconAlignTextLeft', AlignTextLeft)\r\n app.component('IconAlignTextRight', AlignTextRight)\r\n app.component('IconAlignTextCenter', AlignTextCenter)\r\n app.component('IconRowHeight', RowHeight)\r\n app.component('IconFullwidth', Fullwidth)\r\n app.component('IconCode', Code)\r\n app.component('IconTextBold', TextBold)\r\n app.component('IconTextItalic', TextItalic)\r\n app.component('IconTextUnderline', TextUnderline)\r\n app.component('IconStrikethrough', Strikethrough)\r\n app.component('IconQuote', Quote)\r\n app.component('IconList', List)\r\n app.component('IconOrderedList', OrderedList)\r\n app.component('IconUpOne', UpOne)\r\n app.component('IconDownOne', DownOne)\r\n app.component('IconFormat', Format)\r\n\r\n // 箭头与符号\r\n app.component('IconDown', Down)\r\n app.component('IconLeftC', LeftC)\r\n app.component('IconRightC', RightC)\r\n app.component('IconPlus', Plus)\r\n app.component('IconMinus', Minus)\r\n app.component('IconCloseSmall', CloseSmall)\r\n \r\n // 图表\r\n app.component('IconChartLine', ChartLine)\r\n app.component('IconChartHistogram', ChartHistogram)\r\n app.component('IconChartProportion', ChartProportion)\r\n\r\n // 其他\r\n app.component('IconPlayOne', PlayOne)\r\n app.component('IconSearch', Search)\r\n app.component('IconPpt', Ppt)\r\n app.component('IconHelpcenter', Helpcenter)\r\n app.component('IconGithub', Github)\r\n app.component('IconWrite', Write)\r\n app.component('IconEffects', Effects)\r\n app.component('IconRotate', Rotate)\r\n app.component('IconEdit', Edit)\r\n app.component('IconUndo', Undo)\r\n app.component('IconTransform', Transform)\r\n app.component('IconClick', Click)\r\n app.component('IconTheme', Theme)\r\n app.component('IconArrowCircleLeft', ArrowCircleLeft)\r\n }\r\n}","<template>\r\n <div class=\"file-input\" @click=\"handleClick()\">\r\n <slot></slot>\r\n <input \r\n class=\"input\"\r\n type=\"file\" \r\n name=\"upload\" \r\n ref=\"inputRef\" \r\n :accept=\"accept\" \r\n @change=\"$event => handleChange($event)\"\r\n >\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, ref } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'file-input',\r\n props: {\r\n accept: {\r\n type: String,\r\n default: 'image/*',\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const inputRef = ref<HTMLInputElement>()\r\n\r\n const handleClick = () => {\r\n if (!inputRef.value) return\r\n inputRef.value.value = ''\r\n inputRef.value.click()\r\n }\r\n const handleChange = (e: InputEvent) => {\r\n const files = (e.target as HTMLInputElement).files\r\n if (files) emit('change', files)\r\n }\r\n\r\n return {\r\n handleClick,\r\n handleChange,\r\n inputRef,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.input {\r\n display: none;\r\n}\r\n</style>","\r\nimport { defineComponent, ref } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'file-input',\r\n props: {\r\n accept: {\r\n type: String,\r\n default: 'image/*',\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const inputRef = ref<HTMLInputElement>()\r\n\r\n const handleClick = () => {\r\n if (!inputRef.value) return\r\n inputRef.value.value = ''\r\n inputRef.value.click()\r\n }\r\n const handleChange = (e: InputEvent) => {\r\n const files = (e.target as HTMLInputElement).files\r\n if (files) emit('change', files)\r\n }\r\n\r\n return {\r\n handleClick,\r\n handleChange,\r\n inputRef,\r\n }\r\n },\r\n})\r\n","import { render } from \"./FileInput.vue?vue&type=template&id=bf80565c&scoped=true\"\nimport script from \"./FileInput.vue?vue&type=script&lang=ts\"\nexport * from \"./FileInput.vue?vue&type=script&lang=ts\"\n\nimport \"./FileInput.vue?vue&type=style&index=0&id=bf80565c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-bf80565c\"\n\nexport default script","<template>\r\n <svg \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n xmlnsXlink=\"http://www.w3.org/1999/xlink\" \r\n version=\"1.1\"\r\n >\r\n <slot></slot>\r\n </svg>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'svg-wrapper',\r\n}\r\n</script>","\r\nexport default {\r\n name: 'svg-wrapper',\r\n}\r\n","import { render } from \"./SvgWrapper.vue?vue&type=template&id=07215504\"\nimport script from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nexport * from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","<template>\r\n <button class=\"checkbox-button\" :class=\"{ 'checked': checked }\">\r\n <slot></slot>\r\n </button>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'checkbox-button',\r\n props: {\r\n checked: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.checkbox-button {\r\n outline: 0;\r\n background-color: #fff;\r\n border: 1px solid #d9d9d9;\r\n font-size: 13px;\r\n padding: 0 15px;\r\n height: 32px;\r\n text-align: center;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n color: $themeColor;\r\n }\r\n\r\n &.checked {\r\n color: #fff;\r\n background-color: $themeColor;\r\n border-color: $themeColor;\r\n\r\n &:hover {\r\n background: rgba($color: $themeColor, $alpha: .9);\r\n border-color: rgba($color: $themeColor, $alpha: .9);\r\n }\r\n }\r\n}\r\n</style>","\r\nexport default {\r\n name: 'checkbox-button',\r\n props: {\r\n checked: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n","import { render } from \"./CheckboxButton.vue?vue&type=template&id=7cae2b90&scoped=true\"\nimport script from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButton.vue?vue&type=style&index=0&id=7cae2b90&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7cae2b90\"\n\nexport default script","<template>\r\n <div class=\"checkbox-button-group\">\r\n <slot></slot>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'checkbox-button-group',\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.checkbox-button-group {\r\n display: flex;\r\n align-items: center;\r\n\r\n ::v-deep(.checkbox-button) {\r\n border-radius: 0;\r\n border-left-width: 0;\r\n border-right-width: 0;\r\n display: inline-block;\r\n\r\n & + .checkbox-button {\r\n border-left-width: 1px;\r\n }\r\n\r\n &:first-child {\r\n border-top-left-radius: $borderRadius;\r\n border-bottom-left-radius: $borderRadius;\r\n border-left-width: 1px;\r\n }\r\n\r\n &:last-child {\r\n border-top-right-radius: $borderRadius;\r\n border-bottom-right-radius: $borderRadius;\r\n border-right-width: 1px;\r\n }\r\n }\r\n}\r\n</style>","\r\nexport default {\r\n name: 'checkbox-button-group',\r\n}\r\n","import { render } from \"./CheckboxButtonGroup.vue?vue&type=template&id=7dafd0a9&scoped=true\"\nimport script from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButtonGroup.vue?vue&type=style&index=0&id=7dafd0a9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7dafd0a9\"\n\nexport default script","<template>\r\n <div class=\"color-picker\">\r\n <div class=\"picker-saturation-wrap\">\r\n <Saturation :value=\"color\" :hue=\"hue\" @colorChange=\"value => changeColor(value)\" />\r\n </div>\r\n <div class=\"picker-controls\">\r\n <div class=\"picker-color-wrap\">\r\n <div class=\"picker-current-color\" :style=\"{ background: currentColor }\"></div>\r\n <Checkboard />\r\n </div>\r\n <div class=\"picker-sliders\">\r\n <div class=\"picker-hue-wrap\">\r\n <Hue :value=\"color\" :hue=\"hue\" @colorChange=\"value => changeColor(value)\" />\r\n </div>\r\n <div class=\"picker-alpha-wrap\">\r\n <Alpha :value=\"color\" @colorChange=\"value => changeColor(value)\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"picker-field\">\r\n <EditableInput :value=\"color\" @colorChange=\"value => changeColor(value)\" />\r\n </div>\r\n\r\n <div class=\"picker-presets\">\r\n <div\r\n class=\"picker-presets-color\"\r\n v-for=\"c in themeColors\"\r\n :key=\"c\"\r\n :style=\"{background: c}\"\r\n @click=\"selectPresetColor(c)\"\r\n ></div>\r\n </div>\r\n\r\n <div class=\"picker-gradient-presets\">\r\n <div\r\n class=\"picker-gradient-col\"\r\n v-for=\"(col, index) in presetColors\"\r\n :key=\"index\"\r\n >\r\n <div class=\"picker-gradient-color\"\r\n v-for=\"c in col\"\r\n :key=\"c\"\r\n :style=\"{background: c}\"\r\n @click=\"selectPresetColor(c)\"\r\n ></div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"picker-presets\">\r\n <div\r\n v-for=\"c in standardColors\"\r\n :key=\"c\"\r\n class=\"picker-presets-color\"\r\n :style=\"{ background: c }\"\r\n @click=\"selectPresetColor(c)\"\r\n ></div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nimport Alpha from './Alpha.vue'\r\nimport Checkboard from './Checkboard.vue'\r\nimport Hue from './Hue.vue'\r\nimport Saturation from './Saturation.vue'\r\nimport EditableInput from './EditableInput.vue'\r\n\r\nconst presetColorConfig = [\r\n ['#7f7f7f', '#f2f2f2'],\r\n ['#0d0d0d', '#808080'],\r\n ['#1c1a10', '#ddd8c3'],\r\n ['#0e243d', '#c6d9f0'],\r\n ['#233f5e', '#dae5f0'],\r\n ['#632623', '#f2dbdb'],\r\n ['#4d602c', '#eaf1de'],\r\n ['#3f3150', '#e6e0ec'],\r\n ['#1e5867', '#d9eef3'],\r\n ['#99490f', '#fee9da'],\r\n]\r\n\r\nconst gradient = (startColor: string, endColor: string, step: number) => {\r\n const _startColor = tinycolor(startColor).toRgb()\r\n const _endColor = tinycolor(endColor).toRgb()\r\n\r\n const rStep = (_endColor.r - _startColor.r) / step\r\n const gStep = (_endColor.g - _startColor.g) / step\r\n const bStep = (_endColor.b - _startColor.b) / step\r\n const gradientColorArr = []\r\n\r\n for (let i = 0; i < step; i++) {\r\n const gradientColor = tinycolor({\r\n r: _startColor.r + rStep * i,\r\n g: _startColor.g + gStep * i,\r\n b: _startColor.b + bStep * i,\r\n }).toRgbString()\r\n gradientColorArr.push(gradientColor)\r\n }\r\n return gradientColorArr\r\n}\r\n\r\nconst getPresetColors = () => {\r\n const presetColors = []\r\n for (const color of presetColorConfig) {\r\n presetColors.push(gradient(color[1], color[0], 5))\r\n }\r\n return presetColors\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'color-picker',\r\n components: {\r\n Alpha,\r\n Checkboard,\r\n Hue,\r\n Saturation,\r\n EditableInput,\r\n },\r\n props: {\r\n modelValue: {\r\n type: String,\r\n default: '#e86b99',\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const hue = ref(0)\r\n\r\n const color = computed({\r\n get() {\r\n return tinycolor(props.modelValue).toRgb()\r\n },\r\n set(rgba: ColorFormats.RGBA) {\r\n const rgbaString = `rgba(${[rgba.r, rgba.g, rgba.b, rgba.a].join(',')})`\r\n emit('update:modelValue', rgbaString)\r\n },\r\n })\r\n\r\n const themeColors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\r\n const standardColors = ['#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57', '#00afee', '#0071be', '#00215f', '#72349d']\r\n const presetColors = getPresetColors()\r\n\r\n const currentColor = computed(() => {\r\n return `rgba(${[color.value.r, color.value.g, color.value.b, color.value.a].join(',')})`\r\n })\r\n\r\n const selectPresetColor = (colorString: string) => {\r\n emit('update:modelValue', colorString)\r\n }\r\n\r\n const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {\r\n if ('h' in value) {\r\n hue.value = value.h\r\n color.value = tinycolor(value).toRgb()\r\n }\r\n else color.value = value\r\n }\r\n\r\n return {\r\n themeColors,\r\n standardColors,\r\n presetColors,\r\n color,\r\n hue,\r\n currentColor,\r\n changeColor,\r\n selectPresetColor,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.color-picker {\r\n position: relative;\r\n width: 240px;\r\n background: #fff;\r\n user-select: none;\r\n margin-bottom: -10px;\r\n}\r\n.picker-saturation-wrap {\r\n width: 100%;\r\n padding-bottom: 50%;\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n.picker-controls {\r\n display: flex;\r\n}\r\n.picker-sliders {\r\n padding: 4px 0;\r\n flex: 1;\r\n}\r\n.picker-hue-wrap {\r\n position: relative;\r\n height: 10px;\r\n}\r\n.picker-alpha-wrap {\r\n position: relative;\r\n height: 10px;\r\n margin-top: 4px;\r\n overflow: hidden;\r\n}\r\n.picker-color-wrap {\r\n width: 24px;\r\n height: 24px;\r\n position: relative;\r\n margin-top: 4px;\r\n margin-right: 4px;\r\n outline: 1px dashed rgba($color: #666, $alpha: .12);\r\n\r\n .checkerboard {\r\n background-size: auto;\r\n }\r\n}\r\n.picker-current-color {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 2;\r\n}\r\n\r\n.picker-field {\r\n margin-bottom: 8px;\r\n}\r\n\r\n.picker-presets {\r\n @include flex-grid-layout();\r\n}\r\n.picker-presets-color {\r\n @include flex-grid-layout-children(10, 7%);\r\n\r\n height: 0;\r\n padding-bottom: 7%;\r\n flex-shrink: 0;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n.picker-gradient-presets {\r\n @include flex-grid-layout();\r\n}\r\n.picker-gradient-col {\r\n @include flex-grid-layout-children(10, 7%);\r\n\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n.picker-gradient-color {\r\n width: 100%;\r\n height: 0;\r\n padding-bottom: 100%;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n</style>","<template>\r\n <div class=\"alpha\">\r\n <div class=\"alpha-checkboard-wrap\">\r\n <Checkboard />\r\n </div>\r\n <div class=\"alpha-gradient\" :style=\"{ background: gradientColor }\"></div>\r\n <div \r\n class=\"alpha-container\" \r\n ref=\"alphaRef\"\r\n @mousedown=\"$event => handleMouseDown($event)\"\r\n >\r\n <div class=\"alpha-pointer\" :style=\"{ left: color.a * 100 + '%' }\">\r\n <div class=\"alpha-picker\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\r\n\r\nimport Checkboard from './Checkboard.vue'\r\nimport { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'alpha',\r\n components: {\r\n Checkboard,\r\n },\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const color = computed(() => props.value)\r\n \r\n const gradientColor = computed(() => {\r\n const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')\r\n return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`\r\n })\r\n\r\n const alphaRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!alphaRef.value) return\r\n const containerWidth = alphaRef.value.clientWidth\r\n const xOffset = alphaRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const left = e.pageX - xOffset\r\n let a\r\n\r\n if (left < 0) a = 0\r\n else if (left > containerWidth) a = 1\r\n else a = Math.round(left * 100 / containerWidth) / 100\r\n\r\n if (color.value.a !== a) {\r\n emit('colorChange', {\r\n r: color.value.r,\r\n g: color.value.g,\r\n b: color.value.b,\r\n a: a,\r\n })\r\n }\r\n }\r\n\r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n alphaRef,\r\n gradientColor,\r\n handleMouseDown,\r\n color,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.alpha {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n}\r\n.alpha-checkboard-wrap {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n overflow: hidden;\r\n}\r\n.alpha-gradient {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n}\r\n.alpha-container {\r\n cursor: pointer;\r\n position: relative;\r\n z-index: 2;\r\n height: 100%;\r\n margin: 0 3px;\r\n}\r\n.alpha-pointer {\r\n z-index: 2;\r\n position: absolute;\r\n}\r\n.alpha-picker {\r\n cursor: pointer;\r\n width: 4px;\r\n height: 8px;\r\n box-shadow: 0 0 2px rgba(0, 0, 0, .6);\r\n background: #fff;\r\n margin-top: 1px;\r\n transform: translateX(-2px);\r\n}\r\n</style>","<template>\r\n <div class=\"checkerboard\" :style=\"bgStyle\"></div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent } from 'vue'\r\n\r\nconst checkboardCache = {}\r\n\r\nconst renderCheckboard = (white: string, grey: string, size: number) => {\r\n const canvas = document.createElement('canvas')\r\n canvas.width = canvas.height = size * 2\r\n const ctx = canvas.getContext('2d')\r\n \r\n if (!ctx) return null\r\n\r\n ctx.fillStyle = white\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.fillStyle = grey\r\n ctx.fillRect(0, 0, size, size)\r\n ctx.translate(size, size)\r\n ctx.fillRect(0, 0, size, size)\r\n return canvas.toDataURL()\r\n}\r\n\r\nconst getCheckboard = (white: string, grey: string, size: number) => {\r\n const key = white + ',' + grey + ',' + size\r\n if (checkboardCache[key]) return checkboardCache[key]\r\n \r\n const checkboard = renderCheckboard(white, grey, size)\r\n checkboardCache[key] = checkboard\r\n return checkboard\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'checkboard',\r\n props: {\r\n size: {\r\n type: Number,\r\n default: 8,\r\n },\r\n white: {\r\n type: String,\r\n default: '#fff',\r\n },\r\n grey: {\r\n type: String,\r\n default: '#e6e6e6',\r\n },\r\n },\r\n setup(props) {\r\n const bgStyle = computed(() => {\r\n const checkboard = getCheckboard(props.white, props.grey, props.size)\r\n return { backgroundImage: `url(${checkboard})` }\r\n })\r\n\r\n return {\r\n bgStyle,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.checkerboard {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n background-size: contain;\r\n}\r\n</style>","\r\nimport { computed, defineComponent } from 'vue'\r\n\r\nconst checkboardCache = {}\r\n\r\nconst renderCheckboard = (white: string, grey: string, size: number) => {\r\n const canvas = document.createElement('canvas')\r\n canvas.width = canvas.height = size * 2\r\n const ctx = canvas.getContext('2d')\r\n \r\n if (!ctx) return null\r\n\r\n ctx.fillStyle = white\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.fillStyle = grey\r\n ctx.fillRect(0, 0, size, size)\r\n ctx.translate(size, size)\r\n ctx.fillRect(0, 0, size, size)\r\n return canvas.toDataURL()\r\n}\r\n\r\nconst getCheckboard = (white: string, grey: string, size: number) => {\r\n const key = white + ',' + grey + ',' + size\r\n if (checkboardCache[key]) return checkboardCache[key]\r\n \r\n const checkboard = renderCheckboard(white, grey, size)\r\n checkboardCache[key] = checkboard\r\n return checkboard\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'checkboard',\r\n props: {\r\n size: {\r\n type: Number,\r\n default: 8,\r\n },\r\n white: {\r\n type: String,\r\n default: '#fff',\r\n },\r\n grey: {\r\n type: String,\r\n default: '#e6e6e6',\r\n },\r\n },\r\n setup(props) {\r\n const bgStyle = computed(() => {\r\n const checkboard = getCheckboard(props.white, props.grey, props.size)\r\n return { backgroundImage: `url(${checkboard})` }\r\n })\r\n\r\n return {\r\n bgStyle,\r\n }\r\n },\r\n})\r\n","import { render } from \"./Checkboard.vue?vue&type=template&id=e9a0ac98&scoped=true\"\nimport script from \"./Checkboard.vue?vue&type=script&lang=ts\"\nexport * from \"./Checkboard.vue?vue&type=script&lang=ts\"\n\nimport \"./Checkboard.vue?vue&type=style&index=0&id=e9a0ac98&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-e9a0ac98\"\n\nexport default script","\r\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\r\n\r\nimport Checkboard from './Checkboard.vue'\r\nimport { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'alpha',\r\n components: {\r\n Checkboard,\r\n },\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const color = computed(() => props.value)\r\n \r\n const gradientColor = computed(() => {\r\n const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')\r\n return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`\r\n })\r\n\r\n const alphaRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!alphaRef.value) return\r\n const containerWidth = alphaRef.value.clientWidth\r\n const xOffset = alphaRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const left = e.pageX - xOffset\r\n let a\r\n\r\n if (left < 0) a = 0\r\n else if (left > containerWidth) a = 1\r\n else a = Math.round(left * 100 / containerWidth) / 100\r\n\r\n if (color.value.a !== a) {\r\n emit('colorChange', {\r\n r: color.value.r,\r\n g: color.value.g,\r\n b: color.value.b,\r\n a: a,\r\n })\r\n }\r\n }\r\n\r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n alphaRef,\r\n gradientColor,\r\n handleMouseDown,\r\n color,\r\n }\r\n },\r\n})\r\n","import { render } from \"./Alpha.vue?vue&type=template&id=ecf7d10e&scoped=true\"\nimport script from \"./Alpha.vue?vue&type=script&lang=ts\"\nexport * from \"./Alpha.vue?vue&type=script&lang=ts\"\n\nimport \"./Alpha.vue?vue&type=style&index=0&id=ecf7d10e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-ecf7d10e\"\n\nexport default script","<template>\r\n <div class=\"hue\">\r\n <div \r\n class=\"hue-container\"\r\n ref=\"hueRef\"\r\n @mousedown=\"$event => handleMouseDown($event)\"\r\n >\r\n <div \r\n class=\"hue-pointer\"\r\n :style=\"{ left: pointerLeft }\"\r\n >\r\n <div class=\"hue-picker\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'hue',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n hue: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const oldHue = ref(0)\r\n const pullDirection = ref('')\r\n \r\n const color = computed(() => {\r\n const hsla = tinycolor(props.value).toHsl()\r\n if (hsla.s === 0) hsla.h = props.hue\r\n return hsla\r\n })\r\n\r\n const pointerLeft = computed(() => {\r\n if (color.value.h === 0 && pullDirection.value === 'right') return '100%'\r\n return color.value.h * 100 / 360 + '%'\r\n })\r\n\r\n watch(() => props.value, () => {\r\n const hsla = tinycolor(props.value).toHsl()\r\n const h = hsla.s === 0 ? props.hue : hsla.h\r\n if (h !== 0 && h - oldHue.value > 0) pullDirection.value = 'right'\r\n if (h !== 0 && h - oldHue.value < 0) pullDirection.value = 'left'\r\n oldHue.value = h\r\n })\r\n\r\n const hueRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!hueRef.value) return\r\n\r\n const containerWidth = hueRef.value.clientWidth\r\n const xOffset = hueRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const left = e.pageX - xOffset\r\n let h, percent\r\n \r\n if (left < 0) h = 0\r\n else if (left > containerWidth) h = 360\r\n else {\r\n percent = left * 100 / containerWidth\r\n h = (360 * percent / 100)\r\n }\r\n if (color.value.h !== h) {\r\n emit('colorChange', {\r\n h,\r\n l: color.value.l,\r\n s: color.value.s,\r\n a: color.value.a,\r\n })\r\n }\r\n }\r\n\r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n hueRef,\r\n handleMouseDown,\r\n pointerLeft,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.hue {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);\r\n}\r\n.hue-container {\r\n cursor: pointer;\r\n margin: 0 2px;\r\n position: relative;\r\n height: 100%;\r\n}\r\n.hue-pointer {\r\n z-index: 2;\r\n position: absolute;\r\n top: 0;\r\n}\r\n.hue-picker {\r\n cursor: pointer;\r\n margin-top: 1px;\r\n width: 4px;\r\n height: 8px;\r\n box-shadow: 0 0 2px rgba(0, 0, 0, .6);\r\n background: #fff;\r\n transform: translateX(-2px);\r\n}\r\n</style>","\r\nimport { computed, defineComponent, onUnmounted, PropType, ref, watch } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'hue',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n hue: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const oldHue = ref(0)\r\n const pullDirection = ref('')\r\n \r\n const color = computed(() => {\r\n const hsla = tinycolor(props.value).toHsl()\r\n if (hsla.s === 0) hsla.h = props.hue\r\n return hsla\r\n })\r\n\r\n const pointerLeft = computed(() => {\r\n if (color.value.h === 0 && pullDirection.value === 'right') return '100%'\r\n return color.value.h * 100 / 360 + '%'\r\n })\r\n\r\n watch(() => props.value, () => {\r\n const hsla = tinycolor(props.value).toHsl()\r\n const h = hsla.s === 0 ? props.hue : hsla.h\r\n if (h !== 0 && h - oldHue.value > 0) pullDirection.value = 'right'\r\n if (h !== 0 && h - oldHue.value < 0) pullDirection.value = 'left'\r\n oldHue.value = h\r\n })\r\n\r\n const hueRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!hueRef.value) return\r\n\r\n const containerWidth = hueRef.value.clientWidth\r\n const xOffset = hueRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const left = e.pageX - xOffset\r\n let h, percent\r\n \r\n if (left < 0) h = 0\r\n else if (left > containerWidth) h = 360\r\n else {\r\n percent = left * 100 / containerWidth\r\n h = (360 * percent / 100)\r\n }\r\n if (color.value.h !== h) {\r\n emit('colorChange', {\r\n h,\r\n l: color.value.l,\r\n s: color.value.s,\r\n a: color.value.a,\r\n })\r\n }\r\n }\r\n\r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n hueRef,\r\n handleMouseDown,\r\n pointerLeft,\r\n }\r\n },\r\n})\r\n","import { render } from \"./Hue.vue?vue&type=template&id=7b983451&scoped=true\"\nimport script from \"./Hue.vue?vue&type=script&lang=ts\"\nexport * from \"./Hue.vue?vue&type=script&lang=ts\"\n\nimport \"./Hue.vue?vue&type=style&index=0&id=7b983451&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7b983451\"\n\nexport default script","<template>\r\n <div \r\n class=\"saturation\"\r\n ref=\"saturationRef\"\r\n :style=\"{ background: bgColor }\"\r\n @mousedown=\"$event => handleMouseDown($event)\"\r\n >\r\n <div class=\"saturation-white\"></div>\r\n <div class=\"saturation-black\"></div>\r\n <div class=\"saturation-pointer\" \r\n :style=\"{\r\n top: pointerTop,\r\n left: pointerLeft,\r\n }\"\r\n >\r\n <div class=\"saturation-circle\"></div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\nimport throttle from 'lodash/throttle'\r\nimport clamp from 'lodash/clamp'\r\n\r\nexport default defineComponent({\r\n name: 'saturation',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n hue: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const color = computed(() => {\r\n const hsva = tinycolor(props.value).toHsv()\r\n if (hsva.s === 0) hsva.h = props.hue\r\n return hsva\r\n })\r\n\r\n const bgColor = computed(() => `hsl(${color.value.h}, 100%, 50%)`)\r\n const pointerTop = computed(() => (-(color.value.v * 100) + 1) + 100 + '%')\r\n const pointerLeft = computed(() => color.value.s * 100 + '%')\r\n\r\n const emitChangeEvent = throttle(function(param) {\r\n emit('colorChange', param)\r\n }, 20, { leading: true, trailing: false })\r\n\r\n const saturationRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!saturationRef.value) return\r\n \r\n const containerWidth = saturationRef.value.clientWidth\r\n const containerHeight = saturationRef.value.clientHeight\r\n const xOffset = saturationRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const yOffset = saturationRef.value.getBoundingClientRect().top + window.pageYOffset\r\n const left = clamp(e.pageX - xOffset, 0, containerWidth)\r\n const top = clamp(e.pageY - yOffset, 0, containerHeight)\r\n const saturation = left / containerWidth\r\n const bright = clamp(-(top / containerHeight) + 1, 0, 1)\r\n\r\n emitChangeEvent({\r\n h: color.value.h,\r\n s: saturation,\r\n v: bright,\r\n a: color.value.a,\r\n })\r\n }\r\n\r\n \r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n saturationRef,\r\n bgColor,\r\n handleMouseDown,\r\n pointerTop,\r\n pointerLeft,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.saturation,\r\n.saturation-white,\r\n.saturation-black {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n cursor: pointer;\r\n}\r\n.saturation-white {\r\n background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));\r\n}\r\n.saturation-black {\r\n background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));\r\n}\r\n.saturation-pointer {\r\n cursor: pointer;\r\n position: absolute;\r\n}\r\n.saturation-circle {\r\n width: 4px;\r\n height: 4px;\r\n box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0, 0, 0, .3), 0 0 1px 2px rgba(0, 0, 0, .4);\r\n border-radius: 50%;\r\n transform: translate(-2px, -2px);\r\n}\r\n</style>","\r\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\nimport throttle from 'lodash/throttle'\r\nimport clamp from 'lodash/clamp'\r\n\r\nexport default defineComponent({\r\n name: 'saturation',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n hue: {\r\n type: Number,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const color = computed(() => {\r\n const hsva = tinycolor(props.value).toHsv()\r\n if (hsva.s === 0) hsva.h = props.hue\r\n return hsva\r\n })\r\n\r\n const bgColor = computed(() => `hsl(${color.value.h}, 100%, 50%)`)\r\n const pointerTop = computed(() => (-(color.value.v * 100) + 1) + 100 + '%')\r\n const pointerLeft = computed(() => color.value.s * 100 + '%')\r\n\r\n const emitChangeEvent = throttle(function(param) {\r\n emit('colorChange', param)\r\n }, 20, { leading: true, trailing: false })\r\n\r\n const saturationRef = ref<HTMLElement>()\r\n const handleChange = (e: MouseEvent) => {\r\n e.preventDefault()\r\n if (!saturationRef.value) return\r\n \r\n const containerWidth = saturationRef.value.clientWidth\r\n const containerHeight = saturationRef.value.clientHeight\r\n const xOffset = saturationRef.value.getBoundingClientRect().left + window.pageXOffset\r\n const yOffset = saturationRef.value.getBoundingClientRect().top + window.pageYOffset\r\n const left = clamp(e.pageX - xOffset, 0, containerWidth)\r\n const top = clamp(e.pageY - yOffset, 0, containerHeight)\r\n const saturation = left / containerWidth\r\n const bright = clamp(-(top / containerHeight) + 1, 0, 1)\r\n\r\n emitChangeEvent({\r\n h: color.value.h,\r\n s: saturation,\r\n v: bright,\r\n a: color.value.a,\r\n })\r\n }\r\n\r\n \r\n const unbindEventListeners = () => {\r\n window.removeEventListener('mousemove', handleChange)\r\n window.removeEventListener('mouseup', unbindEventListeners)\r\n }\r\n const handleMouseDown = (e: MouseEvent) => {\r\n handleChange(e)\r\n window.addEventListener('mousemove', handleChange)\r\n window.addEventListener('mouseup', unbindEventListeners)\r\n }\r\n\r\n onUnmounted(unbindEventListeners)\r\n\r\n return {\r\n saturationRef,\r\n bgColor,\r\n handleMouseDown,\r\n pointerTop,\r\n pointerLeft,\r\n }\r\n },\r\n})\r\n","import { render } from \"./Saturation.vue?vue&type=template&id=5310dbb4&scoped=true\"\nimport script from \"./Saturation.vue?vue&type=script&lang=ts\"\nexport * from \"./Saturation.vue?vue&type=script&lang=ts\"\n\nimport \"./Saturation.vue?vue&type=style&index=0&id=5310dbb4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5310dbb4\"\n\nexport default script","<template>\r\n <div class=\"editable-input\">\r\n <input\r\n class=\"input-content\"\r\n :value=\"val\"\r\n @input=\"$event => handleInput($event)\"\r\n >\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'editable-input',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const val = computed(() => {\r\n let _hex = ''\r\n if (props.value.a < 1) _hex = tinycolor(props.value).toHex8String().toUpperCase()\r\n else _hex = tinycolor(props.value).toHexString().toUpperCase()\r\n return _hex.replace('#', '')\r\n })\r\n\r\n const handleInput = (e: InputEvent) => {\r\n const value = (e.target as HTMLInputElement).value\r\n if (value.length >= 6) emit('colorChange', tinycolor(value).toRgb())\r\n }\r\n\r\n return {\r\n val,\r\n handleInput,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.editable-input {\r\n width: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n text-align: center;\r\n font-size: 14px;\r\n}\r\n.input-content {\r\n width: 100%;\r\n padding: 3px;\r\n border: 0;\r\n border-bottom: 1px solid #ddd;\r\n outline: none;\r\n text-align: center;\r\n}\r\n.input-label {\r\n text-transform: capitalize;\r\n}\r\n</style>\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nexport default defineComponent({\r\n name: 'editable-input',\r\n props: {\r\n value: {\r\n type: Object as PropType<ColorFormats.RGBA>,\r\n required: true,\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const val = computed(() => {\r\n let _hex = ''\r\n if (props.value.a < 1) _hex = tinycolor(props.value).toHex8String().toUpperCase()\r\n else _hex = tinycolor(props.value).toHexString().toUpperCase()\r\n return _hex.replace('#', '')\r\n })\r\n\r\n const handleInput = (e: InputEvent) => {\r\n const value = (e.target as HTMLInputElement).value\r\n if (value.length >= 6) emit('colorChange', tinycolor(value).toRgb())\r\n }\r\n\r\n return {\r\n val,\r\n handleInput,\r\n }\r\n },\r\n})\r\n","import { render } from \"./EditableInput.vue?vue&type=template&id=0311fdee&scoped=true\"\nimport script from \"./EditableInput.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableInput.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableInput.vue?vue&type=style&index=0&id=0311fdee&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0311fdee\"\n\nexport default script","\r\nimport { computed, defineComponent, ref } from 'vue'\r\nimport tinycolor, { ColorFormats } from 'tinycolor2'\r\n\r\nimport Alpha from './Alpha.vue'\r\nimport Checkboard from './Checkboard.vue'\r\nimport Hue from './Hue.vue'\r\nimport Saturation from './Saturation.vue'\r\nimport EditableInput from './EditableInput.vue'\r\n\r\nconst presetColorConfig = [\r\n ['#7f7f7f', '#f2f2f2'],\r\n ['#0d0d0d', '#808080'],\r\n ['#1c1a10', '#ddd8c3'],\r\n ['#0e243d', '#c6d9f0'],\r\n ['#233f5e', '#dae5f0'],\r\n ['#632623', '#f2dbdb'],\r\n ['#4d602c', '#eaf1de'],\r\n ['#3f3150', '#e6e0ec'],\r\n ['#1e5867', '#d9eef3'],\r\n ['#99490f', '#fee9da'],\r\n]\r\n\r\nconst gradient = (startColor: string, endColor: string, step: number) => {\r\n const _startColor = tinycolor(startColor).toRgb()\r\n const _endColor = tinycolor(endColor).toRgb()\r\n\r\n const rStep = (_endColor.r - _startColor.r) / step\r\n const gStep = (_endColor.g - _startColor.g) / step\r\n const bStep = (_endColor.b - _startColor.b) / step\r\n const gradientColorArr = []\r\n\r\n for (let i = 0; i < step; i++) {\r\n const gradientColor = tinycolor({\r\n r: _startColor.r + rStep * i,\r\n g: _startColor.g + gStep * i,\r\n b: _startColor.b + bStep * i,\r\n }).toRgbString()\r\n gradientColorArr.push(gradientColor)\r\n }\r\n return gradientColorArr\r\n}\r\n\r\nconst getPresetColors = () => {\r\n const presetColors = []\r\n for (const color of presetColorConfig) {\r\n presetColors.push(gradient(color[1], color[0], 5))\r\n }\r\n return presetColors\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'color-picker',\r\n components: {\r\n Alpha,\r\n Checkboard,\r\n Hue,\r\n Saturation,\r\n EditableInput,\r\n },\r\n props: {\r\n modelValue: {\r\n type: String,\r\n default: '#e86b99',\r\n },\r\n },\r\n setup(props, { emit }) {\r\n const hue = ref(0)\r\n\r\n const color = computed({\r\n get() {\r\n return tinycolor(props.modelValue).toRgb()\r\n },\r\n set(rgba: ColorFormats.RGBA) {\r\n const rgbaString = `rgba(${[rgba.r, rgba.g, rgba.b, rgba.a].join(',')})`\r\n emit('update:modelValue', rgbaString)\r\n },\r\n })\r\n\r\n const themeColors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\r\n const standardColors = ['#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57', '#00afee', '#0071be', '#00215f', '#72349d']\r\n const presetColors = getPresetColors()\r\n\r\n const currentColor = computed(() => {\r\n return `rgba(${[color.value.r, color.value.g, color.value.b, color.value.a].join(',')})`\r\n })\r\n\r\n const selectPresetColor = (colorString: string) => {\r\n emit('update:modelValue', colorString)\r\n }\r\n\r\n const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {\r\n if ('h' in value) {\r\n hue.value = value.h\r\n color.value = tinycolor(value).toRgb()\r\n }\r\n else color.value = value\r\n }\r\n\r\n return {\r\n themeColors,\r\n standardColors,\r\n presetColors,\r\n color,\r\n hue,\r\n currentColor,\r\n changeColor,\r\n selectPresetColor,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=44b23aae&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=44b23aae&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-44b23aae\"\n\nexport default script","import { createApp } from 'vue'\r\nimport App from './App.vue'\r\nimport { store, key } from './store'\r\n\r\nimport '@icon-park/vue-next/styles/index.css'\r\nimport 'prosemirror-view/style/prosemirror.css'\r\nimport '@/assets/styles/prosemirror.scss'\r\nimport '@/assets/styles/global.scss'\r\nimport '@/assets/styles/antd.scss'\r\nimport '@/assets/styles/font.scss'\r\nimport 'animate.css'\r\n\r\n// 自定义插件\r\nimport Contextmenu from './plugins/contextmenu'\r\nimport ClickOutside from './plugins/clickOutside'\r\nimport IconPark from './plugins/iconPark'\r\n\r\n// 自定义组件\r\nimport FileInput from '@/components/FileInput.vue'\r\nimport SvgWrapper from '@/components/SvgWrapper.vue'\r\nimport CheckboxButton from '@/components/CheckboxButton.vue'\r\nimport CheckboxButtonGroup from '@/components/CheckboxButtonGroup.vue'\r\nimport ColorPicker from '@/components/ColorPicker/index.vue'\r\n\r\n// antd 组件\r\nimport {\r\n InputNumber,\r\n Divider,\r\n Button,\r\n Tooltip,\r\n Popover,\r\n Slider,\r\n Select,\r\n Switch,\r\n Radio,\r\n Input,\r\n Modal,\r\n Dropdown,\r\n Menu,\r\n Checkbox,\r\n Drawer,\r\n} from 'ant-design-vue'\r\n\r\nconst app = createApp(App)\r\n\r\napp.directive('contextmenu', Contextmenu)\r\napp.directive('click-outside', ClickOutside)\r\napp.use(IconPark)\r\n\r\napp.component('FileInput', FileInput)\r\napp.component('SvgWrapper', SvgWrapper)\r\napp.component('CheckboxButton', CheckboxButton)\r\napp.component('CheckboxButtonGroup', CheckboxButtonGroup)\r\napp.component('ColorPicker', ColorPicker)\r\n\r\napp.component('InputNumber', InputNumber)\r\napp.component('Divider', Divider)\r\napp.component('Button', Button)\r\napp.component('ButtonGroup', Button.Group)\r\napp.component('Tooltip', Tooltip)\r\napp.component('Popover', Popover)\r\napp.component('Slider', Slider)\r\napp.component('Select', Select)\r\napp.component('SelectOption', Select.Option)\r\napp.component('SelectOptGroup', Select.OptGroup)\r\napp.component('Switch', Switch)\r\napp.component('Radio', Radio)\r\napp.component('RadioGroup', Radio.Group)\r\napp.component('RadioButton', Radio.Button)\r\napp.component('Input', Input)\r\napp.component('InputGroup', Input.Group)\r\napp.component('Modal', Modal)\r\napp.component('Dropdown', Dropdown)\r\napp.component('Menu', Menu)\r\napp.component('MenuItem', Menu.Item)\r\napp.component('Checkbox', Checkbox)\r\napp.component('Drawer', Drawer)\r\n\r\napp.use(store, key)\r\napp.mount('#app')\r\n","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ChartPool.vue?vue&type=style&index=0&id=58ced0dd&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementOutline.vue?vue&type=style&index=0&id=2ddaa919&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MultiSelectOperate.vue?vue&type=style&index=0&id=4def6455&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=44b23aae&lang=scss&scoped=true\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./FileInput.vue?vue&type=style&index=0&id=bf80565c&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./EditableTable.vue?vue&type=style&index=0&id=ae1d6576&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Chart.vue?vue&type=style&index=0&id=561c26d2&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./HotkeyDoc.vue?vue&type=style&index=0&id=47d0351b&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementAnimationPanel.vue?vue&type=style&index=0&id=79c3f50b&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\""],"sourceRoot":""} |