两张图片进行分析

两张图片进行分析,可以拖动左边图片进行放大、缩小查看图片差异

底图

javascript 复制代码
<template>
   
   <div class="box_container">
    <section>
      <div class="" v-for="item in imgData.imgDataVal" :key="item.id">
        <img :style="{
          width: boxStyle.width + '%',
          top: boxStyle.top,
          left: boxStyle.left,
        }" :src="item.src" :alt="item.name" />

        <div v-if="clickState" class="selectRegion"
          :style="{ top: selectRegionStyle.top, left: selectRegionStyle.left }"></div>
        <div class="text">
          <p>{{ item.name }}</p>
        </div>

      </div>
      <div ref=" moveDom" id="moveDom"></div>


    </section>

    <p   class="p-diff">差别【不准确】: {{ differencePercentage }}%</p>
  </div>
</template>

<script lang="ts" setup>
  
import imageYT from '../assets/yt.png';
import imageFX from '../assets/fx.png';
import pixelmatch from 'pixelmatch';

import { reactive, ref, onMounted, onBeforeUnmount } from 'vue';
  
 
 
let differencePercentage = ref(0);
onMounted(() => {
  compareImages();
});
function compareImages() {
  const imgA = document.createElement('img');
  const imgB = document.createElement('img');

  imgA.onload = () => {
    imgB.onload = () => {
      const width = imgA.width;
      const height = imgA.height;
      const canvasA = document.createElement('canvas');
      const canvasB = document.createElement('canvas');
      canvasA.width = width;
      canvasA.height = height;
      canvasB.width = width;
      canvasB.height = height;
      const ctxA = canvasA.getContext('2d') as any;
      const ctxB = canvasB.getContext('2d') as any;
      ctxA.drawImage(imgA, 0, 0);
      ctxB.drawImage(imgB, 0, 0);
      const dataA = ctxA.getImageData(0, 0, width, height);
      const dataB = ctxB.getImageData(0, 0, width, height);
      const diff = pixelmatch(dataA.data, dataB.data, null, width, height);
      differencePercentage.value =
        100 - parseInt(((diff / (width * height)) * 100).toFixed(2));
    };
    imgB.src = imageFX as any;
  };
  imgA.src = imageYT as any;
}

let imgData = reactive({
  imgDataVal: [
    {
      id: 1,
      name: '原始图',
      src: imageYT
    },
    {
      id: 2,
      name: '分析图',
      src: imageFX
    }
  ]
})

/**
 * @description: 添加鼠标事件
 * @return {*}
 */

const init = () => {
  moveDom.value = document.getElementById('moveDom')
  moveDom.value.addEventListener('mousemove', moveEvent)
  moveDom.value.addEventListener('wheel', wheelEvent)
  moveDom.value.addEventListener('mousedown', mousedownEvent)
  moveDom.value.addEventListener('mouseup', mouseupEvent)
  moveDom.value.addEventListener('mouseout', mouseoutEvent)
  moveDom.value.addEventListener('mouseover', mouseoverEvent)
}
onMounted(() => {

  init()
})


 const moveDom: any = ref(null);
const images: any = ref(null);
images.value = document.getElementsByClassName('chatImgs');
/**
 * @description: 卸载鼠标事件
 * @return {*}
 */
onBeforeUnmount(() => {
  moveDom.value.removeEventListener('mousemove', moveEvent);
  moveDom.value.removeEventListener('mouseleave', wheelEvent);
  moveDom.value.removeEventListener('mousedown', mousedownEvent);
});
const boxStyle = ref({
  width: 50,
  top: '50%',
  left: '50%',
});
const selectRegionStyle = ref({
  top: '50%',
  left: '50%',
});
const moveX = ref(null);
const moveY = ref(null);

/**
 * @description: 鼠标移动事件
 * @param {*} e
 * @return {*}
 */
