| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- import { Point, Canvas } from 'fabric'
- import { watch, computed } from 'vue'
- import { storeToRefs } from 'pinia'
- import { Disposable } from '@/utils/lifecycle'
- import useCanvasSwipe from '@/hooks/useCanvasSwipe'
- import { useKeyboardStore } from '@/store'
- import { useActiveElement, toValue } from '@vueuse/core'
- type ToolOption = {
- defaultCursor: string
- skipTargetFind: boolean
- selection: boolean
- }
- type ToolType = 'move' | 'handMove' | 'shape'
- export class FabricTool extends Disposable {
- private options: Record<ToolType, ToolOption> = {
- move: {
- defaultCursor: 'default',
- skipTargetFind: false,
- selection: true,
- },
- handMove: {
- defaultCursor: 'grab',
- skipTargetFind: true,
- selection: false,
- },
- shape: {
- defaultCursor: 'crosshair',
- skipTargetFind: true,
- selection: false,
- },
- }
- private _handMoveActivate = false
- private get handMoveActivate() {
- return this._handMoveActivate
- }
- private set handMoveActivate(value) {
- this._handMoveActivate = value
- }
- constructor(private readonly canvas: Canvas) {
- super()
- this.initHandMove()
- }
- private applyOption(tool: ToolType) {
- const { defaultCursor, skipTargetFind, selection } = this.options[tool]
- this.canvas.defaultCursor = defaultCursor
- this.canvas.setCursor(defaultCursor)
- this.canvas.skipTargetFind = skipTargetFind
- this.canvas.selection = selection
- }
- // private switchShape(shape: 'board' | 'rect' | 'ellipse' | 'triangle' | 'text') {
- // const { canvas } = this
- // let coordsStart: Point | undefined
- // let tempObject: FabricObject | undefined
- // const { stop, isSwiping } = useFabricSwipe({
- // onSwipeStart: (e) => {
- // if (e.button !== 1 || this.space.value) return
- // /*
- // * 只有mouseMove的时候isSwiping才会为true
- // * mouseUp会判断isSwiping的值来决定是否执行onSwipeEnd
- // * 这里强制设置成true,让点击也可执行onSwipeEnd
- // */
- // isSwiping.value = true
- // // 获得坐标
- // coordsStart = e.pointer
- // // 创建形状
- // switch (shape) {
- // case 'board':
- // tempObject = new Board([], {
- // fill: '',
- // })
- // break
- // case 'rect':
- // tempObject = new Rect({})
- // break
- // case 'ellipse':
- // tempObject = new Ellipse({
- // rx: 50,
- // ry: 50,
- // })
- // break
- // case 'triangle':
- // tempObject = new Triangle({})
- // break
- // case 'text':
- // tempObject = new Textbox('', {})
- // break
- // }
- // tempObject.set({
- // left: coordsStart.x,
- // top: coordsStart.y,
- // width: 100,
- // height: 100,
- // scaleX: 0.01,
- // scaleY: 0.01,
- // hideOnLayer: true,
- // })
- // // 不发送ObjectAdded事件
- // tempObject.noEventObjectAdded = true
- // // 添加对象到画板
- // const board = this.canvas._searchPossibleTargets(
- // this.canvas.getObjects('Board'),
- // e.absolutePointer,
- // ) as Board | undefined
- // const parent = board || canvas
- // parent.add(tempObject)
- // // 取消不发送
- // tempObject.noEventObjectAdded = false
- // // 设置激活对象
- // canvas.setActiveObject(tempObject)
- // tempObject.__corner = 'br'
- // canvas._setupCurrentTransform(e.e, tempObject, true)
- // },
- // onSwipeEnd: (e) => {
- // if (!tempObject) return
- // console.log('onSwipeEnd:', tempObject)
- // // 如果点击画板,没有移动,设置默认宽高
- // if (tempObject.scaleX <= 0.01 && tempObject.scaleY <= 0.01) {
- // tempObject.set({
- // left: tempObject.left - 50,
- // top: tempObject.top - 50,
- // scaleX: 1,
- // scaleY: 1,
- // })
- // }
- // // 设置宽高缩放
- // tempObject.set({
- // width: tempObject.getScaledWidth(),
- // height: tempObject.getScaledHeight(),
- // scaleX: 1,
- // scaleY: 1,
- // hideOnLayer: false,
- // })
- // // 特殊形状处理
- // if (tempObject instanceof Board) {
- // tempObject.set({
- // fill: '#ffffff',
- // })
- // } else if (tempObject instanceof Ellipse) {
- // tempObject.set({
- // rx: tempObject.width / 2,
- // ry: tempObject.height / 2,
- // })
- // } else if (tempObject instanceof Textbox) {
- // tempObject.set({
- // text: '输入文本',
- // })
- // canvas.defaultCursor = 'default'
- // tempObject.enterEditing(e.e)
- // tempObject.selectAll()
- // }
- // // 通知事件
- // if (!tempObject.group) {
- // canvas._onObjectAdded(tempObject)
- // }
- // canvas.fire('selection:updated')
- // canvas.requestRenderAll()
- // tempObject = undefined
- // useAppStore().activeTool = 'move'
- // },
- // })
- // this.toolStop = stop
- // }
- /**
- *鼠标中键拖动视窗
- */
- private initHandMove() {
- const canvas = this.canvas
- /** 鼠标移动开始的vpt */
- let vpt = canvas.viewportTransform
- const { spaceKeyState } = storeToRefs(useKeyboardStore())
- const { lengthX, lengthY, isSwiping } = useCanvasSwipe({
- onSwipeStart: (e: any) => {
- if (e.e.buttons === 2 || (spaceKeyState.value && e.e.buttons === 1)) {
- isSwiping.value = true
- vpt = canvas.viewportTransform
- this.handMoveActivate = true
- this.applyOption('handMove')
- canvas.setCursor('grab')
- }
- },
- onSwipe: () => {
- if (!this.handMoveActivate) return
- canvas.setCursor('grab')
- requestAnimationFrame(() => {
- const deltaPoint = new Point(lengthX.value, lengthY.value).scalarDivide(canvas.getZoom()).transform(vpt).scalarMultiply(-1)
- canvas.absolutePan(deltaPoint, true)
- })
- },
- onSwipeEnd: () => {
- // 恢复鼠标指针
- this.applyOption(spaceKeyState.value ? 'handMove' : 'move')
- if (!this.handMoveActivate) return
- // 关闭 handMove
- if (!spaceKeyState.value) {
- this.handMoveActivate = false
- }
- },
- })
- // 空格键切换移动工具
- const activeElement = useActiveElement()
- const activeElementHasInput = computed(() => activeElement.value?.tagName !== 'INPUT' && activeElement.value?.tagName !== 'TEXTAREA')
-
-
- watch(
- computed(() => [spaceKeyState.value, activeElementHasInput.value].every((i) => toValue(i))),
- (space) => {
- this.applyOption(space ? 'handMove' : 'move')
- if (isSwiping.value) return
- this.handMoveActivate = space
- },
- )
- }
- }
|