欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue使用canvas畫布實(shí)現(xiàn)平面圖點(diǎn)位標(biāo)注功能(最新推薦)

 更新時(shí)間:2023年07月28日 15:13:56   作者:-風(fēng)過(guò)無(wú)痕  
這篇文章主要介紹了vue使用canvas畫布實(shí)現(xiàn)平面圖點(diǎn)位標(biāo)注功能,經(jīng)過(guò)本文一番研究發(fā)現(xiàn)canvas標(biāo)簽可以完成很多功能,電子簽名,點(diǎn)位標(biāo)注,問(wèn)題標(biāo)注,畫圖功能,感興趣的朋友跟隨小編一起看看吧

前言

  • 最近需要一個(gè)在平面圖標(biāo)注點(diǎn)位功能,去搜了一圈,發(fā)現(xiàn)......,最后在查閱文檔一頓操作之后。
  • 不停修改bug之后,做出一版可以基本使用的版本。
  • 最后發(fā)現(xiàn)canvas標(biāo)簽可以完成很多功能,電子簽名,點(diǎn)位標(biāo)注,問(wèn)題標(biāo)注,畫圖功能等等

效果

功能難點(diǎn)

畫布渲染問(wèn)題-基于canvas提供的渲染方法封裝渲染方法,x,y坐標(biāo),width,height高,url圖片

移動(dòng)距離問(wèn)題-我們需要借助鼠標(biāo)點(diǎn)擊,移動(dòng),彈起來(lái)事件計(jì)算移動(dòng)的距離,來(lái)更改x,y坐標(biāo)

選中圖標(biāo)問(wèn)題-當(dāng)我們畫布上有多個(gè)圖標(biāo)時(shí)通過(guò)x,y,加上width,height和點(diǎn)擊時(shí)x,y坐標(biāo)判斷是那個(gè)圖標(biāo)在被點(diǎn)擊,在數(shù)組中找到匹配返回下標(biāo),反之就是點(diǎn)擊背景圖

畫布渲染問(wèn)題-生成畫布之后,為了讓用戶無(wú)感操作,最好以幀方式刷新畫布(定時(shí)器方式)

圖標(biāo)數(shù)據(jù)格式-畫布上圖標(biāo)有很多個(gè)圖標(biāo),改變一個(gè)同時(shí),其他也是要跟著渲染

設(shè)備信息問(wèn)題-我們需要在畫布上點(diǎn)擊獲取到圖標(biāo)的下標(biāo)之后,把x,y傳遞給信息框,顯示

自己理解

現(xiàn)在這個(gè)版本僅僅相當(dāng)于是一個(gè)例子,但是也是費(fèi)了不少時(shí)間和bug才艱辛完成的

為什么說(shuō)是例子,可能還會(huì)有bug,適配,api交互,放大,存儲(chǔ)問(wèn)題等等。

代碼實(shí)現(xiàn)-可以直接復(fù)制

<template>
  <div class="app-container">
    <!-- 側(cè)邊欄 -->
    <el-row :gutter="20">
      <!-- 樹結(jié)構(gòu) -->
      <el-col :xs="24" :sm="4" :lg="4">
        <div class="grid-left">
          <!-- 篩選框 -->
          <el-input
            class="searchinput"
            placeholder="請(qǐng)搜索樓層"
            suffix-icon="el-input__icon el-icon-search"
            v-model="treeinput"
            clearable
            size="small"
          ></el-input>
          <!-- 樹結(jié)構(gòu) -->
          <el-tree
            :data="treedata"
            :props="defaultProps"
            @node-click="handleNodeClick"
            ref="menuTree"
            node-key="id"
            default-expand-all
            :filter-node-method="filterNode"
          ></el-tree>
        </div>
      </el-col>
      <!-- 點(diǎn)位模塊 -->
      <el-col :xs="24" :sm="15" :lg="15">
        <div class="grid-right">
          <!-- 點(diǎn)位標(biāo)題 -->
          <div class="grid-top"></div>
          <!-- 圖片展示 -->
          <img class="bigImg" :src="backpicture" v-if="backpicture" />
          <!-- 生成畫布模塊 -->
          <div class="canvas-box" v-show="this.canvasinit">
            <!-- 表頭 -->
            <div class="canvas-title">
              <div class="zuo">
                請(qǐng)拖動(dòng)圖標(biāo)到安裝位置-<i>廠家平面圖 平面圖</i>
              </div>
            </div>
            <!-- 畫布 -->
            <canvas
              ref="canvas"
              width="970"
              height="500"
              @mousedown="canvasMouseDown"
              @mousemove="canvasMouseMove"
              @mouseup="canvasMouseUp"
            ></canvas>
          </div>
          <!-- 保存平面圖 -->
          <div class="bottom" v-if="!this.canvasinit">
            <el-button type="primary" @click="save">保存</el-button>
          </div>
          <!-- 圖標(biāo)提示信息 -->
          <el-popover
            placement="top"
            id="popovercan"
            width="200"
            v-model="canvasvisible"
          >
            <div class="popover-top">
              <i>傳感器設(shè)備</i>
            </div>
            <p>序列號(hào):sjhdkjshkj</p>
            <p>設(shè)備類型:是給大家灰色軌跡</p>
            <p></p>
          </el-popover>
        </div>
      </el-col>
      <!-- 設(shè)備信息 -->
      <el-col :xs="24" :sm="5" :lg="5">
        <div class="grid-table">
          <!-- 標(biāo)題 -->
          <div class="grid-top">
            <i></i>
            <p>配置資源點(diǎn)-點(diǎn)擊圖標(biāo)加載到畫布中</p>
          </div>
          <!-- 表格數(shù)據(jù) -->
          <div class="newtable">
            <div
              class="new-item"
              v-for="item in tableData"
              :key="item.id"
              @click="handleClick(item)"
            >
              <img :src="item.img" alt="" />
              <div class="newconter">
                <p>序列號(hào)碼:{{ item.phone }}</p>
                <p>設(shè)備類型:{{ item.newtype }}</p>
                <p>詳細(xì)位置:{{ item.sys }}</p>
              </div>
            </div>
          </div>
          <div class="pagination">
            <el-pagination
              small
              :page-size="pageInfo.pageSize"
              layout="prev, pager, next"
              :total="pageInfo.total"
            >
            </el-pagination>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
