import { fabric } from 'fabric'; import { ref } from 'vue'; import cameraImg from '@/assets/camera/camera.png'; import { CameraImage, MapData, OnMoving, OnRightClick, OnSelect, isCanvas, OnRotating, } from './types'; import { fabricSetting } from './fabricSetting'; import { getRandomPosition } from './utils'; fabricSetting(); interface Props { onSelect: OnSelect; onRightClick: OnRightClick; onMoving: OnMoving; onRotating: OnRotating; } function useCameraMap(props: Props) { let canvas; const createMap = (canvasId: string) => { canvas = new fabric.Canvas(canvasId, { fireRightClick: true, // 启用右键,button的数字为3 stopContextMenu: true, // 禁止默认右键菜单 }); addListener(); window.canvas = canvas; }; /** 监听点击事件 */ const addListener = () => { if (!isCanvas(canvas)) return; canvas.on('mouse:down', (options) => { if (!canvas) return; const target = options.target as CameraImage; const cameraId = target?.cameraId; // console.log('当前选中的id是', cameraId); console.log('mouse:down'); console.log(options); // 判断:右键,且在元素上右键 // opt.button: 1-左键;2-中键;3-右键 // 在画布上点击:opt.target 为 null if (options.button === 3 && options.target) { props.onRightClick(options); return; } if (!cameraId || !target) { props.onSelect(null); return; } props.onSelect(target); }); canvas.on('object:moving', (e) => { // console.log('object moving', e); props.onMoving(e); }); canvas.on('object:rotating', function (e) { props.onRotating(e); }); }; /** 上传背景图 */ const uploadBg = (imgUrl: string) => { if (!isCanvas(canvas)) return; fabric.Image.fromURL(imgUrl, (img) => { const refImg = ref(img); console.log('image', img); canvas!.setWidth(img.width!); canvas!.setHeight(img.height!); refImg.value.lockScalingX = true; refImg.value.lockScalingY = true; // 设置背景图 canvas?.setBackgroundImage(refImg.value, canvas!.renderAll.bind(canvas)); }); }; /** 增加一个摄像头 */ const addCamera = (cameraId: string): Promise => { if (!isCanvas(canvas)) return Promise.reject(); // eslint-disable-next-line @typescript-eslint/no-this-alias return new Promise((resolve) => { fabric.Image.fromURL(cameraImg, (img) => { const cImg = ref(img as unknown as CameraImage); cImg.value.set({ left: getRandomPosition(), top: getRandomPosition(), cameraId, }); cImg.value.lockScalingX = true; cImg.value.lockScalingY = true; canvas?.add(cImg.value); canvas?.setActiveObject(cImg.value); // cImg.value.on('moving', function (e) { // props.onMoving(e); // }); // cImg.value.on('rotating', function (e) { // props.onRotating(e); // }); resolve(cImg.value); }); }); }; /** 删除一个摄像头 */ const removeActiveCamera = () => { if (!isCanvas(canvas)) return; const activeObject = canvas?.getActiveObject(); if (!activeObject) return; canvas.remove(activeObject); const objects = canvas.getObjects(); if (objects.length > 0) { canvas.setActiveObject(objects[0]); } }; /** 导出JSON格式 */ const toJSON = () => { if (!isCanvas(canvas)) return; const initialJSON = canvas.toJSON(['cameraId']); /** toJSON返回值的类型它写错了,应该是有backgroundImage的 */ const { src, type, version, width, height, left, top, angle } = (initialJSON as any).backgroundImage || {}; const newObjects = initialJSON.objects.map((item) => { return { type: item.type, width: item.width, height: item.height, left: item.left, top: item.top, angle: item.angle, cameraId: (item as CameraImage).cameraId, }; }); const newJson = { version: initialJSON.version, backgroundImage: { src, type, version, width, height, left, top, angle }, objects: newObjects, }; return newJson; }; /** 从json中加载 */ const loadFromJSON = (json: MapData): Promise => { if (!isCanvas(canvas)) return Promise.reject(); canvas.clear(); return new Promise((resolve) => { const { width, height } = json.backgroundImage; canvas?.setWidth(width); canvas?.setHeight(height); const objects = json.objects.map((item) => { return { ...item, src: cameraImg, }; }); canvas?.loadFromJSON({ ...json, objects }, () => { resolve(); }); }); }; /** 更新摄像头的渲染 */ const renderCamera = () => { canvas?.renderAll(); }; /** */ const clear = () => { canvas?.clear(); }; /** 是否已经存在这个cameraId */ const hasCamera = (cameraId: string) => { const cameraIds = canvas?.toJSON(['cameraId']).objects.map((item) => (item as CameraImage).cameraId) || []; return cameraIds.includes(cameraId); }; const getObjects = () => { return canvas?.getObjects() as CameraImage[]; }; /** 根据cameraId查找某个元素 */ const getCameraById = (cameraId: string) => { return canvas ?.getObjects() .find((x) => (x as CameraImage).cameraId === cameraId) as CameraImage; }; return { canvas, createMap, uploadBg, addCamera, removeActiveCamera, toJSON, loadFromJSON, renderCamera, clear, hasCamera, getCameraById, getObjects, }; } export default useCameraMap;