zoukankan      html  css  js  c++  java
  • vue+div.canvas图像标注功能实现

     

     main.js

    import Vue from 'vue'
    import 'vueui-widgets/dist/index.css'
    import VueUI from 'vueui-widgets'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    Vue.use(VueUI)
    
    Vue.config.productionTip = false
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')

    组件.vue

    <template>
      <div class="mycanvas-container">
        <div class="left">
          <p>展示视口</p>
          <div class="myshow">
            <img :src="mysrc" alt width="100%" />
            <!-- <div id="canvas" style="100%;height:100%" class="mycanvas"></div> -->
          </div>
        </div>
        <div class="center">
          <p>操作视口</p>
          <div class="myedit" ref="myedit" @mousedown.prevent="onMousedown" @mousemove="onMousemove" @contextmenu.prevent="">
            <!-- <img src="@/assets/jia.svg" alt=""> -->
            <img :src="mysrc" />
            <span
              class="myedit-span"
              v-for="(item, index) in mydata"
              :key="index"
              :style="getSpanStyle(item)"
              @contextmenu.prevent="onContextmenu(item, $event)"
            ></span>
            <!-- <div id="canvas" style="100%;height:100%" class="mycanvas"></div> -->
          </div>
        </div>
        <div class="right">
          <img src alt class="mybutton" />
          <input v-show="0" ref="file" type="file" class="mybutton" @change="onChange" />
          <button class="mybutton" @click="selectFile">导入图片</button>
          <button class="mybutton">新增标注</button>
          <button class="mybutton">修改标注</button>
          <button class="mybutton">删除</button>
          <button class="mybutton">保存</button>
        </div>
        <div class="myMenu" v-show="mymenu.current" :style="mymenu.style">
          <!-- <button @click="onRemoveItem">删除</button> -->
          <ui-button type="primary" @click="onRemoveItem">删除</ui-button>
          <ui-select></ui-select>
          <select name="" id="">
            <option value="1">ceshi</option>
          </select>
        </div>
      </div>
    </template>
    
    <script>
    import jiaIcon from "./jia.svg";
    export default {
      data() {
        return {
          mysrc: "",
          mydata: [],
          mymenu: { current: null, style: { left: 0, top: 0 } }
        };
      },
      mounted() {
        document.addEventListener('mouseup', this.onMouseup)
      },
      beforeDestroy() {
        document.removeEventListener('mouseup', this.onMouseup)
      },
      methods: {
        getXY(e) {
          let rect = this.$refs.myedit.getBoundingClientRect()
          return {
            x: e.clientX - rect.left,
            y: e.clientY - rect.top
          }
        },
        // 上传图片1
        onChange(e) {
          this.mysrc = window.URL.createObjectURL(e.target.files[0]);
          e.target.value = ''
        },
        // 上传图片2,
        selectFile() {
          this.$refs.file.click();
        },
        onMousedown(e) {
          this.mymenu.current = null
          let { x, y } = this.getXY(e)
          this.currentItem = { x, y, w: 0, h: 0, now: Date.now() }
          this.startPos = { x, y }
          this.mydata.push(this.currentItem)
        },
        onMousemove(e) {
          if (!this.currentItem) return;
          let { x, y } = this.getXY(e)
          this.currentItem.w = Math.abs(x - this.startPos.x)
          this.currentItem.h = Math.abs(y - this.startPos.y)
        },
        onMouseup(e) {
          this.currentItem = this.startPos = null;
          this.mydata = this.mydata.filter(_ => _.w > 10 && _.h > 10)
        },
        onContextmenu(item, e) {
          this.mymenu = {
            current: item,
            style: {
              top: e.clientY + 'px',
              left: e.clientX + 'px'
            }
          }
        },
        onRemoveItem() {
          this.mydata.splice(this.mydata.indexOf(this.mymenu.current), 1)
          this.mymenu = { ...this.mymenu, current: null }
        },
        getSpanStyle(item) {
          return {
             `${item.w}px`,
            height: `${item.h}px`,
            top: `${item.y}px`,
            left: `${item.x}px`
          };
        }
      }
    };
    </script>
    <style lang="less" scoped>
    // 设置绘图样式1
    body {
      user-select: none;
    }
    
    .myMenu {
      position: fixed;
      top: 400px;
      left: 400px;
      width: 100px;
      padding: 8px 0;
      background-color: #fff;
      > * {
        width: 100%;
      }
    }
    
    #canvas > div {
      /* border: 2px solid green; */
      position: absolute;
      background-color: transparent;
    }
    
    #canvas > div > span {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-family: simsun;
      font-size: 9pt;
    }
    
    // 设置绘图样式2
    
    .mycanvas-container {
      display: flex;
      justify-content: center;
      align-items: center;
    
      .left,
      .center,
      .right {
        width: 300px;
        // height: 520px;
        margin: 20px;
    
        p {
          text-align: center;
        }
    
        .myshow,
        .myedit {
          width: 300px;
          // height: 500px;
          border: 1px solid #000;
          position: relative;
          .myedit-span {
            position: absolute;
            border: 1px dashed #fff;
            background: url("./jia.svg") no-repeat center center;
            background-size: contain;
          }
    
          .mycanvas {
            border: 1px solid pink;
            position: absolute;
            top: 0;
            left: 0;
          }
    
          img {
            width: 100%;
          }
        }
      }
    
      .right {
        width: 150px;
        display: flex;
        justify-content: center;
        align-items: left;
        flex-direction: column;
    
        .mybutton {
          margin-top: 20px;
          display: block;
        }
      }
    }
    </style>

  • 相关阅读:
    API入门系列之三 那迷惑人的Windows字符和字符指针类型 转载
    laravel中关联模型查询选择性的字段
    【实习】微软PM实习生面经
    【C++学习】String类的基本用法
    sql server cast 和 convert函数使用
    JS,Jquery获取,dropdownlist,checkbox 下拉列表框的值
    Buffer
    SQL Server 2012新增的内置函数尝试
    SQL Server2012新特性WITH RESULT SETS
    ros(8)自定义service数据
  • 原文地址:https://www.cnblogs.com/sugartang/p/11524834.html
Copyright © 2011-2022 走看看