当前位置: 首页 > news >正文

UNIAPP利用canvas绘制图片和文字,并跟随鼠标移动

最近有个项目,要触摸组件,产生一条图片跟随移动,并显示相应的文字,在网上找了一些资料,终于完成构想,废话少说,直接上代码(测试通过)

<template>
    <view>
        <view class="btnBox">
            <view class="btn" style="background-color: blue;" @click="moveImage">移动图片</view>
        </view>
        <canvas canvas-id="myCanvas" id="myCanvas" @touchstart="handleTouchStart" @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"></canvas>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                ctx: '',
                beginX: '',
                beginY: '',
                movedX: '',
                movedY: '',
                layers: [],
                toBase64Url: "",
                bloburl: "",
            }
        },
        onLoad() {
            this.ctx = uni.createCanvasContext('myCanvas')
        },
        methods: {
            moveImage() {
                let that = this;
                var Image = "";
                //var Image="https://www.small-helper.com/account.png";//网络图片地址
                //Image="http://localhost:8080/static/images/wx_img/dkk.png"//本地服务器内图片直接地址
                uni.getImageInfo({
                    src: '/static/images/wx_img/dkk.png',
                    success: function(res) {
                    //    console.log(res);
                        Image = res.path;
                        var contentWidth = res.width;
                        var contentHeight = res.height;
                        //
                        let layer = {
                            type: 'photo',
                            resoure: Image,
                            //resoure:"http://localhost:8080/static/images/wx_img/dkk.png",
                            x: 0,
                            y: 0,
                            w: 150,
                            h: 150,
                            isDrag: false
                        }
                        that.layers.push(layer);
                        that.darwImages(Image, layer.x, layer.y, layer.w, layer.h);
                    },
                    fail() {
                        that.$Common.toast(";获取图片失败")
                    }
                });
                
                /*从相册获取图片进行移动
                uni.chooseImage({
                    success: (res) => {
                        let layer = {
                            type: 'photo',
                            resoure: res.tempFilePaths[0],
                            x: 0,
                            y: 0,
                            w: 200,
                            h: 150,
                            isDrag: false
                        }
                        //console.log(res.tempFilePaths[0]);
                        that.urlTobase64("/static/images/wx_img/dkk.png");
                        console.log(that.toBase64Url);
                        //let bloburl=that.dataURLToBlob(url);
                        that.layers.push(layer);
                        this.darwImages(res.tempFilePaths[0],layer.x,layer.y,layer.w,layer.h)
                     
                    }
                })*/
            },
            darwImages(url, x, y, w, h) {
                this.ctx.drawImage(url, x, y, w, h);//设置图片初始位置
                this.ctx.setFontSize(uni.upx2px(40));//设置字体尺寸
                this.ctx.setFillStyle("#5500ff");
                //this.ctx.font = "songti";
                this.ctx.fillText('nihao',x+50,y-1);
                this.ctx.draw(true);
            },
             draw() {
                //var ctx = document.getElementById('canvas').getContext('2d');
                var img = new Image();
                img.onload = function() {
                    //this.ctx.drawImage(img, 0, 0);
                    this.ctx.beginPath();
                    this.ctx.moveTo(30, 96);
                    this.ctx.lineTo(70, 66);
                    this.ctx.lineTo(103, 76);
                    this.ctx.lineTo(170, 15);
                    this.ctx.stroke();
                    this.ctx.fillText('nihao',10,100);

                };
                img.src = "/static/images/wx_img/dkk.png";
                //img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';
            },
            
            //可通过此方法对本地路径 如: …/…/static/img/01.png 或者网络路径图片转为base64
            urlTobase64(url) {
                var that = this;
                //var toBase64Url;
                uni.request({
                    url: url,
                    method: 'GET',
                    responseType: 'arraybuffer',
                    success: async res => {
                        let base64 = wx.arrayBufferToBase64(res.data); //把arraybuffer转成base64
                        that.toBase64Url = 'data:image/jpeg;base64,' + base64; //不加上这串字符,在页面无法显示
                        //console.log(that.toBase64Url);
                        //return toBase64Url ;

                        return (that.dataURLToBlob(that.toBase64Url));

                    }
                });
            },
          
            

            // DataURL转Blob对象
            dataURLToBlob(dataurl) {
                console.log(dataurl);
                var arr = dataurl.split(',');
                var mime = arr[0].match(/:(.*?);/)[1];
                var bstr = atob(arr[1]);
                var n = bstr.length;
                var u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                var dataURL1 = this.windowURL.createObjectURL(new Blob([u8arr], {
                    type: mime
                }));
            //    console.log(dataURL1);
                return new Blob([u8arr], {
                    type: mime
                });
                //console.log(new Blob([u8arr], {type:mime}));
            },

            
            handleTouchStart(e) {
                let {
                    x,
                    y
                } = e.changedTouches[0]
                this.beginX = x
                this.beginY = y
                for (var i = this.layers.length - 1; i >= 0; i--) {
                    if (x > this.layers[i].x && y > this.layers[i].y && x < this.layers[i].w + this.layers[i].x && y < this
                        .layers[i].h + this.layers[i].y) {
                        this.layers[i].isDrag = true
                        let selectObj = this.layers[i]
                        this.layers.splice(i, 1)
                        this.layers.push(selectObj)
                        //console.log(selectObj)
                        break
                    }
                }
            },

            handleTouchMove(e) {
                if (this.layers.length != 0 && this.layers[this.layers.length - 1].isDrag == true) {
                    let {
                        x,
                        y
                    } = e.changedTouches[0]
                    this.movedX = x - this.beginX
                    this.movedY = y - this.beginY
                    this.layers[this.layers.length - 1].x += this.movedX
                    this.layers[this.layers.length - 1].y += this.movedY
                    this.beginX = x
                    this.beginY = y
                }
                this.ctx.clearRect(0, 0, 750, 900)
                this.layers.forEach(l => this.darwImages(l.resoure, l.x, l.y, l.w, l.h))
            },
            handleTouchEnd(e) {
                if (this.layers.length != 0) {
                    this.layers[this.layers.length - 1].isDrag = false
                }
            }

        }
    }