?
<script>
export default {
  name: "Ceshi",
  watch: {
    treeinput(val) {
      this.$refs.menuTree.filter(val);
    },
  },
  data() {
    return {
      // 樹結(jié)構(gòu)篩選框
      treeinput: "",
      // 樹結(jié)構(gòu)數(shù)據(jù)
      treedata: [
        {
          id: 1,
          name: "中國(guó)",
          children: [
            {
              id: 1,
              name: "廣東",
              children: [
                {
                  id: 4,
                  name: "惠州",
                },
                {
                  id: 5,
                  name: "深圳",
                },
                {
                  id: 6,
                  name: "廣州",
                },
              ],
            },
            {
              id: 2,
              name: "湖北",
              children: [
                {
                  id: 7,
                  name: "武漢",
                },
              ],
            },
            {
              id: 3,
              name: "北京",
            },
          ],
        },
      ],
      // 樹結(jié)構(gòu)配置
      // 樹形數(shù)據(jù)分析
      defaultProps: {
        id: "id",
        label: "name",
        children: "children",
      },
      // 獲取canvas標(biāo)簽
      canvas: null,
      // 創(chuàng)建畫布
      ctx: null,
      // 畫布大小
      canvasWidth: 970,
      canvasHeight: 500,
      //定時(shí)器
      intervalId: null,
      //判斷鼠標(biāo)是否點(diǎn)擊
      isClick: false,
      //記錄需要移動(dòng)的圖片的開光
      index: -1,
      frameNumber: 20,
      sensorImgList: [],
      backgroundImg: {
        url: "https://img2.baidu.com/it/u=2832413337,2216208892&fm=253&fmt=auto&app=138&f=JPEG?w=544&h=500",
        x: 0,
        y: 0,
        width: 970,
        height: 500,
      },
      canvasSensorImg: [
        {
          channelId: 12,
          height: 46,
          url: "https://img2.baidu.com/it/u=3823882177,3352315913&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
          width: 46,
          x: 247,
          y: 233,
        },
        {
          channelId: 13,
          height: 46,
          url: "https://img2.baidu.com/it/u=3823882177,3352315913&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
          width: 46,
          x: 400,
          y: 400,
        },
      ],
      tableData: [
        {
          id: 1,
          img: "https://img2.baidu.com/it/u=3823882177,3352315913&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
          phone: "865566043823044",
          newtype: "NP-FDY100-N",
          sys: "中國(guó)北京市北京人名大會(huì)堂側(cè)門旁邊",
        },
      ],
      // 圖標(biāo)數(shù)據(jù)
      Icondata:
        "https://img2.baidu.com/it/u=3823882177,3352315913&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
      // 背景圖圖片
      backpicture:
        "https://img2.baidu.com/it/u=2832413337,2216208892&fm=253&fmt=auto&app=138&f=JPEG?w=544&h=500",
      // 畫布開關(guān)
      canvasinit: false,
      // 設(shè)備抱緊查詢
      pageInfo: {
        // 總條數(shù)
        total: 17,
        // 當(dāng)前頁(yè)
        pageNo: 1,
        // 每頁(yè)條數(shù)
        pageSize: 10,
      },
      clickicon: {},
      canvasvisible: false,
    };
  },
  created() {},
  methods: {
    // 樹結(jié)構(gòu)點(diǎn)擊事件
    handleNodeClick(data) {
      if (data.children.length !== 0) {
        return;
      }
      console.log("樹形結(jié)構(gòu)", data);
      console.log(data.id);
      // 樓層id
      this.page.floorId = data.id;
    },
    // 樹節(jié)點(diǎn)搜索
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    // 確認(rèn)保存按鈕
    save() {
      this.canvasinit = true;
      this.init();
    },
    // 創(chuàng)建畫布
    init() {
      // 找到畫布標(biāo)簽
      this.canvas = this.$refs.canvas;
      this.ctx = this.canvas.getContext("2d");
      // 創(chuàng)建背景,圖標(biāo),移動(dòng)圖標(biāo)
      this.loadBgImg();
      // 刷新畫布
      this.dataRefreh();
    },
    loadBgImg() {
      let img = new Image();
      let bgImg = this.backgroundImg;
      img.src = bgImg.url;
      img.onload = () => {
        this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
        this.ctx.drawImage(img, bgImg.x, bgImg.y, bgImg.width, bgImg.height);
        this.drawCanvasSensorImg();
        this.loadSensorImg();
      };
    },
    //加載圖標(biāo)
    loadSensorImg() {
      let imgList = [];
      for (let i = 0; i < this.sensorImgList.length; i++) {
        let img = new Image();
        let sensorImg = this.sensorImgList[i];
        img.src = sensorImg.url;
        let imgs = {};
        imgs.img = img;
        imgs.x = sensorImg.x;
        imgs.y = sensorImg.y;
        imgs.width = sensorImg.width;
        imgs.height = sensorImg.height;
        // console.log(imgs)
        imgList.push(imgs);
      }
      this.drawImg(imgList);
    },
    //繪制圖片方法
    drawImg(imgList) {
      for (let i = 0; i < imgList.length; i++) {
        this.ctx.drawImage(
          imgList[i].img,
          imgList[i].x,
          imgList[i].y,
          imgList[i].width,
          imgList[i].height
        );
      }
    },
    // 繪制移動(dòng)的圖片
    drawCanvasSensorImg() {
      let imgList = [];
      for (let i = 0; i < this.canvasSensorImg.length; i++) {
        let img = new Image();
        let sensorImg = this.canvasSensorImg[i];
        img.src = sensorImg.url;
        let imgs = {};
        imgs.img = img;
        imgs.x = sensorImg.x;
        imgs.y = sensorImg.y;
        imgs.width = sensorImg.width;
        imgs.height = sensorImg.height;
        imgList.push(imgs);
      }
      this.drawImg(imgList);
    },
    //判斷鼠標(biāo)是否在圖標(biāo)范圍內(nèi),并返回下標(biāo)
    isMouseInIcon(e, imgList) {
      let x = e.offsetX;
      let y = e.offsetY;
      for (let i = 0; i < imgList.length; i++) {
        let imgX = imgList[i].x;
        let imgY = imgList[i].y;
        let imgWidth = imgList[i].width;
        let imgHeight = imgList[i].height;
        if (
          x > imgX &&
          x < imgX + imgWidth &&
          y > imgY &&
          y < imgY + imgHeight
        ) {
          return i;
        }
      }
      return -1;
    },
    // 定時(shí)器刷新畫布
    dataRefreh() {
      if (this.intervalId != null) {
        return;
      }
      this.intervalId = setInterval(() => {
        this.loadBgImg();
      }, this.frameNumber);
    },
    //鼠標(biāo)點(diǎn)擊觸發(fā)事件
    canvasMouseDown(e) {
      console.log("鼠標(biāo)點(diǎn)擊", e);
      this.isClick = true;
      this.index = this.isMouseInIcon(e, this.canvasSensorImg);
?
      if (this.index == -1) {
        console.log("沒選中");
        return;
      }
      this.$nextTick(() => {
        console.log("top");
        const canpro = document.getElementById("popovercan");
        canpro.style.position = "absolute";
        canpro.style.top = this.canvasSensorImg[this.index].y + 40 + "px";
        canpro.style.left = this.canvasSensorImg[this.index].x - 60 + "px";
        this.canvasvisible = !this.canvasvisible;
      });
    },
    //鼠標(biāo)移動(dòng)觸發(fā)事件
    canvasMouseMove(e) {
      if (!this.isClick) {
        return;
      }
      if (this.index != -1) {
        this.canvasvisible = false;
        let x = e.offsetX;
        let y = e.offsetY;
        this.canvasSensorImg[this.index].x =
          this.canvasSensorImg[this.index].x < 0
            ? 0
            : x - this.canvasSensorImg[this.index].width / 2;
        this.canvasSensorImg[this.index].y =
          this.canvasSensorImg[this.index].y < 0
            ? 0
            : y - this.canvasSensorImg[this.index].height / 2;
      }
    },
    //鼠標(biāo)抬起觸發(fā)事件
    canvasMouseUp(e) {
      console.log("執(zhí)行了");
      this.isClick = false;
    },
    handleClick(item) {
      // 判斷是否上傳樓層圖片
        // 創(chuàng)建點(diǎn)位
        let imgs = {};
        imgs.url = this.Icondata;
        imgs.x = 0;
        imgs.y = 0;
        imgs.width = 46;
        imgs.height = 46;
        // 加載點(diǎn)位圖標(biāo)
        this.canvasSensorImg.push(imgs);
        this.$message.success("請(qǐng)拖動(dòng)圖標(biāo)到指定點(diǎn)位");
    },
  },
  beforeDestroy() {
    clearInterval(this.intervalId);
    this.intervalId = null; 
  },
};
</script>
?
<style lang="scss" scoped>
.app-container {
  height: 815px;
  .grid-left {
    padding: 30px 20px 20px;
    min-height: 815px;
    border: 1px solid #ccc;
    // 輸入框
    .searchinput {
      margin-bottom: 20px;
    }
  }
  .grid-right {
    // width: 1363px;
    width: 100%;
    height: 815px;
    padding: 30px 20px 20px;
    border: 1px solid #ccc;
    position: relative;
    // 標(biāo)題
    .grid-top {
      width: 100%;
    }
    // 圖片展示
    .bigImg {
      display: block;
      width: 970px;
      height: 500px;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -54%);
    }
    // 畫布模塊
    .canvas-box {
      width: 1000px;
      height: 620px;
      padding: 10px;
      background-color: #fff;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -55%);
      cursor: pointer;
      .canvas-title {
        display: flex;
        // background-color: skyblue;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 10px;
      }
    }
    // 保存平面圖
    .bottom {
      width: 95%;
      height: 100px;
      border-top: 1px solid #ccc;
      display: flex;
      justify-content: center;
      align-items: center;
      // background-color: skyblue;
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      bottom: 0;
    }
    // 設(shè)備彈出框
    ::v-deep .el-popover {
      // background-color: skyblue;
      padding: 0;
      .popover-top {
        display: flex;
        justify-content: space-between;
        align-items: center;
        .popover-title {
          width: 30px;
          height: 35px;
          cursor: pointer;
          background-color: #e72528;
          display: flex;
          justify-content: center;
          align-items: center;
          border-radius: 0 5px 0 0;
          i {
            font-size: 25px;
          }
        }
        i {
          font-style: normal;
          // font-size: 20px;
        }
      }
      p {
        margin: 3px 0;
      }
    }
  }
  .grid-table {
    padding: 30px 5px 5px;
    height: 815px;
    border: 1px solid #ccc;
    .grid-top {
      display: flex;
      align-items: center;
      // background-color: skyblue;
      i {
        display: block;
        width: 3px;
        height: 19px;
        background-color: #409eff;
        // border-radius: 2px;
        margin-right: 5px;
      }
      p {
        // font-size: 17px;
        // font-weight: 700;
        color: rgb(36, 37, 37);
      }
    }
    // 設(shè)備列表
    .newtable {
      background-color: #fff;
      .new-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 80px;
        padding: 0 5px;
        cursor: pointer;
        // background-color: skyblue;
        border-top: 2px solid #c8c8c8;
        // border-bottom: 2px solid #c8c8c8;
        &:last-child {
          border-bottom: 2px solid #c8c8c8;
        }
        img {
          width: 45px;
          height: 45px;
        }
        .newconter {
          margin-left: 10px;
          font-size: 12px;
          p {
            padding: 0;
            margin: 2px 0;
          }
        }
      }
    }
    .pagination {
      margin-top: 10px;
      display: flex;
      justify-content: center;
      align-content: center;
    }
  }
}
</style>

總結(jié):

經(jīng)過(guò)這一趟流程下來(lái)相信你也對(duì) vue-使用canvas畫布實(shí)現(xiàn)平面圖點(diǎn)位標(biāo)注功能 有了初步的深刻印象,但在實(shí)際開發(fā)中我 們遇到的情況肯定是不一樣的,所以我們要理解它的原理,萬(wàn)變不離其宗。

到此這篇關(guān)于vue使用canvas畫布實(shí)現(xiàn)平面圖點(diǎn)位標(biāo)注功能的文章就介紹到這了,更多相關(guān)vue canvas平面圖點(diǎn)位標(biāo)注內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論