微信小程序画布显示图片绘制矩形选区

news2024/12/27 11:47:51

在这里插入图片描述

wxml

<view class="page-body">
  <!-- 画布 -->
  <view class="page-body-wrapper">
    <canvas canvas-id="myCanvas" type="2d" id="myCanvas" class='myCanvas' bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas>
  </view>
  <!-- 操作 -->
  <view class="layout-bottom">
    <view class="page-bottom">
      <view class="pbottom pmiddle" bindtap="pre">
        <image src="/images/next2.png" style="height: 65rpx; width: 65rpx; " mode="aspectFit"></image>
        <view class="pictureBottomArea"><p>返回</p></view>
      </view>
      <view class="pbottom pmiddle" bindtap="detection">
        <image src="{{sbUrl}}" style="height: 100rpx; width: 100rpx; " mode="aspectFit"></image>
        <view class="pictureBottomArea1"><p>识别</p></view>
      </view>
      <view class="pbottom pmiddle" bindtap="clear">
        <image src="/images/qc3.png" style="height: 70rpx; width: 70rpx; " mode="aspectFit"></image>
        <view class="pictureBottomArea"><p>清除选区</p></view>
      </view>
    </view>
  </view>
</view>

wxss

.myCanvas { background-color: #F7F7F7; width: 100vw; height: 100vh; }
page { width: 100%; height: 100%; padding: 0; margin: 0; background-color: #F8F8F8; font-size: 32rpx; line-height: 1.6; display: flex; display: -webkit-flex; flex-direction: column; flex-wrap: wrap; justify-content: center; align-items: center; }
.page-body { width: 100%; height: 100%; padding: 0; margin: 0; }  .page-body-wrapper { width: 100%; height: 80%; display: flex; flex-direction: column; align-items: center; width: 100%; }
.layout-bottom { width: 100%; height: 20%; background-color: white; }
.page-bottom { width: 100%; height: 75%; display: flex; display: -webkit-flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; }
.pbottom { width: 33.333333333%; height: 100%; }
.pmiddle{ display: flex; display: -webkit-flex; flex-direction: column; flex-wrap: wrap; justify-content: center; align-items: center; }
.pictureBottomArea { margin-top: 15rpx; font-size: small; }
.pictureBottomArea1 { font-size: 0.9rem; letter-spacing:4rpx; font-weight: 600; color: #585858; }

js

图片适配画布显示,关键在于计数图片缩放比例


// 定义变量
let startX, startY, endX, endY, rectWidth, rectHeight

Page({
  data: {
    drawWidth: 0,
    drawHeight: 0,
    drawX: 0,
    drawY: 0,
    ratio: 0,//缩放比例
    sbUrl: '/images/a2.png',//按钮
    imgSrc: '/images/ll.png',
    area: [],
    ctx: null,
    canvas: null,
    drawimage: null,
  },
  
  onLoad(options) {
    startX = 0
    startY = 0
    endX = 0
    endY = 0
    rectWidth = 0
    rectHeight = 0
    //把图片绘制到画布上
    this.drawImage(this.data.imgSrc)
  },

  //把图片绘制到画布上
  drawImage(imgSrc){
    let _this = this
    wx.createSelectorQuery().select('#myCanvas').fields({ node: true, size: true }).exec((res0) => {
      //获取canvas宽高
      const canvas = res0[0].node
      console.log(canvas)
      let ctx = canvas.getContext('2d');
      const cw = res0[0].width
      const ch = res0[0].height
      console.log('Canvas宽度:'+cw, 'Canvas高度:'+ch)

      const dpr = wx.getSystemInfoSync().pixelRatio
      console.log(dpr)
      
      canvas.width = cw * dpr     // 获取宽
      canvas.height = ch * dpr  // 获取高
      console.log(cw * dpr, ch * dpr)
      ctx.scale(dpr, dpr)

      wx.getImageInfo({
        src: imgSrc,
        success: function (res) {
          //获取图片宽高
          let iw = res.width
          let ih = res.height
          console.log('图片宽度:'+iw, '图片高度:'+ih);

          // 计算绘制位置,保持原始比例
          let ratio = Math.min(cw / iw, ch / ih);
          console.log(ratio)
          // 图片适配画布显示,关键在于计数图片缩放比例
          let drawWidth = iw * ratio;
          let drawHeight = ih * ratio;
          console.log('图片缩放后宽度:'+drawWidth, '图片缩放后高度:'+drawHeight);
          let drawX = (cw - drawWidth) / 2;
          let drawY = (ch - drawHeight) / 2;

          // 到这里就可以直接绘制
          let image = canvas.createImage();//创建iamge实例
          image.src = imgSrc;  // 引入本地图片
          image.onload = function () {
            ctx.drawImage(image, 0, 0, drawWidth, drawHeight);
          }

          _this.setData({drawWidth: drawWidth,drawHeight: drawHeight,drawX: drawX,drawY: drawY,  ratio: ratio,ctx: ctx,canvas: canvas,drawimage: image})
        },
        fail: function (res) {
          console.error('获取图片信息失败', res);
        }
      });
    })
  },

  // 触摸开始事件
  touchStart(e) {
    startX = e.touches[0].x
    startY = e.touches[0].y
    console.log("触摸开始事件", e.touches[0], startX, startY)
  },

  // 触摸移动事件
  touchMove(e) {
    let imgSrc = this.data.imgSrc
    let drawWidth = this.data.drawWidth
    let drawHeight = this.data.drawHeight
    let ctx = this.data.ctx
    let image = this.data.drawimage

    endX = e.touches[0].x
    endY = e.touches[0].y

    ctx.clearRect(0, 0, drawWidth, drawHeight)
    ctx.drawImage(image, 0, 0, drawWidth, drawHeight);
    
    rectWidth = endX - startX
    rectHeight = endY - startY
    ctx.strokeRect(startX, startY, rectWidth, rectHeight)
    ctx.strokeStyle = 'red'
    ctx.stroke()
  },

  // 触摸结束事件
  touchEnd(e) {
    // 绘制完成后的操作
    // 可以将坐标框的位置和大小保存到全局变量或发送给服务器等
    console.log("触摸结束事件",e.changedTouches[0])
  },

  //清除绘制的图形
  clear(){
    console.log("清除绘制")
    let imgSrc = this.data.imgSrc
    let drawWidth = this.data.drawWidth
    let drawHeight = this.data.drawHeight
    let ctx = this.data.ctx
    let image = this.data.drawimage
    ctx.clearRect(0, 0, drawWidth, drawHeight)
    ctx.drawImage(image, 0, 0, drawWidth, drawHeight);
    startX = 0
    startY = 0
    endX = 0
    endY = 0
    rectWidth = 0
    rectHeight = 0
  },
  // 识别
  detection(e){
    console.log("开始识别")
    let ratio = this.data.ratio
    //获取绘制选区的相关信息,这里要除以图片缩放比例,才是真是图片上的框选区
    if (rectWidth != 0 && rectHeight != 0){
        console.log('矩形','x='+startX/ratio,'y='+startY/ratio,'Width='+rectWidth/ratio,'Height='+rectHeight/ratio)
     }

  },
  //上一页
  pre(){
    console.log("上一页")
  }
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UEFI EDK2源码学习(一)——环境安装

部署环境 vmvare15.0 ubuntu20.04 docker edk2 源码 具体步骤 docker安装 # 更新apt软件包索引 sudo apt-get update# 添加docker依赖 sudo apt-get install -y \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common# 添加docker 官方…

白嫖免费图床!CloudFlare R2太香了!

1 为啥要折腾搭建一个专属图床&#xff1f; 技术大佬写博客都用 md 格式&#xff0c;要在多平台发布&#xff0c;图片就得有外链后续如博客迁移&#xff0c;国内博客网站如掘金&#xff0c;简书&#xff0c;语雀等都做了防盗链&#xff0c;图片无法迁移 2 为啥选择CloudFlare…

力扣刷题---返回word中所有不重复的单词

当需要从一个数据集合中去除重复元素时&#xff0c;set是一个很好的选择。由于其不允许存储重复的元素&#xff0c;因此可以很容易地实现去重功能。这在处理原始数据或进行数据分析时特别有用。 题目&#xff1a; 给定一个字符串数组 words&#xff0c;请返回一个由 words 中所…

SpringCloud微服务03-微服务保护-分布式事务-MQ基础-MQ高级

一、微服务保护 1.雪崩问题 如何做好后备方案就是后续&#xff1a; 2.雪崩解决方案 某一个服务的线程是固定的&#xff0c;出现故障线程占满后&#xff0c;就不会让取调用这个服务&#xff0c;对其他服务就没有影响。 3.Sentinel ①初识Sentinel 配置过程&#xff1a;day05-服…

Unity 实现心电图波形播放(需波形图图片)

实现 在Hierarchy 面板从2D Object 中新建一个Sprite&#xff0c;将波形图图片的赋给Sprite。 修改Sprite 的Sprite Renderer 组件中Draw Mode 为Tiled, 修改Sprite Renderer 的Size 即可实现波形图播放。 在Hierarchy 面板从2D Object 中新建一个Sprite Mask 并赋以遮罩图片…

表现层框架设计之表现层设计模式_2.MVP模式

1.MVP模式 MVP&#xff08;Model-View-Presenter&#xff09;模式提供数据&#xff0c;View负责显示&#xff0c;Controller/Presenter负责逻辑的处理。MVP是从经典的模式MVC演变而来&#xff0c;它们的基本思想有相通的地方&#xff1a;Controller/Presenter负责逻辑的处理&am…

10款手机黑科技app,每款都好用到爆!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 1. 计划程序应用 —— Android Auto Text Android Auto Text&#xff08;前身为 Do It Later&#xff09;是一款简单易用的日程安排应用程序&am…

LLM实战:当网页爬虫集成gpt3.5

1. 背景 最近本qiang~关注了一个开源项目Scrapegraph-ai&#xff0c;是关于网页爬虫结合LLM的项目&#xff0c;所以想一探究竟&#xff0c;毕竟当下及未来&#xff0c;LLM终将替代以往的方方面面。 这篇文章主要介绍下该项目&#xff0c;并基于此项目实现一个demo页面&#x…

can设备调试 - linux driver

这篇文章主要介绍can设备的调试相关信息&#xff0c;不具体介绍驱动的实现。 如果驱动写完&#xff0c;对can设备进行验证&#xff0c;可能会出现很多不可预见的问题。下面说说验证步骤 验证can设备可以使用工具can-utils。这个工具包中会有cansend candump等程序。可以直接通…

找钢集团亮相沙特利雅得建筑行业供应链展会

5月20日-21日&#xff0c;找钢产业互联集团&#xff08;以下简称&#xff1a;找钢集团&#xff09;亮相沙特利雅得建筑行业供应链展会。本次展会由沙特阿拉伯国家住房公司&#xff08;NHC&#xff09;主办&#xff0c;中信建设协办&#xff0c;涵盖住房新科技、绿色环保等多个主…

C语言例题46、根据公式π/4=1-1/3+1/5-1/7+1/9-1/11+…,计算π的近似值,当最后一项的绝对值小于0.000001为止

#include <stdio.h> #include <math.h>int main() {int fm 1;//分母double sign 1;//正负号double fzs 1;//分子式double sum 0;while (fabs(fzs) > 0.000001) {sum fzs;sign * -1; //变换正负号fm 2; //分母3、5、7、9...增长fzs sign / fm;//分子式…

Pod容器资源限制和探针

目录 一、资源限制 1.Pod和容器的资源请求和限制 2.CPU 资源单位 案例一 案例二 二、健康检查&#xff0c;又称为探针&#xff08;Probe&#xff09; 1.探针的三种规则 2.Probe支持三种检查方法 3.探测获得的三种结果 案例一&#xff1a;exec 案例二&#xff1a;htt…

[NOIP2002]过河卒 标准递归

题目地址 登录—专业IT笔试面试备考平台_牛客网 输入输出描述 如果没有马存在 就是一个经典的递归题 // Dduo // Bhu Bigdata 1421 package Dduo; import java.util.*; // Eslipse IDE 2020-08 // JDK 1.8 // 2024/5/21public class Main {static Scanner scnew Scanner(Sy…

linux命令日常使用思考

linux命令日常使用思考 复制的相关问题scp和cp的区别root192.168.5.229-r的理解 更新版本的相关问题svn info 根目录和家目录的区别根目录家目录 复制的相关问题 scp和cp的区别 安全性&#xff1a;SCP 是基于 SSH 的加密传输协议&#xff0c;可以保证数据在传输过程中的安全性…

Midjourney应用场景、特点、生成图片带来影响

Midjourney是一个基于GPT-3.5系列接口开发的免费AI机器人&#xff0c;旨在提供多领域的智能对话服务。本文主要介绍Midjourney的应用场景、功能特点、图片生成后可以做什么&#xff1f; 一、Midjourney应用场景 Midjourney的应用场景相当广泛&#xff0c;以下是一些主要的适用…

HTML5好看的通用网站模板源码

文章目录 1.设计来源1.1 主界面1.2 模板菜单1 界面1.3 模板菜单2 界面1.4 模板菜单3 界面1.5 下拉菜单1 界面1.6 下拉菜单2 界面1.7 模板菜单4 界面1.8 模板菜单5 界面1.9 界面底部 2.效果和源码2.1 动态效果2.2 源码目录2.3 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址…

学习通高分免费刷课实操教程

文章目录 概要整体架构流程详细步骤云上全平台登录步骤小结 概要 我之前提到过一个通过浏览器的三个脚本就可以免费高分刷课的文章&#xff0c;由于不方便拍视频进行实操演示&#xff0c;然后写下了这个实操教程&#xff0c;之前的三个脚本划到文章末尾 整体架构流程 整体大…

若依 ruoyi-vue 用户账号前后端参数校验密码 手机号 邮箱

前端 <el-dialog :title"title" :visible.sync"open" width"800px" append-to-body><el-form ref"form" :model"form" :rules"rules" label-width"120px"><el-row><el-col :span…

链游:区块链技术的游戏新纪元

随着区块链技术的快速发展&#xff0c;越来越多的行业开始探索与其结合的可能性&#xff0c;其中&#xff0c;游戏行业与区块链的结合尤为引人注目。链游&#xff0c;即基于区块链技术的游戏&#xff0c;正以其独特的优势&#xff0c;为玩家带来全新的游戏体验。本文将对链游进…