inspection-painter.vue 7.08 KB
<template>
  <view class="inspection-painter">
    <canvas ref="painterRef" :style="{ width: '100%',height:canvasHeight+'px' }" canvas-id="firstCanvas" id="firstCanvas" disable-scroll
      @touchstart="handleStart" @touchmove="handleMove" @touchend="handleEnd"></canvas>
    <!-- <view @click="getCanvasBase64">base64</view> -->
  </view>
</template>

<script setup>
  import {
    ref,
    onMounted,
    getCurrentInstance,
    nextTick
  } from 'vue';
  import {
    testDrawLine
  } from '../draw.js'
  import {
    getImagePath,
  } from '../utils'
  
  const { proxy } = getCurrentInstance()

  const props = defineProps({
    imageUrl: {
      type: String,
      required: true,
    },
  })
  const canvasHeight = ref(150)

  // 绘制部分
  const linePointList = [] // 绘制路线,数据集合
  let currentLinePointList = [] // 本次绘制的坐标集合
  let context = null

  function drawLine() {
    context.beginPath();
    context.moveTo(50, 50);
    context.lineTo(200, 100);

    context.strokeStyle = "red";
    context.stroke();
  }

  function getPointData(data) {
    const coord = data.changedTouches[0]
    if (coord) {
      // 记录数据
      currentLinePointList.push([coord.x, coord.y])
      return [coord.x, coord.y]
    } else {
      return null
    }
  }
  /**
   * "changedTouches": {
  		"0": { "x": 195, "y": 60 }
  	},
   */
  const isDrawing = ref(false);
  let lastCoord = []

  function handleStart(event) {
    const coord = getPointData(event)
    console.log('handleStart', coord)

    isDrawing.value = true
    console.log(context, '=s=s=');

    // context.beginPath();
    // context.moveTo(50, 50);
    context.moveTo(...coord);
    lastCoord = coord
  }

  function handleMove(event) {
    console.log('handleMove', event)
    // if(!isDrawing.value) return;
    const coord = getPointData(event)

    context.beginPath();
    context.setStrokeStyle("red")
    context.setLineWidth(2)

    context.moveTo(...lastCoord);
    context.lineTo(...coord);

    context.stroke();
    context.draw(true)

    lastCoord = coord
  }

  function handleEnd(event) {
    console.log('handleEnd', event)
    linePointList.push(currentLinePointList)
    currentLinePointList = []
  }
  // 小程序获取64
  function getBase64FromTempPath(tempFilePath,callback=()=>{}) {
    uni.getFileSystemManager().readFile({
      filePath: tempFilePath,
      encoding: 'base64',
      success: (res) => {
        callback(res.data)
      },
      fail: (err) => {
        console.error('读取文件失败:', err);
      }
    });
  }

  // 获取base64
  function getCanvasBase64() {
    console.log('getCanvasBase64')
    // #ifdef H5
    return getCanvasBase64H5()
    // #endif
    
    return new Promise((resolve, reject) => {
      uni.canvasToTempFilePath({
        canvasId: 'firstCanvas',
        success: async (res) => {
          const tempFilePath = res.tempFilePath;
          // #ifdef MP-WEIXIN
          getBase64FromTempPath(tempFilePath,resolve)
          // #endif

          // #ifdef APP-PLUS
          const platform = uni.getSystemInfoSync().platform
          if (platform === 'ios') {
            const uniPath = plus.io.convertLocalFileSystemURL(res.tempFilePath);

            plus.io.resolveLocalFileSystemURL(uniPath, (entry) => {
              entry.file((file) => {
                const fileReader = new plus.io.FileReader();
                // 使用原生大文件处理模式
                fileReader.readAsDataURL(file, "utf-8", 1024 * 1024); // 1MB 分块

                fileReader.onload = (event) => {
                  if (event.type === 'progress') {
                    console.log(`加载进度: ${event.loaded}/${event.total}`);
                  } else if (event.type === 'load') {
                    const base64 = event.target.result;
                    console.log('base64加载成功', base64.length, base64.slice(0, 54));
                    // console.log('Base64 加载完成', base64);
                    const targetData = base64.split(',')
                    if (targetData[1]) {
                      resolve(targetData[1])
                    } else {
                      reject('图片数据不存在')
                    }
                  }
                };

                fileReader.onerror = (error) => {
                  console.error('大文件读取错误:', error.message);
                };
              });
            });
          } else {
            // console.log(22222)
            plus.io.resolveLocalFileSystemURL(res.tempFilePath, entry => {
              entry.file(file => {
                const reader = new plus.io.FileReader();
                reader.onloadend = event => {
                  const targetData = event.target.result.split(',')
                  if (targetData[1]) {
                    resolve(targetData[1])
                  } else {
                    reject('图片数据不存在')
                  }
                };
                reader.readAsDataURL(file);
              });
            });
          }
          // #endif
        },
        fail: err => {
          console.error('canvasToTempFilePath 失败:', err);
          reject('canvasToTempFilePath 获取失败')
        }
      },proxy);
    })
  }

  function getCanvasBase64H5() {
    return new Promise((resolve, reject) => {
      uni.canvasToTempFilePath({
        canvasId: 'firstCanvas',
        success: res => {
          console.log('res', res)
          const targetData = res.tempFilePath.split(',')
          if (targetData[1]) {
            resolve(targetData[1])
          } else {
            reject('图片数据不存在')
          }
        },
        fail: err => {
          reject(err)
        }
      },proxy)
    })
  }

  const painterRef = ref(null)

  function initPainter(url) {
    const imgPath = decodeURIComponent(url)
    getImagePath(imgPath).then(res => {
      // 计算展示的宽和高
      const systemInfo = uni.getSystemInfoSync()
      const showWidth = systemInfo.windowWidth - 20 // 20
      // 保持图片比例
      const showHeight = (res.height * showWidth) / res.width
      console.log(res.width, res.height, '------', showWidth, showHeight);
    
      canvasHeight.value = showHeight
      // 设置宽高
      console.log('painterRef', painterRef, showWidth, showHeight)
    
      // 不设置,也可使用
      // painterRef.value.style.width = showWidth + 'px'
      // painterRef.value.style.height = showHeight + 'px'
    
      // 保证canvas的宽高与图片一致
      nextTick(()=>{
        setTimeout(()=>{
          const ctx = uni.createCanvasContext('firstCanvas', proxy)
          ctx.drawImage(res.path, 0, 0, showWidth, showHeight)
          ctx.draw()
          // 记录context值
          context = ctx
        },200)

      })
    })
  }

  onMounted(() => {
    // const targetUrl = 'https://store.keliuyun.com/images/patrol%2Fscreenshot%2F20250605%2Fbd56cd4c-729f-45c4-9d3e-0eff767bb663.jpg'
    const targetUrl = props.imageUrl
    initPainter(targetUrl)
  })

  // 暴露方法给父组件调用
  defineExpose({
    getCanvasBase64H5,
    getCanvasBase64,
  });
</script>

<style scoped lang="less">
  .inspection-painter {}
</style>