Annotate.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <template>
  2. <template v-for="(tool, index) in item" :key="`${tool.type}-${tool.dataElement || index}`">
  3. <StickyNoteButton v-if="tool.type === 'note' && !tool.hidden" :data-element="tool.dataElement" />
  4. <div v-else-if="['highlight', 'underline', 'strikeout', 'squiggly'].includes(tool.type)" class="markup-container">
  5. <Button v-if="tool.type === 'highlight' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: markupActive && markupTool === 'highlight' }" @click.stop="changeMarkupTool('highlight')" :title="$t('header.highlight')"><Highlight /></Button>
  6. <Button v-if="tool.type === 'underline' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: markupActive && markupTool === 'underline' }" @click.stop="changeMarkupTool('underline')" :title="$t('header.underline')"><Underline /></Button>
  7. <Button v-if="tool.type === 'strikeout' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: markupActive && markupTool === 'strikeout' }" @click.stop="changeMarkupTool('strikeout')" :title="$t('header.strikeout')"><Strikeout /></Button>
  8. <Button v-if="tool.type === 'squiggly' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: markupActive && markupTool === 'squiggly' }" @click.stop="changeMarkupTool('squiggly')" :title="$t('header.squiggly')"><Squiggle /></Button>
  9. </div>
  10. <Button v-if="tool.type === 'note' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: activeTool === 'ink' }" @click="changeActiveTool('ink')" :title="$t('header.ink')">
  11. <Ink />
  12. </Button>
  13. <div v-else-if="['circle', 'square', 'arrow', 'line'].includes(tool.type)" class="shape-container">
  14. <Button v-if="tool.type === 'circle' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: shapeActive && shapeTool === 'circle' }" @click.stop="changeShapeTool('circle')" :title="$t('header.circle')">
  15. <EllipseTool />
  16. </Button>
  17. <Button v-if="tool.type === 'square' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: shapeActive && shapeTool === 'square' }" @click.stop="changeShapeTool('square')" :title="$t('header.square')">
  18. <RectangleTool />
  19. </Button>
  20. <Button v-if="tool.type === 'arrow' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: shapeActive && shapeTool === 'arrow' }" @click.stop="changeShapeTool('arrow')" :title="$t('header.arrow')">
  21. <ArrowTool />
  22. </Button>
  23. <Button v-if="tool.type === 'line' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: shapeActive && shapeTool === 'line' }" @click.stop="changeShapeTool('line')" :title="$t('header.line')">
  24. <LineTool />
  25. </Button>
  26. </div>
  27. <Button v-else-if="tool.type === 'freetext' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: activeTool === 'freetext' }" @click="changeActiveTool('freetext')" :title="$t('header.freetext')">
  28. <Text />
  29. </Button>
  30. <Button v-else-if="tool.type === 'stamp' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: activeTool === 'stamp' }" @click="changeActiveTool('stamp')" :title="$t('header.stamp')">
  31. <Stamp />
  32. </Button>
  33. <Button v-else-if="tool.type === 'image' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: activeTool === 'image' }" @click="changeActiveTool('image')" :title="$t('header.image')">
  34. <Image />
  35. </Button>
  36. <Button v-else-if="tool.type === 'link' && !tool.hidden" :data-element="tool.dataElement" :class="{ active: activeTool === 'link' }" @click="changeActiveTool('link')" :title="$t('header.link')">
  37. <Link />
  38. </Button>
  39. </template>
  40. <div class="divider pc"></div>
  41. <div v-if="showColors.includes(activeTool)" class="colors-container">
  42. <span class="cell-container">
  43. <span class="cell-outer" :class="{ active: activeToolColor === '#FF0000' }" @click="setActiveToolColor('#FF0000')">
  44. <span class="cell red"></span></span>
  45. </span>
  46. <span class="cell-container">
  47. <span class="cell-outer" :class="{ active: activeToolColor === '#FFEC66' }" @click="setActiveToolColor('#FFEC66')">
  48. <span class="cell yellow"></span></span>
  49. </span>
  50. <span class="cell-container">
  51. <span class="cell-outer" :class="{ active: activeToolColor === '#2D77FA' }" @click="setActiveToolColor('#2D77FA')">
  52. <span class="cell blue"></span></span>
  53. </span>
  54. <span class="cell-container">
  55. <span class="cell-outer" :class="{ active: activeToolColor === '#64BC38' }" @click="setActiveToolColor('#64BC38')">
  56. <span class="cell green"></span></span>
  57. </span>
  58. </div>
  59. </template>
  60. <script setup>
  61. import { computed, onUnmounted } from 'vue'
  62. import { useViewerStore } from '@/stores/modules/viewer'
  63. import { useDocumentStore } from '@/stores/modules/document'
  64. import core from '@/core'
  65. const { switchTool, switchAnnotationEditorMode } = core
  66. const { item } = defineProps(['item'])
  67. const useDocument = useDocumentStore()
  68. const useViewer = useViewerStore()
  69. const activeTool = computed(() => useDocument.getActiveTool)
  70. const markupActive = computed(() => {
  71. const markups = ['highlight', 'underline', 'squiggly', 'strikeout']
  72. return markups.includes(activeTool.value)
  73. })
  74. const showColors = ['highlight', 'underline', 'squiggly', 'strikeout', 'square', 'circle', 'arrow', 'line', 'ink']
  75. const shapeActive = computed(() => {
  76. const shapes = ['square', 'circle', 'arrow', 'line']
  77. return shapes.includes(activeTool.value)
  78. })
  79. const markupTool = computed(() => useDocument.getMarkupToolState)
  80. const shapeTool = computed(() => useDocument.getShapeToolState)
  81. const activeToolColor = computed(() => useDocument.getActiveToolColor)
  82. const changeActiveTool = (tool) => {
  83. useDocument.setToolState(tool)
  84. useViewer.toggleActiveHand(false)
  85. switchTool(0)
  86. switchAnnotationEditorMode(0)
  87. if (tool === 'stamp') {
  88. useViewer.toggleElement('stampPanel')
  89. } else {
  90. useViewer.closeElement('stampPanel')
  91. }
  92. if (activeTool.value === 'image') {
  93. document.getElementById('signImageInput').click()
  94. }
  95. }
  96. const changeMarkupTool = (tool) => {
  97. useDocument.setMarkupToolState(tool)
  98. changeActiveTool(tool)
  99. }
  100. const changeShapeTool = (tool) => {
  101. useDocument.setShapeToolState(tool)
  102. changeActiveTool(tool)
  103. }
  104. const setActiveToolColor = (color) => {
  105. useDocument.setActiveToolColor(color)
  106. }
  107. const unselectImage = () => {
  108. if (activeTool.value === 'image') {
  109. changeActiveTool('image')
  110. }
  111. }
  112. core.addEvent('imageChange', unselectImage)
  113. onUnmounted(() => {
  114. core.removeEvent('imageChange', unselectImage)
  115. })
  116. </script>
  117. <style lang="scss">
  118. .shape-container, .markup-container {
  119. display: flex;
  120. align-items: center;
  121. }
  122. .colors-container {
  123. display: flex;
  124. padding: 5px 8px;
  125. border: 1px solid var(--c-findbar-input-border);
  126. span {
  127. display: block;
  128. }
  129. .cell-container {
  130. padding: 0;
  131. border: none;
  132. background-color: transparent;
  133. cursor: pointer;
  134. display: flex;
  135. align-items: center;
  136. justify-content: center;
  137. outline: none;
  138. .cell-outer {
  139. border: 2px solid transparent;
  140. width: 20px;
  141. height: 20px;
  142. border-radius: 50%;
  143. display: flex;
  144. align-items: center;
  145. justify-content: center;
  146. & + .cell-outer {
  147. margin-left: 8px;
  148. }
  149. &.active {
  150. border-color: var(--c-header-circle-bg);
  151. }
  152. .cell {
  153. width: 14px;
  154. height: 14px;
  155. border-radius: 50%;
  156. &.red {
  157. background-color: #FF0000;
  158. }
  159. &.yellow {
  160. background-color: #FFEC66;
  161. }
  162. &.blue {
  163. background-color: #2D77FA;
  164. }
  165. &.green {
  166. background-color: #64BC38;
  167. }
  168. }
  169. }
  170. }
  171. }
  172. @media screen and (max-width: 768px) {
  173. .pc {
  174. display: none;
  175. }
  176. }
  177. </style>