| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- <template>
- <div id="container" ref="container"></div>
- </template>
- <script>
- import Konva from 'konva'
- import {
- selectIsIsolationPointById,
- getIsIsolationPointPage
- } from '@/api/mes/spm/segregationPoint'
- import { mapGetters } from 'vuex'
- export default {
- name: 'KonvaExample',
- props: {
- points: {
- type: Object,
- default: null
- }
- },
- data() {
- return {
- stage: null,
- layer: null,
- selectedStates: [], // 用于存储每个元素的选中状态
- selectedText: [], // 用于存储未选中的元素文本
- rects: [], //白色rect合集
- texts: [], //白色text合集
- bgrects:[],//白色底部
- redrects: [], //红色rect合集
- redtexts: [], //白色text合集
- }
- },
- watch: {
- 'getMapData': {
- handler(newval) {
- if (newval) {
- this.$nextTick(()=>{
- this.initKonva()
- })
- }
- }
- },
- },
- created() {
- this.initKonva()
- },
- mounted() {
- // this.initKonva() //暂时先注释掉这里 为了避免多次重复渲染
- console.log(this.points, 'points')
- console.log(
- this.getSelectSopPoints,
- this.getSopEdit,
- this.getSopLook,
- 'getSopEdit - getSelectSopPoints'
- )
- },
- computed: {
- ...mapGetters('sopSelectPoints', [
- 'getSelectSopPoints',
- 'getSopEdit',
- 'getSopLook',
- 'getMapData'
- ])
- },
- methods: {
- initKonva() {
- // 创建舞台
- this.stage = new Konva.Stage({
- container: this.$refs.container, // 容器元素
- width: 1270,
- height: 830
- })
- // 创建图层
- this.layer = new Konva.Layer()
- // 创建底图
- const bgImage = new Image()
- bgImage.src = require('@/assets/images/table.png')
- bgImage.onload = () => {
- const knovaImage = new Konva.Image({
- x: 330,
- y: 10,
- image: bgImage,
- width: 500,
- height: 790,
- draggable: false
- })
- this.layer.add(knovaImage)
- this.layer.draw()
- }
- // 绘制无限网格
- this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
- // 渲染数据
- const imageSrc = require('@/assets/images/localSetIcon.jpg') // 图片路径
- this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25)
- // 将图层添加到舞台
- this.stage.add(this.layer)
- this.layer.draw()
- // 禁止舞台拖拽
- this.stage.draggable(false)
- },
- // 绘制无限网格
- drawGrid(cellWidth, cellHeight, gridColor) {
- const width = 1270
- const height = 830
- // 绘制竖线
- for (let i = 0; i <= width; i += cellWidth) {
- const verticalLine = new Konva.Line({
- points: [i, 0, i, height],
- stroke: gridColor,
- strokeWidth: 1
- })
- this.layer.add(verticalLine)
- }
- // 绘制横线
- for (let j = 0; j <= height; j += cellHeight) {
- const horizontalLine = new Konva.Line({
- points: [0, j, width, j],
- stroke: gridColor,
- strokeWidth: 1
- })
- this.layer.add(horizontalLine)
- }
- this.layer.draw()
- },
- renderGrid(imageSrc) {
- this.selectedStates = {} // 用对象来存储选中状态,键为文字内容
- this.rects = {}
- this.texts = {}
- this.bgrects={}
- this.redrects = {}
- this.redtexts = {}
- this.selectedText = []
- // const positions = JSON.parse(this.points.map);
- console.log(this.getMapData,',apData')
- let positions;
- // 判断getMapData是否已为数组
- if (Array.isArray(this.getMapData)) {
- // 如果是数组,则直接使用
- positions = this.getMapData;
- } else {
- // 如果不是数组,则尝试将其从JSON字符串转换为数组或其他对象
- try {
- positions = JSON.parse(this.getMapData);
- } catch (e) {
- console.error("Error parsing getMapData:", e);
- // 可以在这里处理错误情况,例如将positions设置为空数组等
- positions = [];
- }
- }
- // 检查 this.getSelectSopPoints 是否有内容
- const isLocked = this.getSelectSopPoints.length > 0
- // 添加或移除全局点击事件监听器 this.getSopEdit这是vuex里判断是否可以选择隔离点的操作
- if (isLocked && this.getSopEdit == true) {
- this.layer.on('click', (e) => {
- e.cancelBubble = true // 阻止事件冒泡
- // e.stopPropagation(); // 阻止事件传播
- })
- } else {
- this.layer.off('click') // 移除全局点击事件监听器
- }
- positions.forEach((pos, index) => {
- const x = pos.col * 50 // 每个单元格宽度为50
- const y = pos.row * 50 // 每个单元格高度为50
- const labelText = pos.pointName // 对应的文字
- const point = new Image()
- point.src = pos.pointIcon
- // point.src = imageSrc;
- point.onload = () => {
- const knovaImage = new Konva.Image({
- x: x,
- y: y,
- image: point,
- width: 50,
- height: 50,
- draggable: false
- })
- // 添加点击事件,仅当 getSopEdit 为 true 时才允许点击a
- if (this.getSopEdit == true && this.getSopLook == false) {
- knovaImage.on('click', () => {
- // 切换选中状态,基于文本内容
- this.selectedStates[labelText] = !this.selectedStates[labelText]
- if (this.selectedStates[labelText]) {
- // 选中状态,显示红色矩形和文字,切换为选中的图片
- this.rects[labelText].visible(true)
- this.texts[labelText].visible(true)
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- const selectedImage = new Image()
- selectedImage.src = pos.pointIcon
- selectedImage.onload = () => {
- knovaImage.image(selectedImage) // 更新图像
- this.layer.draw() // 更新图层
- }
- // 获取隔离点信息,并将选中的 labelText 推入数组
- this.$nextTick(() => {
- if (
- this.$route.query.sopId !== null ||
- this.$route.query.ticketId !== null
- ) {
- this.selectedText.push({
- pointName: pos.pointName,
- pointId: pos.pointId,
- pointType: pos.pointTypeName,
- powerType: pos.powerTypeName,
- prePointId:pos.prePointId
- })
- this.$emit('selection-changed', this.selectedText)
- }
- })
- } else {
- // 取消选中状态,恢复普通矩形和文字,切换为未选中的图片
- this.rects[labelText].visible(true)
- this.texts[labelText].visible(true)
- this.redrects[labelText].visible(false)
- this.redtexts[labelText].visible(false)
- const normalImage = new Image()
- normalImage.src = pos.pointIcon
- // normalImage.src = imageSrc; // 未选中的默认图片路径
- normalImage.onload = () => {
- knovaImage.image(normalImage) // 更新图像
- this.layer.draw() // 更新图层
- }
- // 从选中数组中移除该项
- this.selectedText = this.selectedText.filter(
- (item) => item.pointName !== labelText
- )
- }
- // 确保图层重新渲染
- this.layer.draw()
- this.$emit('selection-changed', this.selectedText)
- })
- }
- // 底部白色背景
- const bgrect=new Konva.Rect({
- x: x - 6,
- y: y - 5,
- width: 62,
- height: 80,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- this.layer.add(bgrect)
- this.bgrects[labelText] = bgrect // 用文字作为键存储
- // 普通矩形
- const rect = new Konva.Rect({
- x: x + 0,
- y: y - 1,
- width: 50,
- height: 72,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white'
- })
- this.layer.add(rect)
- this.rects[labelText] = rect // 用文字作为键存储
- // 先加底部白色 再添加图片
- this.layer.add(knovaImage)
- // // 普通矩形
- // const rect = new Konva.Rect({
- // x: x ,
- // y: y + 45,
- // width: 50,
- // height: 25,
- // cornerRadius: 0,
- // stroke: 'red',
- // strokeWidth: 2,
- // fill: 'white'
- // })
- // this.layer.add(rect)
- // this.rects[labelText] = rect // 用文字作为键存储
- //
- // // 普通文字
- // const text = new Konva.Text({
- // x: x + 8,
- // y: y + 50,
- // fontSize: 20,
- // text: labelText,
- // fontFamily: 'Calibri',
- // fill: 'red'
- // })
- // this.layer.add(text)
- // this.texts[labelText] = text // 用文字作为键存储
- // // 红色矩形(初始隐藏)
- // const redrect = new Konva.Rect({
- // x: x - 3,
- // y: y + 55,
- // width: 60,
- // height: 25,
- // cornerRadius: 10,
- // stroke: 'red',
- // strokeWidth: 2,
- // fill: 'red',
- // visible: false
- // })
- // this.layer.add(redrect)
- // this.redrects[labelText] = redrect // 用文字作为键存储
- //
- // // 红色文字(初始隐藏)
- // const redtext = new Konva.Text({
- // x: x + 12,
- // y: y + 60,
- // fontSize: 20,
- // text: labelText,
- // fontFamily: 'Calibri',
- // fill: 'white',
- // visible: false
- // })
- // this.layer.add(redtext)
- // this.redtexts[labelText] = redtext // 用文字作为键存储
- // 普通文字
- const text = new Konva.Text({
- x: x + 8,
- y: y + 50,
- fontSize: 20,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- this.layer.add(text)
- this.texts[labelText] = text // 用文字作为键存储
- // 覆盖层(表示选中状态)
- const redrect = new Konva.Rect({
- x: x - 7,
- y: y - 6,
- width: 64.1,
- height: 82,
- cornerRadius: 5,
- fill: 'rgba(97, 97, 97, 0.5)', // 半透明灰色
- visible: false, // 初始状态隐藏
- listening:false
- });
- this.layer.add(redrect)
- this.redrects[labelText] = redrect // 用文字作为键存储
- // 创建对号文本
- const redtext = new Konva.Text({
- x: x - 5 + 42 / 2, // 水平居中
- y: y + 62 / 2, // 垂直居中
- fontSize: 24, // 根据需要调整字体大小
- text: '✔',
- fontFamily: 'Arial',
- fill: 'white',
- align: 'center',
- verticalAlign: 'middle',
- visible: false,//初始隐藏状态
- listening:false,
- });
- this.layer.add(redtext);
- this.redtexts[labelText] = redtext; // 用文字作为键存储
- // 检查 this.getSelectSopPoints 是否包含当前点的 pointId
- if (pos.state) {
- console.log('我走这里了-------')
- // 设置为选中状态
- this.selectedStates[labelText] = true
- this.rects[labelText].visible(true)
- this.texts[labelText].visible(true)
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- // 切换图片为选中状态的图片
- const selectedImage = new Image()
- selectedImage.src = pos.pointIcon // 选中的图片路径
- selectedImage.onload = () => {
- knovaImage.image(selectedImage) // 更新图像
- this.layer.draw() // 更新图层
- }
- // 将选中的 labelText 推入数组
- this.selectedText.push({
- pointName: pos.pointName,
- pointId: pos.pointId,
- pointType: pos.pointTypeName,
- powerType: pos.powerTypeName,
- prePointId:pos.prePointId
- })
- } else {
- // 设置为未选中状态
- this.selectedStates[labelText] = false
- this.rects[labelText].visible(true)
- this.texts[labelText].visible(true)
- this.redrects[labelText].visible(false)
- this.redtexts[labelText].visible(false)
- }
- // 触发父组件的 selection-changed 事件
- this.$emit('selection-changed', this.selectedText)
- this.layer.draw()
- }
- })
- }
- // methods结束
- }
- }
- </script>
- <style scoped lang="scss">
- #container {
- width: 100%;
- height: 100%;
- }
- </style>
|