</script>

<style>
    .btnBox {
        display: flex;
    }

    .btn {
        width: 630rpx;
        height: 90rpx;
        line-height: 94rpx;
        text-align: center;
        //background: $wx_theme_blue;

        color: #fff;
        border-radius: 45rpx;
        font-size: 36rpx;
        margin: 80rpx auto 30rpx;
    }

    #myCanvas {
        width: 750rpx;
        height: 900rpx;
    }
</style>

相关文章:

UNIAPP利用canvas绘制图片和文字,并跟随鼠标移动

最近有个项目&#xff0c;要触摸组件&#xff0c;产生一条图片跟随移动&#xff0c;并显示相应的文字&#xff0c;在网上找了一些资料&#xff0c;终于完成构想&#xff0c;废话少说&#xff0c;直接上代码&#xff08;测试通过&#xff09; <template> <view>…...

【智能电表数据接入物联网平台实践】

智能电表数据接入物联网平台实践 设备接线准备设备调试代码实现Modbus TCP Client 读取电表数据读取寄存器数据转成32bit Float格式然后使用modbusTCP Client 读取数据 使用mqtt协议接入物联网平台最终代码实现 设备接线准备 设备调试 代码实现 Modbus TCP Client 读取电表数…...

Docker--network命令的用法

原文网址&#xff1a;Docker--network命令的用法_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker的network网络命令的用法。 官网网址 docker network | Docker Documentation 命令概述 所有命令 命令名称 说明 docker network connect 将容器连接到网络 dock…...

优维低代码实践:图片和搜索

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

[Qt]控件

文章摘于 爱编程的大丙 文章目录 1. 按钮类型控件1.1 按钮基类 QAbstractButton1.1.1 标题和图标1.1.2 按钮的 Check 属性1.1.3 信号1.1.4 槽函数 1.2 QPushButton1.2.1 常用API1.2.2 按钮的使用 1.3 QToolButton1.3.1 常用API1.3.2 按钮的使用 1.4 QRadioButton1.4.1 常用API…...

GEE:快速实现时间序列线性趋势和变化敏感性计算(斜率、截距)以NDVI时间序列为例

作者:CSDN @ _养乐多_ 本博客将向您介绍如何使用Google Earth Engine(GEE)平台来处理Landsat 5、7和8的卫星图像数据,构建时间序列,以NDVI为例,计算NDVI时间序列的斜率和截距,以及如何导出这些结果供进一步分析使用。 文章目录 一、代码详解1.1 核心代码详解1.2 核心代…...

LC1713. 得到子序列的最少操作次数(java - 动态规划)

LC1713. 得到子序列的最少操作次数 题目描述LIS 动态规划 二分法代码演示 题目描述 难度 - 困难 LC1713.得到子序列的最少操作次数 给你一个数组 target &#xff0c;包含若干 互不相同 的整数&#xff0c;以及另一个整数数组 arr &#xff0c;arr 可能 包含重复元素。 每一次…...

vr飞机驾驶舱模拟流程3D仿真演示加大航飞安全法码

众所周知&#xff0c;航空航天飞行是一项耗资大、变量参数很多、非常复杂的系统工程&#xff0c;因此可利用虚拟仿真技术经济、安全及可重复性等特点&#xff0c;进行飞行任务或操作的模拟&#xff0c;以代替某些费时、费力、费钱的真实试验或者真实试验无法开展的场合&#xf…...

一、八大排序(sort)

文章目录 一、时间复杂度&#xff08;一&#xff09;定义&#xff1a;常数操作 二、空间复杂度&#xff08;一&#xff09;定义&#xff1a; 三、排序&#xff08;一&#xff09;选择排序1.定义2.代码3.特性 &#xff08;二&#xff09;冒泡排序1.定义2.代码3.特性 &#xff08…...

【AWS】AI 代码生成器—Amazon CodeWhisperer初体验 | 开启开挂编程之旅

