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'; import { object } from 'vue-types'; fabricSetting(); interface Props { onSelect: OnSelect; onRightClick: OnRightClick; onMoving: OnMoving; onRotating: OnRotating; } function useCameraMap(props: Props) { const canvas = ref(); const createMap = (canvasId: string) => { canvas.value = new fabric.Canvas(canvasId, { fireRightClick: true, // 启用右键,button的数字为3 stopContextMenu: true, // 禁止默认右键菜单 }); addListener(); window.canvas = canvas.value; }; /** 监听点击事件 */ const addListener = () => { if (!isCanvas(canvas.value)) return; canvas.value.on('mouse:down', (options) => { if (!canvas.value) 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); }); }; /** 上传背景图 */ const uploadBg = (imgUrl: string) => { if (!isCanvas(canvas.value)) return; fabric.Image.fromURL(imgUrl, (img) => { const refImg = ref(img); console.log('image', img); canvas.value!.setWidth(img.width!); canvas.value!.setHeight(img.height!); refImg.value.lockScalingX = true; refImg.value.lockScalingY = true; // 设置背景图 canvas.value?.setBackgroundImage(refImg.value, canvas.value!.renderAll.bind(canvas.value)); }); }; /** 增加一个摄像头 */ const addCamera = (cameraId: string): Promise => { if (!isCanvas(canvas.value)) 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.value?.add(cImg.value); canvas.value?.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.value)) return; const activeObject = canvas.value?.getActiveObject(); if (!activeObject) return; canvas.value.remove(activeObject); const objects = canvas.value.getObjects(); if (objects.length > 0) { canvas.value.setActiveObject(objects[0]); } }; /** 导出JSON格式 */ const toJSON = () => { if (!isCanvas(canvas.value)) return; const initialJSON = canvas.value.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.value)) return Promise.reject(); return new Promise((resolve) => { const { width, height } = json.backgroundImage; canvas.value?.setWidth(width); canvas.value?.setHeight(height); const objects = json.objects.map((item) => { return { ...item, src: cameraImg, }; }); canvas.value?.loadFromJSON({ ...json, objects }, () => { resolve(); }); }); }; /** 更新摄像头的渲染 */ const renderCamera = () => { canvas.value?.renderAll.bind(canvas.value); }; /** */ const clear = () => { canvas.value?.clear(); }; /** 是否已经存在这个cameraId */ const hasCamera = (cameraId: string) => { const cameraIds = canvas.value?.toJSON(['cameraId']).objects.map((item) => (item as CameraImage).cameraId) || []; return cameraIds.includes(cameraId); }; const getObjects = () => { return canvas.value?.getObjects() as CameraImage[]; }; /** 根据cameraId查找某个元素 */ const getCameraById = (cameraId: string) => { return canvas.value ?.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;