index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <template>
  2. <div id="container" ref="container"></div>
  3. </template>
  4. <script>
  5. import Konva from "konva";
  6. import {selectIsIsolationPointById} from "@/api/mes/spm/segregationPoint"
  7. export default {
  8. name: "KonvaExample",
  9. props: {
  10. points: {
  11. type: Object,
  12. default: null
  13. }
  14. },
  15. data() {
  16. return {
  17. stage: null,
  18. layer: null,
  19. selectedStates: [], // 用于存储每个元素的选中状态
  20. selectedText: [], // 用于存储未选中的元素文本
  21. rects:[],//白色rect合集
  22. texts:[],//白色text合集
  23. redrects:[],//红色rect合集
  24. redtexts:[],//白色text合集
  25. };
  26. },
  27. mounted() {
  28. this.initKonva();
  29. },
  30. methods: {
  31. initKonva() {
  32. // 创建舞台
  33. this.stage = new Konva.Stage({
  34. container: this.$refs.container, // 容器元素
  35. width: 1270,
  36. height: 830,
  37. });
  38. // 创建图层
  39. this.layer = new Konva.Layer();
  40. // 创建底图
  41. const bgImage = new Image();
  42. bgImage.src = require("@/assets/images/table.png");
  43. bgImage.onload = () => {
  44. const knovaImage = new Konva.Image({
  45. x: 330,
  46. y: 10,
  47. image: bgImage,
  48. width: 500,
  49. height: 790,
  50. draggable: false,
  51. });
  52. this.layer.add(knovaImage);
  53. this.layer.draw();
  54. };
  55. // 绘制无限网格
  56. this.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
  57. // 渲染数据
  58. const imageSrc = require("@/assets/images/localSetIcon.jpg"); // 图片路径
  59. this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25);
  60. // 将图层添加到舞台
  61. this.stage.add(this.layer);
  62. this.layer.draw();
  63. // 禁止舞台拖拽
  64. this.stage.draggable(false);
  65. },
  66. // 绘制无限网格
  67. drawGrid(cellWidth, cellHeight, gridColor) {
  68. const width = 1270;
  69. const height = 830;
  70. // 绘制竖线
  71. for (let i = 0; i <= width; i += cellWidth) {
  72. const verticalLine = new Konva.Line({
  73. points: [i, 0, i, height],
  74. stroke: gridColor,
  75. strokeWidth: 1,
  76. });
  77. this.layer.add(verticalLine);
  78. }
  79. // 绘制横线
  80. for (let j = 0; j <= height; j += cellHeight) {
  81. const horizontalLine = new Konva.Line({
  82. points: [0, j, width, j],
  83. stroke: gridColor,
  84. strokeWidth: 1,
  85. });
  86. this.layer.add(horizontalLine);
  87. }
  88. this.layer.draw();
  89. },
  90. renderGrid(imageSrc) {
  91. this.selectedStates = {}; // 用对象来存储选中状态,键为文字内容
  92. this.rects = {};
  93. this.texts = {};
  94. this.redrects = {};
  95. this.redtexts = {};
  96. this.selectedText = [];
  97. const positions=JSON.parse(this.points.map)
  98. console.log(positions,'this.points')
  99. // const positions = [
  100. // { row: 2, col: 9 },
  101. // { row: 2, col: 11 },
  102. // { row: 2, col: 13 },
  103. // { row: 4, col: 9 },
  104. // { row: 4, col: 11 },
  105. // { row: 4, col: 13 },
  106. // { row: 6, col: 9 },
  107. // { row: 6, col: 11 },
  108. // { row: 6, col: 13 },
  109. // { row: 8, col: 9 },
  110. // { row: 8, col: 11 },
  111. // { row: 8, col: 13 },
  112. // { row: 10, col: 9 },
  113. // { row: 10, col: 11 },
  114. // { row: 10, col: 13 },
  115. // { row: 12, col: 9 },
  116. // { row: 12, col: 11 },
  117. // { row: 12, col: 13 },
  118. // ];
  119. // const positionsJson = JSON.stringify(positions);
  120. // console.log(positionsJson,'json');
  121. positions.forEach((pos, index) => {
  122. const x = pos.col * 50; // 每个单元格宽度为50
  123. const y = pos.row * 50; // 每个单元格高度为50
  124. const labelText = pos.pointName; // 对应的文字
  125. const point = new Image();
  126. point.src = imageSrc;
  127. point.onload = () => {
  128. const knovaImage = new Konva.Image({
  129. x: x,
  130. y: y,
  131. image: point,
  132. width: 50,
  133. height: 50,
  134. draggable: false,
  135. });
  136. knovaImage.on("click", () => {
  137. // 切换选中状态,基于文本内容
  138. this.selectedStates[labelText] = !this.selectedStates[labelText];
  139. // 判断当前是否选中
  140. if (this.selectedStates[labelText]) {
  141. // 选中状态
  142. // 显示红色矩形和文字,隐藏普通矩形和文字
  143. this.rects[labelText].visible(false);
  144. this.texts[labelText].visible(false);
  145. this.redrects[labelText].visible(true);
  146. this.redtexts[labelText].visible(true);
  147. // 切换图片为选中状态的图片
  148. const selectedImage = new Image();
  149. selectedImage.src = require('@/assets/images/localSetSelect.jpg'); // 选中的图片路径
  150. selectedImage.onload = () => {
  151. knovaImage.image(selectedImage); // 更新图像
  152. this.layer.draw(); // 更新图层
  153. };
  154. this.$nextTick(()=>{
  155. selectIsIsolationPointById(pos.pointId).then((res)=>{
  156. console.log(res,'拿到的隔离点信息');
  157. //将选中的 labelText 推入数组
  158. this.selectedText.push({
  159. pointName: res.data.pointName,
  160. pointId: res.data.pointId,
  161. pointType: res.data.pointType,
  162. powerType: res.data.powerType,
  163. });
  164. // this.selectedText.push({
  165. // label: labelText,
  166. // value: pos.pointId,
  167. // });
  168. this.$emit("selection-changed", this.selectedText);
  169. })
  170. })
  171. } else {
  172. // 取消选中状态
  173. // 显示普通矩形和文字,隐藏红色矩形和文字
  174. this.rects[labelText].visible(true);
  175. this.texts[labelText].visible(true);
  176. this.redrects[labelText].visible(false);
  177. this.redtexts[labelText].visible(false);
  178. // 切换图片为未选中状态的图片
  179. const normalImage = new Image();
  180. normalImage.src = imageSrc; // 未选中的默认图片路径
  181. normalImage.onload = () => {
  182. knovaImage.image(normalImage); // 更新图像
  183. this.layer.draw(); // 更新图层
  184. };
  185. // 从选中数组中移除该项
  186. this.selectedText = this.selectedText.filter(
  187. (item) => item.pointName !== labelText
  188. );
  189. }
  190. // 最后确保图层重新渲染
  191. this.layer.draw();
  192. // 传递选中的元素文本到父组件
  193. this.$emit("selection-changed", this.selectedText);
  194. });
  195. this.layer.add(knovaImage);
  196. // 普通矩形
  197. const rect = new Konva.Rect({
  198. x: x - 3,
  199. y: y + 55,
  200. width: 60,
  201. height: 25,
  202. cornerRadius: 10,
  203. stroke: "red",
  204. strokeWidth: 2,
  205. fill: "white",
  206. });
  207. this.layer.add(rect);
  208. this.rects[labelText] = rect; // 用文字作为键存储
  209. // 普通文字
  210. const text = new Konva.Text({
  211. x: x + 12,
  212. y: y + 60,
  213. fontSize: 20,
  214. text: labelText,
  215. fontFamily: "Calibri",
  216. fill: "red",
  217. });
  218. this.layer.add(text);
  219. this.texts[labelText] = text; // 用文字作为键存储
  220. // 红色矩形(初始隐藏)
  221. const redrect = new Konva.Rect({
  222. x: x - 3,
  223. y: y + 55,
  224. width: 60,
  225. height: 25,
  226. cornerRadius: 10,
  227. stroke: "red",
  228. strokeWidth: 2,
  229. fill: "red",
  230. visible: false,
  231. });
  232. this.layer.add(redrect);
  233. this.redrects[labelText] = redrect; // 用文字作为键存储
  234. // 红色文字(初始隐藏)
  235. const redtext = new Konva.Text({
  236. x: x + 12,
  237. y: y + 60,
  238. fontSize: 20,
  239. text: labelText,
  240. fontFamily: "Calibri",
  241. fill: "white",
  242. visible: false,
  243. });
  244. this.layer.add(redtext);
  245. this.redtexts[labelText] = redtext; // 用文字作为键存储
  246. this.layer.draw();
  247. };
  248. });
  249. },
  250. // methods结束
  251. },
  252. };
  253. </script>
  254. <style scoped lang="scss">
  255. #container {
  256. width: 100%;
  257. height: 100%;
  258. }
  259. </style>