使用 AI 编码配套应用程序更快、更安全地构建应用程序 文章目录 1.1 Amazon CodeWhisperper简介1.2 Amazon CodeWhisperer 定价2.1 打开VS Code2.2 安装AWS ToolKit插件 一、前言 1.1 Amazon CodeWhisperper简介 1️⃣更快地完成更多工作 CodeWhisperer 经过数十亿行代码的训…...

【Mysql主从配置方法---单主从】

Mysql主从 主服务器 创建用户 create user “for_rep”“从服务器IP地址” IDENTIFIED by “123456” 授权 grant replication slave on . to “for_rep”“从服务器IP地址” IDENTIFIED by “123456” 查看用户权限 SHOW GRANTS FOR “for_rep”“从服务器IP地址”; 修改M…...

⼀⽂读懂加密资产交易赛道的新锐⼒量Bitdu

交易所&#xff0c;仍然是加密资产赛道的皇冠级赛道。围绕这个领域展开的商业竞争&#xff0c;最能引起⼴⼤⽤⼾的关注。 经历了数轮资产价格涨跌的⽜熊之后&#xff0c;⼀批批创业者也在不断地思考这⼀议题 — 如何在去中⼼化的世界中&#xff0c;最⾼效率地集结流量、资本和…...

万里牛与金蝶云星空对接集成查询调拨单连通调拨单新增(万里牛调拨单-金蝶【直接调拨单】)

万里牛与金蝶云星空对接集成查询调拨单连通调拨单新增(万里牛调拨单-金蝶【直接调拨单】) 源系统:万里牛 万里牛是杭州湖畔网络技术有限公司旗下SaaS软件品牌&#xff0c;主要针对电商、外贸、实体门店等业务群体&#xff0c;帮助企业快速布局新零售&#xff0c;提升订单处理效…...

虚拟DOM与diff算法

虚拟DOM与diff算法 snabbdom虚拟DOMdiff算法 snabbdom 是什么&#xff1a;snabbdom是著名的虚拟DOM库&#xff0c;是diff算法的鼻祖&#xff0c;Vue源码借鉴了snabbdom 虚拟DOM 是什么&#xff1a;本质上是存在内存里的 JavaScript 对象 作用&#xff1a;用来描述真实DOM的层…...

K8S:pod资源限制及探针

文章目录 一.pod资源限制1.pod资源限制方式2.pod资源限制指定时指定的参数&#xff08;1&#xff09;request 资源&#xff08;2&#xff09; limit 资源&#xff08;3&#xff09;两种资源匹配方式 3.资源限制的示例&#xff08;1&#xff09;官网示例&#xff08;2&#xff0…...

CSS中的定位

position 的属性与含义 CSS 中的 position 属性用于控制元素在页面中的定位方式&#xff0c;有四个主要的取值&#xff0c;每个取值都会影响元素的布局方式&#xff0c;它们是&#xff1a; static&#xff08;默认值&#xff09;&#xff1a; 这是所有元素的初始定位方式。在静…...

二、链表(linked-list)

文章目录 一、定义二、经典例题&#xff08;一&#xff09;[21.合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/description/)1.思路2.复杂度分析3.注意4.代码 &#xff08;二&#xff09;[86.分割链表](https://leetcode.cn/problems/partition-list…...

Android EditText筛选+选择功能开发

在日常开发中经常会遇到这种需求&#xff0c;EditText既需要可以筛选&#xff0c;又可以点击选择。这里筛选功能用的是AutoCompleteTextView&#xff0c;选择功能使用的是第三方库https://github.com/kongzue/DialogX。 Android AutoCompleteTextView(自动完成文本框)的基本使用…...

Linux 信号 alarm函数 setitimer函数

/*#include <unistd.h>unsigned int alarm(unsigned int seconds);功能&#xff1a;设置定时器。函数调用&#xff0c;开始倒计时&#xff0c;0的时候给当前的进程发送SIGALARM信号参数&#xff1a;倒计时的时长。。单位&#xff1a;秒 如果参数为0&#xff0c;无效返回…...

自主设计,模拟实现 RabbitMQ - 实现发送方消息确认机制

目录 一、实现发送方消息确认 1.1、需求分析 什么是发送方的消息确认? 如何实现?...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

【java面试】微服务篇

【java面试】微服务篇 一、总体框架二、Springcloud&#xff08;一&#xff09;Springcloud五大组件&#xff08;二&#xff09;服务注册和发现1、Eureka2、Nacos &#xff08;三&#xff09;负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

2.2.2 ASPICE的需求分析

ASPICE的需求分析是汽车软件开发过程中至关重要的一环&#xff0c;它涉及到对需求进行详细分析、验证和确认&#xff0c;以确保软件产品能够满足客户和用户的需求。在ASPICE中&#xff0c;需求分析的关键步骤包括&#xff1a; 需求细化&#xff1a;将从需求收集阶段获得的高层需…...

数据挖掘是什么?数据挖掘技术有哪些?

目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...

Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用

Linux 内存管理调试分析&#xff1a;ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础&#xff0c;但这一子系统结构复杂&#xff0c;常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题&#xff0c;需要一套工具化、…...