useCameraMap.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { fabric } from 'fabric';
  2. import { ref } from 'vue';
  3. import cameraImg from '@/assets/camera/camera.png';
  4. import {
  5. CameraImage,
  6. MapData,
  7. OnMoving,
  8. OnRightClick,
  9. OnSelect,
  10. isCanvas,
  11. OnRotating,
  12. } from './types';
  13. import { fabricSetting } from './fabricSetting';
  14. import { getRandomPosition } from './utils';
  15. fabricSetting();
  16. interface Props {
  17. onSelect: OnSelect;
  18. onRightClick: OnRightClick;
  19. onMoving: OnMoving;
  20. onRotating: OnRotating;
  21. }
  22. function useCameraMap(props: Props) {
  23. let canvas;
  24. const createMap = (canvasId: string) => {
  25. canvas = new fabric.Canvas(canvasId, {
  26. fireRightClick: true, // 启用右键,button的数字为3
  27. stopContextMenu: true, // 禁止默认右键菜单
  28. });
  29. addListener();
  30. window.canvas = canvas;
  31. };
  32. /** 监听点击事件 */
  33. const addListener = () => {
  34. if (!isCanvas(canvas)) return;
  35. canvas.on('mouse:down', (options) => {
  36. if (!canvas) return;
  37. const target = options.target as CameraImage;
  38. const cameraId = target?.cameraId;
  39. // console.log('当前选中的id是', cameraId);
  40. console.log('mouse:down');
  41. console.log(options);
  42. // 判断:右键,且在元素上右键
  43. // opt.button: 1-左键;2-中键;3-右键
  44. // 在画布上点击:opt.target 为 null
  45. if (options.button === 3 && options.target) {
  46. props.onRightClick(options);
  47. return;
  48. }
  49. if (!cameraId || !target) {
  50. props.onSelect(null);
  51. return;
  52. }
  53. props.onSelect(target);
  54. });
  55. canvas.on('object:moving', (e) => {
  56. // console.log('object moving', e);
  57. props.onMoving(e);
  58. });
  59. canvas.on('object:rotating', function (e) {
  60. props.onRotating(e);
  61. });
  62. };
  63. /** 上传背景图 */
  64. const uploadBg = (imgUrl: string) => {
  65. if (!isCanvas(canvas)) return;
  66. fabric.Image.fromURL(imgUrl, (img) => {
  67. const refImg = ref(img);
  68. console.log('image', img);
  69. canvas!.setWidth(img.width!);
  70. canvas!.setHeight(img.height!);
  71. refImg.value.lockScalingX = true;
  72. refImg.value.lockScalingY = true;
  73. // 设置背景图
  74. canvas?.setBackgroundImage(refImg.value, canvas!.renderAll.bind(canvas));
  75. });
  76. };
  77. /** 增加一个摄像头 */
  78. const addCamera = (cameraId: string): Promise<CameraImage> => {
  79. if (!isCanvas(canvas)) return Promise.reject();
  80. // eslint-disable-next-line @typescript-eslint/no-this-alias
  81. return new Promise((resolve) => {
  82. fabric.Image.fromURL(cameraImg, (img) => {
  83. const cImg = ref(img as unknown as CameraImage);
  84. cImg.value.set({
  85. left: getRandomPosition(),
  86. top: getRandomPosition(),
  87. cameraId,
  88. });
  89. cImg.value.lockScalingX = true;
  90. cImg.value.lockScalingY = true;
  91. canvas?.add(cImg.value);
  92. canvas?.setActiveObject(cImg.value);
  93. // cImg.value.on('moving', function (e) {
  94. // props.onMoving(e);
  95. // });
  96. // cImg.value.on('rotating', function (e) {
  97. // props.onRotating(e);
  98. // });
  99. resolve(cImg.value);
  100. });
  101. });
  102. };
  103. /** 删除一个摄像头 */
  104. const removeActiveCamera = () => {
  105. if (!isCanvas(canvas)) return;
  106. const activeObject = canvas?.getActiveObject();
  107. if (!activeObject) return;
  108. canvas.remove(activeObject);
  109. const objects = canvas.getObjects();
  110. if (objects.length > 0) {
  111. canvas.setActiveObject(objects[0]);
  112. }
  113. };
  114. /** 导出JSON格式 */
  115. const toJSON = () => {
  116. if (!isCanvas(canvas)) return;
  117. const initialJSON = canvas.toJSON(['cameraId']);
  118. /** toJSON返回值的类型它写错了,应该是有backgroundImage的 */
  119. const { src, type, version, width, height, left, top, angle } =
  120. (initialJSON as any).backgroundImage || {};
  121. const newObjects = initialJSON.objects.map((item) => {
  122. return {
  123. type: item.type,
  124. width: item.width,
  125. height: item.height,
  126. left: item.left,
  127. top: item.top,
  128. angle: item.angle,
  129. cameraId: (item as CameraImage).cameraId,
  130. };
  131. });
  132. const newJson = {
  133. version: initialJSON.version,
  134. backgroundImage: { src, type, version, width, height, left, top, angle },
  135. objects: newObjects,
  136. };
  137. return newJson;
  138. };
  139. /** 从json中加载 */
  140. const loadFromJSON = (json: MapData): Promise<void> => {
  141. if (!isCanvas(canvas)) return Promise.reject();
  142. canvas.clear();
  143. return new Promise((resolve) => {
  144. const { width, height } = json.backgroundImage;
  145. canvas?.setWidth(width);
  146. canvas?.setHeight(height);
  147. const objects = json.objects.map((item) => {
  148. return {
  149. ...item,
  150. src: cameraImg,
  151. };
  152. });
  153. canvas?.loadFromJSON({ ...json, objects }, () => {
  154. resolve();
  155. });
  156. });
  157. };
  158. /** 更新摄像头的渲染 */
  159. const renderCamera = () => {
  160. canvas?.renderAll();
  161. };
  162. /** */
  163. const clear = () => {
  164. canvas?.clear();
  165. };
  166. /** 是否已经存在这个cameraId */
  167. const hasCamera = (cameraId: string) => {
  168. const cameraIds =
  169. canvas?.toJSON(['cameraId']).objects.map((item) => (item as CameraImage).cameraId) || [];
  170. return cameraIds.includes(cameraId);
  171. };
  172. const getObjects = () => {
  173. return canvas?.getObjects() as CameraImage[];
  174. };
  175. /** 根据cameraId查找某个元素 */
  176. const getCameraById = (cameraId: string) => {
  177. return canvas
  178. ?.getObjects()
  179. .find((x) => (x as CameraImage).cameraId === cameraId) as CameraImage;
  180. };
  181. return {
  182. canvas,
  183. createMap,
  184. uploadBg,
  185. addCamera,
  186. removeActiveCamera,
  187. toJSON,
  188. loadFromJSON,
  189. renderCamera,
  190. clear,
  191. hasCamera,
  192. getCameraById,
  193. getObjects,
  194. };
  195. }
  196. export default useCameraMap;