AnnotationCanvas.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. <template>
  2. <div v-if="show">
  3. <el-row :gutter="20">
  4. <el-col :span="24">
  5. <canvas
  6. ref="canvas"
  7. class="drawing-canvas"
  8. @mousedown="handleMouseDown"
  9. @mousemove="handleMouseMove"
  10. @mouseup="handleMouseUp"
  11. @mouseleave="handleMouseUp"
  12. @touchstart="handleTouchStart"
  13. @touchmove="handleTouchMove"
  14. @touchend="handleTouchEnd"
  15. ></canvas>
  16. </el-col>
  17. </el-row>
  18. <el-row
  19. :gutter="20"
  20. class="toolbar"
  21. :style="`${showTool ? '' : 'display:none'}`"
  22. >
  23. <el-col :span="24" class="toolbar-container">
  24. <div class="brushBtn">
  25. <!-- <el-button
  26. @click="setMode('draw')"
  27. icon="el-icon-edit"
  28. :class="{ active: mode === 'draw' }"
  29. >画笔</el-button
  30. > -->
  31. <el-tooltip class="item" effect="light" content="画笔" placement="top">
  32. <svg
  33. width="24"
  34. height="24"
  35. viewBox="0 0 24 24"
  36. :style="mode === 'draw' ? `background-color:${brushColor}` : ''"
  37. fill="none"
  38. xmlns="http://www.w3.org/2000/svg"
  39. @click.stop="setMode('draw')"
  40. >
  41. <path
  42. fill-rule="evenodd"
  43. clip-rule="evenodd"
  44. d="M12 6.75C12.2508 6.75 12.4849 6.87533 12.624 7.08397L15.624 11.584C15.7062 11.7072 15.75 11.8519 15.75 12V21C15.75 21.4142 15.4142 21.75 15 21.75C14.5858 21.75 14.25 21.4142 14.25 21V12.75H9.75V21C9.75 21.4142 9.41421 21.75 9 21.75C8.58579 21.75 8.25 21.4142 8.25 21V12C8.25 11.8519 8.29383 11.7072 8.37596 11.584L11.376 7.08397C11.5151 6.87533 11.7492 6.75 12 6.75ZM10.4014 11.25H13.5986L12 8.85208L10.4014 11.25Z"
  45. :fill="mode === 'draw' ? brushColor==='#FFFFFF'?'black':'#fff' : '#3681FC'"
  46. />
  47. <path
  48. fill-rule="evenodd"
  49. clip-rule="evenodd"
  50. d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM12 22.5C17.799 22.5 22.5 17.799 22.5 12C22.5 6.20101 17.799 1.5 12 1.5C6.20101 1.5 1.5 6.20101 1.5 12C1.5 17.799 6.20101 22.5 12 22.5Z"
  51. :fill="mode === 'draw' ? brushColor==='#FFFFFF'?'black':'#fff' : 'black'"
  52. fill-opacity="0.9"
  53. />
  54. </svg>
  55. </el-tooltip>
  56. <el-tooltip
  57. class="item"
  58. effect="light"
  59. content="切换颜色"
  60. placement="top"
  61. >
  62. <el-button
  63. class="selectBox"
  64. @click.stop="changeOpenBrushColorBox(!openBrushColorBox)"
  65. :icon="
  66. openBrushColorBox ? 'el-icon-arrow-down' : 'el-icon-arrow-up'
  67. "
  68. ></el-button>
  69. </el-tooltip>
  70. <div class="brushBtn_colorBox" v-if="openBrushColorBox">
  71. <span
  72. v-for="(item, index) in colorList"
  73. :key="index"
  74. :style="`background-color: ${item};${
  75. item === '#FFFFFF' ? 'border:solid 2px #E2E1E5' : ''
  76. }`"
  77. @click="setColor(item)"
  78. ></span>
  79. </div>
  80. </div>
  81. <div>
  82. <el-slider
  83. v-model="brushSize"
  84. :min="1"
  85. :max="20"
  86. style="width: 100px"
  87. ></el-slider>
  88. </div>
  89. <!-- <div>
  90. <el-color-picker
  91. v-model="brushColor"
  92. @active-change="setColor"
  93. ></el-color-picker>
  94. </div> -->
  95. <div class="eraserBtn">
  96. <el-tooltip
  97. class="item"
  98. effect="light"
  99. content="橡皮擦"
  100. placement="top"
  101. >
  102. <svg
  103. width="24"
  104. height="24"
  105. viewBox="0 0 24 24"
  106. fill="none"
  107. :class="{ eraserBtnActive: mode === 'erase' }"
  108. xmlns="http://www.w3.org/2000/svg"
  109. @click.stop="setMode('erase')"
  110. >
  111. <path
  112. fill-rule="evenodd"
  113. clip-rule="evenodd"
  114. d="M13.6464 6.14645C13.8417 5.95118 14.1583 5.95118 14.3536 6.14645L17.8536 9.64645C18.0488 9.84171 18.0488 10.1583 17.8536 10.3536L11.2071 17H17.5V18H10C9.86739 18 9.74021 17.9473 9.64645 17.8536L6.14645 14.3536C5.95118 14.1583 5.95118 13.8417 6.14645 13.6464L13.6464 6.14645ZM10 16.7929L7.20711 14L9 12.2071L11.7929 15L10 16.7929ZM12.5 14.2929L16.7929 10L14 7.20711L9.70711 11.5L12.5 14.2929Z"
  115. fill="black"
  116. fill-opacity="0.9"
  117. />
  118. </svg>
  119. </el-tooltip>
  120. <!-- <el-button
  121. @click="setMode('erase')"
  122. icon="el-icon-connection"
  123. :class="{ active: mode === 'erase' }"
  124. >橡皮擦</el-button
  125. > -->
  126. </div>
  127. <!-- <el-button @click="setMode('line')" :class="{ active: mode === 'line' }">直线</el-button>
  128. <el-button @click="setMode('rect')" :class="{ active: mode === 'rect' }">矩形</el-button>
  129. <el-button @click="setMode('circle')" :class="{ active: mode === 'circle' }">圆圈</el-button> -->
  130. <div class="clearScreenBtn">
  131. <!-- <el-button @click="clearCanvas" icon="el-icon-refresh-left"
  132. >清空画布</el-button
  133. > -->
  134. <el-tooltip class="item" effect="light" content="清空" placement="top">
  135. <svg
  136. width="24"
  137. height="24"
  138. viewBox="0 0 24 24"
  139. fill="none"
  140. xmlns="http://www.w3.org/2000/svg"
  141. @click.stop="clearCanvas"
  142. >
  143. <path
  144. d="M12.7622 15.8897C12.6906 16.186 12.327 16.8335 11.7485 17.7059C11.9071 17.7442 12.0584 17.7873 12.2123 17.8164C12.4925 17.8695 12.775 17.9108 13.0552 17.9642C13.147 17.9818 13.1937 17.9469 13.2428 17.8711C13.8067 16.9985 14.2612 16.0662 14.6425 15.0947C14.7917 14.7147 14.9193 14.3252 15.0568 13.9401C15.0706 13.901 15.0844 13.8619 15.101 13.8148C15.4032 13.9233 15.6984 14.0292 16.0076 14.1401C15.9522 14.309 15.9021 14.4686 15.8476 14.6265C15.3838 15.9675 14.806 17.25 14.0368 18.4337C13.9729 18.532 13.9007 18.6244 13.8375 18.7233C13.6927 18.9501 13.4901 19.0203 13.236 18.9951C12.2568 18.8983 11.308 18.6663 10.3886 18.3061C8.71606 17.6508 7.27596 16.648 6.13465 15.2025C5.9979 15.0293 5.95862 14.8374 6.04787 14.634C6.13399 14.4379 6.29961 14.3488 6.50182 14.346C7.37097 14.334 8.20886 14.1527 9.019 13.834C9.75205 13.5455 10.42 13.1461 10.9342 12.5139C11.0831 12.3307 11.2047 12.1233 11.3453 11.9175L12.1832 12.4089C12.0277 12.6431 11.8895 12.8771 11.7268 13.0911C11.3292 13.6144 10.8276 14.0121 10.2707 14.3343C9.43156 14.8197 8.52561 15.0995 7.58204 15.2585C7.56342 15.2616 7.545 15.2656 7.49965 15.2746C7.63454 15.4033 7.74824 15.5234 7.87332 15.6288C8.10763 15.8262 8.34592 16.019 8.58921 16.2041C8.63666 16.2403 8.71971 16.2556 8.77787 16.2419C9.26162 16.1281 9.70587 15.9268 10.0783 15.5679C10.0462 15.744 9.74006 16.192 9.3107 16.6905C9.58042 16.8303 9.85304 16.9528 10.107 17.1082C10.4358 17.3093 10.7502 17.2546 11.0731 17.1093C11.6185 16.864 12.0858 16.4972 12.5333 16.0991C12.6058 16.0345 12.6767 15.968 12.7622 15.8897ZM16.2967 13.3014C14.7658 12.5925 13.2459 11.8889 11.7148 11.18C11.8414 10.8741 12.04 10.6413 12.3083 10.4766C12.7564 10.2015 13.2256 10.1707 13.702 10.3865C14.3139 10.6636 14.925 10.9432 15.5305 11.235C16.2423 11.578 16.5769 12.3494 16.3604 13.1153C16.3436 13.1748 16.3204 13.2326 16.2967 13.3014ZM15.6169 10.5242C15.1348 10.3007 14.6589 10.0803 14.1831 9.85909C14.1731 9.85439 14.1659 9.84304 14.1522 9.82989C14.1699 9.79241 14.1866 9.75481 14.2053 9.71826C14.8011 8.55524 15.3972 7.39231 15.9933 6.22935C16.093 6.03469 16.2093 5.97585 16.424 6.0085C16.6213 6.03839 16.7885 6.12638 16.9169 6.28695C17.0015 6.39268 17.0224 6.50787 16.9755 6.64248C16.5306 7.91644 16.0885 9.19145 15.6454 10.466C15.64 10.4817 15.631 10.496 15.6169 10.5242V10.5242Z"
  145. fill="black"
  146. />
  147. </svg>
  148. </el-tooltip>
  149. </div>
  150. <div class="cancelBtn">
  151. <el-tooltip
  152. class="item"
  153. effect="light"
  154. content="上一步"
  155. placement="top"
  156. >
  157. <svg
  158. width="24"
  159. height="24"
  160. viewBox="0 0 24 24"
  161. fill="none"
  162. xmlns="http://www.w3.org/2000/svg"
  163. @click.stop="undo"
  164. >
  165. <path
  166. fill-rule="evenodd"
  167. clip-rule="evenodd"
  168. d="M11 6.61328L6 9.50003L11 12.3868V10H14.5C16.1569 10 17.5 11.3432 17.5 13C17.5 14.6569 16.1569 16 14.5 16H6C5.72386 16 5.5 16.2239 5.5 16.5C5.5 16.7762 5.72386 17 6 17H14.5C16.7091 17 18.5 15.2092 18.5 13C18.5 10.7909 16.7091 9.00003 14.5 9.00003H11V6.61328Z"
  169. fill="black"
  170. fill-opacity="0.9"
  171. />
  172. </svg>
  173. </el-tooltip>
  174. <!-- <el-button-group style="display: flex">
  175. <el-button @click="undo" icon="el-icon-arrow-left"
  176. >上一步</el-button
  177. >
  178. <el-button @click="redo"
  179. >下一步<i class="el-icon-arrow-right el-icon--right"></i
  180. ></el-button>
  181. </el-button-group> -->
  182. </div>
  183. <div class="cancelBtn">
  184. <el-tooltip
  185. class="item"
  186. effect="light"
  187. content="下一步"
  188. placement="top"
  189. >
  190. <svg
  191. width="24"
  192. height="24"
  193. viewBox="0 0 24 24"
  194. fill="none"
  195. xmlns="http://www.w3.org/2000/svg"
  196. @click.stop="redo"
  197. >
  198. <path
  199. fill-rule="evenodd"
  200. clip-rule="evenodd"
  201. d="M13 6.61328L18 9.50003L13 12.3868V10H9.5C7.84315 10 6.5 11.3432 6.5 13C6.5 14.6569 7.84315 16 9.5 16H18C18.2761 16 18.5 16.2239 18.5 16.5C18.5 16.7762 18.2761 17 18 17H9.5C7.29086 17 5.5 15.2092 5.5 13C5.5 10.7909 7.29086 9.00003 9.5 9.00003H13V6.61328Z"
  202. fill="black"
  203. fill-opacity="0.9"
  204. />
  205. </svg>
  206. </el-tooltip>
  207. </div>
  208. <!-- <div>
  209. <el-button @click="downloadCanvas" icon="el-icon-download"
  210. >下载</el-button
  211. >
  212. </div> -->
  213. <div class="closeBtn">
  214. <el-tooltip
  215. class="item"
  216. effect="light"
  217. content="结束绘画"
  218. placement="top"
  219. >
  220. <svg
  221. width="24"
  222. height="24"
  223. viewBox="0 0 24 24"
  224. fill="none"
  225. xmlns="http://www.w3.org/2000/svg"
  226. @click.stop="close()"
  227. >
  228. <circle cx="12" cy="12" r="10" fill="#EE3E3E" />
  229. <path
  230. fill-rule="evenodd"
  231. clip-rule="evenodd"
  232. d="M9.1439 7.6929C9.29275 7.89983 9.24568 8.18824 9.03876 8.33709C7.75653 9.25949 6.92308 10.7631 6.92308 12.4615C6.92308 15.2654 9.19609 17.5384 12 17.5384C14.8039 17.5384 17.0769 15.2654 17.0769 12.4615C17.0769 10.7631 16.2435 9.25949 14.9612 8.33709C14.7543 8.18824 14.7073 7.89983 14.8561 7.6929C15.005 7.48598 15.2934 7.43891 15.5003 7.58776C17.0133 8.67615 18 10.4536 18 12.4615C18 15.7752 15.3137 18.4615 12 18.4615C8.68629 18.4615 6 15.7752 6 12.4615C6 10.4536 6.98673 8.67615 8.49971 7.58776C8.70663 7.43891 8.99504 7.48598 9.1439 7.6929Z"
  233. fill="white"
  234. fill-opacity="0.9"
  235. />
  236. <path
  237. fill-rule="evenodd"
  238. clip-rule="evenodd"
  239. d="M12 5.53845C12.2549 5.53845 12.4615 5.74509 12.4615 5.99999V11.5385C12.4615 11.7934 12.2549 12 12 12C11.7451 12 11.5385 11.7934 11.5385 11.5385V5.99999C11.5385 5.74509 11.7451 5.53845 12 5.53845Z"
  240. fill="white"
  241. fill-opacity="0.9"
  242. />
  243. </svg>
  244. </el-tooltip>
  245. <!-- <el-button @click.stop="close()">退出绘画</el-button> -->
  246. </div>
  247. </el-col>
  248. </el-row>
  249. </div>
  250. </template>
  251. <script>
  252. // import html2canvas from "html2canvas";
  253. import "element-ui/lib/theme-chalk/index.css";
  254. export default {
  255. emits: ["close"],
  256. data() {
  257. return {
  258. show: false,
  259. showTool: false,
  260. canvas: null,
  261. ctx: null,
  262. brushColor: "#000000",
  263. brushSize: 5,
  264. mode: "draw",
  265. history: [],
  266. historyStep: -1,
  267. startX: 0,
  268. startY: 0,
  269. isDrawing: false,
  270. tempShape: null,
  271. tempCtx: null,
  272. openBrushColorBox: false,
  273. colorList: [
  274. "#000000",
  275. "#E2E1E5",
  276. "#FFFFFF",
  277. "#E11E1E",
  278. "#FA6402",
  279. "#F8B501",
  280. "#58C215",
  281. "#17CCA4",
  282. "#0290FB",
  283. "#6235FF",
  284. ],
  285. };
  286. },
  287. mounted() {
  288. // this.initCanvas();
  289. // this.open();
  290. },
  291. methods: {
  292. open() {
  293. this.show = true;
  294. this.showTool = true;
  295. this.mode = "draw";
  296. this.history = [];
  297. this.historyStep = -1;
  298. this.startX = 0;
  299. this.startY = 0;
  300. this.isDrawing = false;
  301. this.tempShape = null;
  302. this.tempCtx = null;
  303. this.$nextTick(() => {
  304. document.body.style.overflow = "hidden"; //禁止页面滚动
  305. this.initCanvas();
  306. });
  307. this.$emit("changeStatus", true);
  308. },
  309. close() {
  310. this.show = false;
  311. this.showTool = false;
  312. this.mode = "draw";
  313. this.history = [];
  314. this.historyStep = -1;
  315. this.startX = 0;
  316. this.startY = 0;
  317. this.isDrawing = false;
  318. this.tempShape = null;
  319. this.tempCtx = null;
  320. document.body.style.overflow = "auto"; //允许页面滚动
  321. this.$emit("changeStatus", false);
  322. this.$emit("close");
  323. },
  324. initCanvas() {
  325. this.canvas = this.$refs.canvas;
  326. this.ctx = this.canvas.getContext("2d");
  327. this.canvas.width = window.innerWidth;
  328. this.canvas.height = window.innerHeight;
  329. this.saveState();
  330. },
  331. setMode(mode) {
  332. this.mode = mode;
  333. },
  334. clearCanvas() {
  335. this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  336. this.saveState();
  337. },
  338. downloadCanvas() {
  339. return;
  340. const canvas = this.$refs.canvas;
  341. this.showTool = false;
  342. // console.log(window.scrollX)
  343. // console.log(window.scrollY)
  344. // console.log(window.innerWidth)
  345. // console.log(window.innerHeight)
  346. // console.log(window.document.documentElement.clientWidth)
  347. // console.log(window.document.documentElement.clientHeight)
  348. // return;
  349. this.$nextTick(() => {
  350. html2canvas(document.body, {
  351. x: window.scrollX,
  352. y: window.scrollY,
  353. width: window.innerWidth,
  354. height: window.innerHeight,
  355. windowWidth: document.documentElement.clientWidth,
  356. windowHeight: document.documentElement.clientHeight,
  357. scrollX: 0,
  358. scrollY: 0,
  359. }).then((capturedCanvas) => {
  360. const ctx = capturedCanvas.getContext("2d");
  361. ctx.drawImage(canvas, 0, 0);
  362. const link = document.createElement("a");
  363. link.href = capturedCanvas.toDataURL("image/png");
  364. link.download = "canvas-drawing.png";
  365. link.click();
  366. this.showTool = true;
  367. });
  368. });
  369. },
  370. undo() {
  371. if (this.historyStep > 0) {
  372. this.historyStep--;
  373. this.restoreState();
  374. }
  375. },
  376. redo() {
  377. if (this.historyStep < this.history.length - 1) {
  378. this.historyStep++;
  379. this.restoreState();
  380. }
  381. },
  382. saveState() {
  383. this.history = this.history.slice(0, this.historyStep + 1);
  384. this.history.push(this.canvas.toDataURL());
  385. this.historyStep++;
  386. },
  387. restoreState() {
  388. const img = new Image();
  389. img.src = this.history[this.historyStep];
  390. img.onload = () => {
  391. this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  392. this.ctx.drawImage(img, 0, 0);
  393. };
  394. },
  395. handleMouseDown(event) {
  396. if (this.mode === "erase" || this.mode === "draw") {
  397. this.ctx.strokeStyle =
  398. this.mode === "erase" ? "white" : this.brushColor;
  399. this.ctx.lineWidth = this.brushSize;
  400. this.ctx.lineCap = "round";
  401. this.ctx.lineJoin = "round";
  402. this.isDrawing = true;
  403. this.ctx.beginPath();
  404. const rect = this.canvas.getBoundingClientRect();
  405. this.startX = event.clientX - rect.left;
  406. this.startY = event.clientY - rect.top;
  407. this.ctx.moveTo(this.startX, this.startY);
  408. } else if (["line", "rect", "circle"].includes(this.mode)) {
  409. this.tempShape = document.createElement("canvas");
  410. this.tempShape.width = this.canvas.width;
  411. this.tempShape.height = this.canvas.height;
  412. this.tempCtx = this.tempShape.getContext("2d");
  413. this.tempCtx.strokeStyle = this.brushColor;
  414. this.tempCtx.lineWidth = this.brushSize;
  415. this.tempCtx.fillStyle = this.brushColor;
  416. this.isDrawing = true;
  417. const rect = this.canvas.getBoundingClientRect();
  418. this.startX = event.clientX - rect.left;
  419. this.startY = event.clientY - rect.top;
  420. }
  421. },
  422. handleMouseMove(event) {
  423. if (!this.isDrawing) return;
  424. const rect = this.canvas.getBoundingClientRect();
  425. const x = event.clientX - rect.left;
  426. const y = event.clientY - rect.top;
  427. // this.drawPreviewSize(x,y)
  428. if (this.mode === "draw") {
  429. this.ctx.lineTo(x, y);
  430. this.ctx.stroke();
  431. } else if (this.mode === "erase") {
  432. this.ctx.beginPath();
  433. this.ctx.clearRect(
  434. x - this.brushSize / 2,
  435. y - this.brushSize / 2,
  436. this.brushSize * 3,
  437. this.brushSize * 3
  438. );
  439. } else if (this.tempShape) {
  440. this.tempCtx.clearRect(
  441. 0,
  442. 0,
  443. this.tempShape.width,
  444. this.tempShape.height
  445. );
  446. if (this.mode === "line") {
  447. this.tempCtx.beginPath();
  448. this.tempCtx.moveTo(this.startX, this.startY);
  449. this.tempCtx.lineTo(x, y);
  450. this.tempCtx.stroke();
  451. } else if (this.mode === "rect") {
  452. this.tempCtx.strokeRect(
  453. this.startX,
  454. this.startY,
  455. x - this.startX,
  456. y - this.startY
  457. );
  458. } else if (this.mode === "circle") {
  459. const radius = Math.sqrt(
  460. Math.pow(x - this.startX, 2) + Math.pow(y - this.startY, 2)
  461. );
  462. this.tempCtx.beginPath();
  463. this.tempCtx.arc(this.startX, this.startY, radius, 0, Math.PI * 2);
  464. this.tempCtx.stroke();
  465. }
  466. this.ctx.drawImage(this.tempShape, 0, 0);
  467. // this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  468. this.restoreState();
  469. }
  470. },
  471. drawPreviewSize(x, y) {
  472. if (this.mode === "draw" || this.mode === "erase") {
  473. const previewSize = this.mode === "draw" ? this.brushSize : 20; // 设置橡皮擦的大小
  474. const previewColor = this.mode === "draw" ? this.brushColor : "#FFFFFF"; // 设置橡皮擦的颜色
  475. this.previewX = x;
  476. this.previewY = y;
  477. this.ctx.save();
  478. this.ctx.strokeStyle = previewColor;
  479. this.ctx.lineWidth = previewSize;
  480. this.ctx.beginPath();
  481. this.ctx.arc(x, y, previewSize / 2, 0, Math.PI * 2);
  482. this.ctx.stroke();
  483. this.ctx.restore();
  484. }
  485. },
  486. clearPreview() {
  487. this.ctx.clearRect(this.previewX - 12, this.previewY - 12, 25, 25); // 清除预览的区域
  488. },
  489. handleMouseUp() {
  490. if (!this.isDrawing) return;
  491. this.isDrawing = false;
  492. this.ctx.closePath();
  493. if (this.tempShape) {
  494. this.ctx.drawImage(this.tempShape, 0, 0);
  495. this.tempShape = null;
  496. this.tempCtx = null;
  497. }
  498. this.saveState();
  499. },
  500. handleTouchStart(event) {
  501. event.preventDefault();
  502. const touch = event.touches[0];
  503. this.handleMouseDown({
  504. clientX: touch.clientX,
  505. clientY: touch.clientY,
  506. });
  507. },
  508. handleTouchMove(event) {
  509. event.preventDefault();
  510. const touch = event.touches[0];
  511. this.handleMouseMove({
  512. clientX: touch.clientX,
  513. clientY: touch.clientY,
  514. });
  515. },
  516. handleTouchEnd(event) {
  517. event.preventDefault();
  518. this.handleMouseUp();
  519. },
  520. setColor(newColor) {
  521. this.brushColor = newColor;
  522. this.openBrushColorBox = false;
  523. this.setMode("draw");
  524. },
  525. changeOpenBrushColorBox(newValue) {
  526. this.openBrushColorBox = newValue;
  527. },
  528. },
  529. watch: {
  530. brushColor(newColor) {
  531. this.ctx.strokeStyle = newColor;
  532. },
  533. brushSize(newSize) {
  534. this.ctx.lineWidth = newSize;
  535. },
  536. },
  537. };
  538. </script>
  539. <style scoped>
  540. .drawing-canvas {
  541. position: fixed;
  542. top: 0;
  543. left: 0;
  544. width: 100vw;
  545. height: 100vh;
  546. background-color: rgba(255, 255, 255, 0);
  547. }
  548. .toolbar {
  549. position: fixed;
  550. bottom: 0;
  551. left: 50%;
  552. width: auto;
  553. background: #ffffff;
  554. color: white;
  555. padding: 10px;
  556. bottom: 3vh;
  557. border-radius: 8px 8px 0 0;
  558. box-shadow: 0px 8px 10px -5px #00000014;
  559. box-shadow: 0px 16px 24px 2px #0000000a;
  560. box-shadow: 0px 6px 30px 5px #0000000d;
  561. transform: translateX(-50%);
  562. max-width: 100vw;
  563. }
  564. .toolbar-container {
  565. display: flex;
  566. justify-content: space-around;
  567. align-items: center;
  568. }
  569. .toolbar-container > div {
  570. margin: 0 20px;
  571. width: auto;
  572. height: auto;
  573. display: flex;
  574. justify-content: center;
  575. align-items: center;
  576. }
  577. .el-button.active {
  578. background-color: #409eff;
  579. color: white;
  580. }
  581. .closeBtn > svg {
  582. width: 45px;
  583. height: 45px;
  584. cursor: pointer;
  585. }
  586. .cancelBtn > svg {
  587. width: 40px;
  588. height: 40px;
  589. cursor: pointer;
  590. }
  591. .clearScreenBtn > svg {
  592. width: 40px;
  593. height: 40px;
  594. cursor: pointer;
  595. }
  596. .eraserBtn > svg {
  597. width: 40px;
  598. height: 40px;
  599. cursor: pointer;
  600. }
  601. .brushBtn > svg {
  602. width: 35px;
  603. height: 35px;
  604. cursor: pointer;
  605. border-radius: 8px;
  606. box-sizing: border-box;
  607. padding: 2px;
  608. }
  609. .brushBtn_colorBox {
  610. width: 250px;
  611. height: auto;
  612. background-color: #ffffff;
  613. position: absolute;
  614. bottom: 0;
  615. margin-bottom: 70px;
  616. padding: 4px, 8px, 4px, 8px;
  617. box-shadow: 0px 4px 10px 0px #1d398314;
  618. box-shadow: 1px 1px 20px 4px #1d39830d;
  619. left: 0;
  620. border-radius: 6px;
  621. display: flex;
  622. align-items: center;
  623. justify-content: center;
  624. flex-wrap: wrap;
  625. }
  626. .brushBtn_colorBox > span {
  627. width: 25px;
  628. height: 25px;
  629. border-radius: 100%;
  630. cursor: pointer;
  631. margin: 10px;
  632. box-sizing: border-box;
  633. }
  634. .selectBox {
  635. /* width: 30px;
  636. height: 30px; */
  637. display: flex !important;
  638. justify-content: center;
  639. align-items: center;
  640. padding: 5px !important;
  641. margin-left: 5px;
  642. }
  643. </style>