const moveEvent = (e: any) => {
  moveX.value = e.offsetX;
  moveY.value = e.offsetY;
  selectRegionStyle.value.left = `${e.offsetX}px`;
  selectRegionStyle.value.top = `${e.offsetY}px`;
  if (clickState.value) {
    boxStyle.value.top = `${e.offsetY}px`;
    boxStyle.value.left = `${e.offsetX}px`;
  }
};
/**
 * @description: 滚轮事件
 * @param {*} e
 * @return {*}
 */
const wheelEvent = (e: any) => {
  if (e.deltaY < 0) {
    if (boxStyle.value.width > 200) {
      return;
    }
    boxStyle.value.width = boxStyle.value.width + 10;
  } else {
    if (boxStyle.value.width < 50) {
      return;
    }
    boxStyle.value.width = boxStyle.value.width - 10;
  }
};

const clickState = ref(false);
const overState = ref(false);
/**
 * @description: 鼠标左键按下事件
 * @param {*} e
 * @return {*}
 */
const mousedownEvent = (e: any) => {
  clickState.value = true;
  overState.value = true;
};
/**
 * @description: 鼠标移入事件
 * @param {*} e
 * @return {*}
 */
const mouseoverEvent = (e: any) => {
  if (overState.value) {
    clickState.value = true;
  }
};
/**
 * @description: 鼠标左键抬起事件
 * @param {*} e
 * @return {*}
 */
const mouseupEvent = (e: any) => {
  clickState.value = false;
  overState.value = false;
};
/**
 * @description: 鼠标移出事件
 * @param {*} e
 * @return {*}
 */
const mouseoutEvent = (e: any) => {
  clickState.value = false;
};
</script>

<style scoped lang="scss">
.box_container {
  width: 100vw;
  height: 100vh;

  padding: 0;

}


section {
  width: 100%;
  height: 85%;
  display: flex;
  justify-content: center;
  justify-items: center;


  >div {
    flex: 1;
    height: 100%;
    position: relative;
    overflow: hidden;
    background-color: #0decb8da;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.07);

    img {
      width: 100%;
      position: absolute;
      transform: translate(-50%, -50%);
      z-index: 0;

    }

    .selectRegion {
      position: absolute;
      width: 100px;
      height: 100px;
      transform: translate(-50%, -50%);
      border: 1px solid rgba(0, 0, 0, 0.3);

    }
  }

  // 左边区域可以拖动
  #moveDom {
    width: 49.8%;
    height: 85.0%;
    background-color: rgba(0, 0, 0, 0);
    position: absolute;
    top: 0;
    left: 0;
    cursor: move;
  }

  >div:nth-child(1) {
    margin-right: 5px;
  }

  >div:nth-child(2) {
    cursor: no-drop;
    margin-left: 5px;
  }

  .text {
    width: 100%;
    height: 50px;
    position: absolute;
    bottom: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.1);

    p {
      width: 100%;
      height: 100%;
      line-height: 100%;
      text-align: center;
      line-height: 50px;
      // color: #333;
      color: #fff;
      font-weight: 600;
      letter-spacing: 10px;
      font-size: 18px;
    }
  }
}
.p-diff{
  display: flex;
  justify-content: center;
  margin-top: 20px;
  font-size: 20px;
  font-weight:600
}
</style>
相关推荐
山河木马2 分钟前
前端学C++可太简单了:双冒号 :: 操作符
前端·javascript·c++
3Katrina4 分钟前
前端面试之防抖节流(二)
前端·javascript·面试
前端进阶者10 分钟前
天地图编辑支持删除编辑点
前端·javascript
江号软件分享18 分钟前
无接触服务的关键:二维码生成识别技术详解
前端
江号软件分享19 分钟前
如何利用取色器实现跨平台色彩一致性
前端
灰海23 分钟前
封装WebSocket
前端·网络·websocket·网络协议·vue
前端小巷子33 分钟前
深入理解TCP协议
前端·javascript·面试
万少34 分钟前
鸿蒙外包的十大生存法则
前端·后端·面试
顽疲1 小时前
从零用java实现 小红书 springboot vue uniapp(13)模仿抖音视频切换
java·vue.js·spring boot
开开心心就好1 小时前
电脑息屏工具,一键黑屏超方便
开发语言·javascript·电脑·scala·erlang·perl