useCameraMap.ts 5.9 KB

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