droneFront.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { css } from '@emotion/css';
  2. import React, { FC } from 'react';
  3. import { GrafanaTheme2 } from '@grafana/data';
  4. import { useStyles2 } from '@grafana/ui';
  5. import { DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions';
  6. import { ScalarDimensionEditor } from 'app/features/dimensions/editors';
  7. import { CanvasElementItem, CanvasElementProps } from '../element';
  8. interface DroneFrontData {
  9. rollAngle?: number;
  10. }
  11. interface DroneFrontConfig {
  12. rollAngle?: ScalarDimensionConfig;
  13. }
  14. const DroneFrontDisplay: FC<CanvasElementProps<DroneFrontConfig, DroneFrontData>> = (props) => {
  15. const styles = useStyles2(getStyles);
  16. const { data } = props;
  17. const droneFrontTransformStyle = `rotate(${data?.rollAngle ? data.rollAngle : 0}deg)`;
  18. return (
  19. <svg
  20. className={styles.droneFront}
  21. xmlns="http://www.w3.org/2000/svg"
  22. xmlnsXlink="http://www.w3.org/1999/xlink"
  23. viewBox="0 0 1300 290"
  24. style={{ transform: droneFrontTransformStyle }}
  25. >
  26. <g className="arms" stroke="black" strokeWidth="28px">
  27. <line x1="510" x2="320" y1="100" y2="150" />
  28. <line x1="510" x2="320" y1="190" y2="210" />
  29. <line x1="790" x2="980" y1="190" y2="210" />
  30. <line x1="790" x2="980" y1="100" y2="150" />
  31. </g>
  32. <g className="body" stroke="black" strokeWidth="28px">
  33. <path
  34. fill="none"
  35. d=" M 510 130 C 510 124 510 110 510 100 C 510 90 530 71 540 70 C 640 61 670 60 760 70 C 770 71 790 90 790 100 Q 790 120 790 130 L 790 130 Q 790 177 790 196 C 790 207 770 225 760 226 C 670 236 640 236 540 226 C 530 226 510 206 510 196 Q 510 177 510 130 Q 510 133 510 130 Z "
  36. />
  37. <circle cx="650" cy="160" r="40" fill="none" />
  38. </g>
  39. <g className="motors" stroke="black" strokeWidth="28px">
  40. <path
  41. className="motor"
  42. fill="none"
  43. d=" M 320 60 L 250 60 L 250 230 L 260 290 L 310 290 L 320 230 L 320 60 Z "
  44. />
  45. <path
  46. className="motor"
  47. fill="none"
  48. d=" M 1050 60 L 980 60 L 980 230 L 990 290 L 1040 290 L 1050 230 L 1050 60 Z "
  49. />
  50. </g>
  51. <g className="propellers" fill="black">
  52. <path
  53. className="prop"
  54. d=" M 270 60 L 300 60 L 300 20 Q 311 30 330 30 Q 349 30 570 10 L 300 10 Q 300 0 290 0 C 286 0 284 0 280 0 Q 270 0 270 10 L 0 10 Q 220 30 240 30 Q 260 30 270 20 L 270 60 Z "
  55. />
  56. <path
  57. className="prop"
  58. d=" M 1000 60 L 1030 60 L 1030 20 Q 1041 30 1060 30 Q 1079 30 1300 10 L 1030 10 Q 1030 0 1020 0 C 1016 0 1014 0 1010 0 Q 1000 0 1000 10 L 730 10 Q 950 30 970 30 Q 990 30 1000 20 L 1000 60 Z "
  59. />
  60. </g>
  61. </svg>
  62. );
  63. };
  64. export const droneFrontItem: CanvasElementItem<any, any> = {
  65. id: 'droneFront',
  66. name: 'Drone Front',
  67. description: 'Drone front',
  68. display: DroneFrontDisplay,
  69. defaultSize: {
  70. width: 100,
  71. height: 100,
  72. },
  73. getNewOptions: (options) => ({
  74. ...options,
  75. }),
  76. // Called when data changes
  77. prepareData: (ctx: DimensionContext, cfg: DroneFrontConfig) => {
  78. const data: DroneFrontData = {
  79. rollAngle: cfg?.rollAngle ? ctx.getScalar(cfg.rollAngle).value() : 0,
  80. };
  81. return data;
  82. },
  83. registerOptionsUI: (builder) => {
  84. const category = ['Drone Front'];
  85. builder.addCustomEditor({
  86. category,
  87. id: 'rollAngle',
  88. path: 'config.rollAngle',
  89. name: 'Roll Angle',
  90. editor: ScalarDimensionEditor,
  91. });
  92. },
  93. };
  94. const getStyles = (theme: GrafanaTheme2) => ({
  95. droneFront: css`
  96. transition: transform 0.4s;
  97. `,
  98. });