2***@qq.com
2***@qq.com
  • 发布:2024-08-12 10:59
  • 更新:2024-08-12 10:59
  • 阅读:481

uni.canvasToTempFilePath无效,触发 fail回调提示canvasToTempFilePath:fail fail canvas is empty

分类:uni-app

以下是我封装的canvas方法,和使用实例

<script setup lang="ts">  
import { watch, getCurrentInstance, onMounted, reactive, ref, CSSProperties } from 'vue'  
import Circle from './canvas'  

let cricle: Circle  
const props = defineProps<{  
  circleParam: {  
    percentage: number | string  
    treatmentMode: string  
    pressureUnit: string  
  }  
}>()  

const size = reactive({  
  width: 0,  
  height: 480,  
})  

watch(  
  () => props.circleParam,  
  () => {  
    updateDrawings()  
  },  
  {  
    deep: true,  
    // immediate: true,  
  }  
)  

onMounted(() => {  
  const instance = getCurrentInstance() as any  

  const info = uni.createSelectorQuery().in(instance).select('.circle')  

  info  
    .boundingClientRect(function (data) {  
      size.width = data['width'] * 2  

      const context = uni.createCanvasContext('circleCanvas', instance) //canvas组建封装,需要后加个this  
      const { width, height } = size  
      cricle = new Circle('circleCanvas', context, { width: width / 2, height: height / 2 })  
      updateDrawings()  
    })  
    .exec(function (_res) {  
      // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据  
    })  
})  

function updateDrawings() {  
  const value = props.circleParam.percentage  
  cricle.drawProgressValue(value === '--' ? 0 : (+props.circleParam.percentage / 20) * 100)  
  drawProgressInfo()  
  cricle.draw()  
}  

/**  
 * @description: 绘制圆环信息  
 */  
function drawProgressInfo() {  
  const { width } = size  
  const { treatmentMode, percentage, pressureUnit } = props.circleParam  
  cricle.paintFont(width / 4, 70, '治疗压力', 16)  
  cricle.paintFont(width / 4, 120, percentage, 'bold 48', '#292B3F', {  
    textAlign: 'center',  
    textBaseline: 'middle',  
  })  
  cricle.paintFont(width / 4, 160, pressureUnit, 'bold 16')  
  cricle.paintFont(width / 4, 200, treatmentMode, '20', '#4AC596')  
}  

const canvasStyle = ref<CSSProperties>()  

function canvasDisplay(value: 'show' | 'hidden') {  
  if (value === 'hidden') {  
    canvasStyle.value = {  
      position: 'absolute',  
      top: '-500px',  
    }  
  } else {  
    canvasStyle.value = {}  
  }  
}  

defineExpose({  
  canvasDisplay,  
})  
</script>  
<template>  
  <view class="circle" style="height: 480rpx">  
    <div :style="canvasStyle">  
      <canvas  
        v-if="size.width"  
        style="height: 480rpx; margin: 0 auto"  
        :style="{ widht: size.width + 'rpx' }"  
        canvas-id="circleCanvas"></canvas>  
    </div>  
  </view>  
</template>  
<style lang="scss" scoped>  
.circle {  
  width: 100%;  
  text-align: center;  
}  
</style>  
export default class Circle {  
  private context  
  size: {  
    width: number  
    height: number  
  }  
  BASEFONTCOLOR = '#B4B5BF'  
  BASEBGCOLOR = '#EBEBEB'  
  radius = 100  
  CANVASID: string  

  constructor(canvasId, context, size) {  
    this.CANVASID = canvasId  
    this.context = context  
    this.size = size  
    this.drawBackground()  
  }  

  drawBackground() {  
    const { width, height } = this.size  
    const [startAngle, endAngle] = this.scopePI()  

    this.drawBGRing(width / 2, height / 2, this.radius, startAngle, endAngle)  
    this.drawBGFont()  
  }  

  draw() {  
    const _that = this  
    this.context.draw(false, () => {  
      uni.canvasToTempFilePath(  
        {  
          canvasId: _that.CANVASID,  
          success: function (res) {  
            console.log('res', res)  

            return res.tempFilePath  
          },  
          fail: function (err) {  
            console.log('err', err)  
          },  
          complete: (com) => {  
            console.log('com', com)  
          },  
        },  
        _that  
      )  
    })  
  }  

  scopePI() {  
    return [(3 / 4) * Math.PI, (1 / 4) * Math.PI]  
  }  

  drawBGRing(x, y, radius, start, end, color = this.BASEBGCOLOR, LineWidth = 12) {  
    const ctx = this.context  

    ctx.beginPath()  
    ctx.setLineWidth(LineWidth)  
    ctx.strokeStyle = color  
    ctx.lineCap = 'round'  
    ctx.arc(x, y, radius, start, end, false)  
    ctx.stroke()  
    ctx.closePath()  
  }  
  drawBGFont() {  
    const { width, height } = this.size  
    const [startAngle, endAngle] = this.scopePI()  

    const minTextX = width / 2 + this.radius * Math.cos(startAngle)  
    const minTextY = height / 2 + this.radius * Math.sin(endAngle)  
    const maxTextX = width / 2 + this.radius * Math.cos(endAngle)  
    const maxTextY = height / 2 + this.radius * Math.sin(startAngle)  

    this.paintFont(minTextX + 20, minTextY + 20, 0, 14)  
    this.paintFont(maxTextX - 20, maxTextY + 20, 20, 14)  
  }  

  paintFont(x, y, text, fontSize, color = this.BASEFONTCOLOR, otherAttr: any = null) {  
    const ctx = this.context  
    ctx.beginPath()  
    ctx.font = (fontSize ?? '20') + 'px Arial'  
    ctx.fillStyle = color  
    ctx.textAlign = 'center'  

    if (otherAttr !== null) {  
      Object.keys(otherAttr).forEach((key) => {  
        ctx[key] = otherAttr[key]  
      })  
    }  
    ctx.closePath()  
    ctx.fillText(text, x, y)  
  }  

  /**  
   * @description: 绘制值  
   * @param {*} percentage 百分比值  
   */  
  async drawProgressValue(percentage) {  
    const { width, height } = this.size  
    const [startAngle, endAngle] = this.scopePI()  

    this.clearReact()  
    this.drawBGRing(width / 2, height / 2, this.radius, startAngle, endAngle)  
    this.drawBGFont()  

    // 计算当前进度的结束角度  
    const totalAngle = 2 * Math.PI - startAngle + endAngle // 完整的角度跨度  
    const progressEndAngle = startAngle + (percentage / 100) * totalAngle // 计算进度结束角度  

    // 创建渐变  
    const gradient = this.context.createLinearGradient(0, height / 2, width / 2, height / 2)  
    gradient.addColorStop(0, '#4AC596') // 起始颜色  
    gradient.addColorStop(1, '#82D2E3') // 结束颜色  

    // 绘制进度条  
    if (percentage > 0) {  
      this.drawBGRing(  
        width / 2,  
        height / 2,  
        this.radius,  
        startAngle,  
        progressEndAngle,  
        gradient,  
        12  
      )  
    }  
  }  

  clearReact() {  
    const ctx = this.context  
    const { width, height } = this.size  
    ctx.clearRect(0, 0, width, height)  
  }  
}  
2024-08-12 10:59 负责人:无 分享
已邀请:

要回复问题请先登录注册