箭头绘制参考了:https://blog.csdn.net/qq_45939676/article/details/127425426 这位大佬的文章

gitee地址: https://gitee.com/philippines-kisses-snow/uniapp-image-edit.git

组件预览

功能介绍

  1. 剪切
  2. 添加文本
  3. 涂鸦
  4. 绘制图形(支持箭头,圆形,矩形)
  5. 旋转

实现思路

  1. 将屏幕分为两部分:图片编辑部分、操作栏部分
  2. 图片编辑部分当中创建一个图片容器,容器大小为:图片大小*缩放比例,在容器当中使用<image />标签显示图片内容,<image />的大小占满父容器
  3. 创建一个<canvas />,canvas的大小为图片容器的大小,创建后用于保存图片编辑后的内容,并导出图片,再将image上的图片替换为canvas导出的图片,利用css将这个仅用于保存的canvas标签设置为不可见

一、 剪切

这里只设置了四个夹角用于拖动:左上角、右上角、左下角、右下角

剪切蒙版使用定位,相当于图片容器进行定位,那么蒙版的大小就是可以通过left、top、right、bottom的定位控制

  1. 设置蒙版颜色和边框,给蒙版的四个角设置拖动点,添加4个元素,定位到四个角,给这4个元素添加边框,使边框刚好包裹图片的菱角
  2. 给这四个元素添加拖动事件,并记录每次拖动的起始点,注:在touchmove当中需要更新起始点为当前位置的坐标font>
<view @touchmove.stop="cropTouchMove($event, CROP_TYPE.TOP_LEFT)" @touchstart.stop="cropTouchStart" class="top-left"></view>
<view @touchmove.stop="cropTouchMove($event, CROP_TYPE.TOP_RIGHT)" @touchstart.stop="cropTouchStart" class="top-right"></view>
<view @touchmove.stop="cropTouchMove($event, CROP_TYPE.BOTTOM_RIGHT)" @touchstart.stop="cropTouchStart" class="bottom-right"></view>
<view @touchmove.stop="cropTouchMove($event, CROP_TYPE.BOTTOM_LEFT)" @touchstart.stop="cropTouchStart" class="bottom-left"></view>
  1. 根据始末位置的坐标差计算定位
例如:移动左上角时:
起始点是(x = 0, y = 0)
当前点为(x = 2, y = 2)
移动差:(diffx = 2, diffy = 2)
由于移动点为左上角,蒙版的定位只有top、left会变化:
top变为:top + diffy
left变为: left + diffx,同理其他几个点类似: 右上角:top变为:top + diffy,right变为: right - diffx
左下角:bottom变为:bottom - diffy,left变为: left + diffx
右下角:bottom变为:bottom - diffy,right变为: right - diffx 出界判断:
0 <= top <= 图片容器高
0 <= left <= 图片容器宽
0 <= right <= 图片容器宽
0 <= bottom <= 图片容器高 最小剪切框大小限制:
图片宽 - right - left >= 最小宽
图片高 - bottom - top >= 最小高
  1. 导出,剪切完成后通过canvas的drawImage将图片渲染到canvas上,然后导出时,根据剪切蒙版的定位坐标计算出蒙版宽高,以蒙版左上角坐标开始导出蒙版宽高的图片即可

二、添加文本

文本添加与剪切类似,在图片容器内添加一个文本容器,并相对于图片容器定位,大小占满图片容器,创建一个文本数组用于保存文本框的属性:内容、位置,在文本容器内循环遍历文本数组,删除时只需删除对应索引的文本即可,保存时遍历数组,将文本循环绘制到canvas上,最后保存即可,双击图片可以新建一个文本框

// 绘制时的文本换行处理:
/**
* 绘制文本
* @param {Object} _this 组件实例
* @param {String} canvasID canvasID
* @param {String} text 文本字符串
* @param {Number} fontH 单行字体高度
* @param {Number} maxW 最大文本域宽
* @param {Number} startX 开始x坐标
* @param {Number} startY 开始y坐标
*/
export function drawText(_this, canvasID, textArea, fontSize, fontH, maxW, startX, startY) {
const ctx = uni.createCanvasContext(canvasID, _this)
const text = textArea.text
ctx.setFontSize(fontSize)
ctx.fillStyle = textArea.color
let rowW = 0
let rowTexts = []
let startIndex = 0
// 将一段长文本拆分为多段
for(let i = 0; i < text.length; i++) {
rowW += ctx.measureText(text[i]).width
if(rowW > maxW) {
rowTexts.push(text.substr(startIndex, i))
startIndex = i
rowW = 0
}
}
rowTexts.push(text.substr(startIndex))
// 分段绘制
rowTexts.forEach((str, index) => {
const y = index === 0 ? startY : index*fontH + startY
ctx.fillText(str, startX, y);
ctx.draw(true)
})
}

三、涂鸦

由于涂鸦实时性要求较高,图形不规则且连贯,需要使用canvas进行实时绘制

  1. 在图片容器内创建一个canvas,canvas大小为图片容器大小
  2. 涂鸦时直接在canvas上绘制即可(具体绘制过程的代码就不贴了,可在git当中查看)
  3. 保存时需导出该涂鸦图片,使用保存用的canvas绘制这两张图片,先绘制原图,再绘制涂鸦,导出即可

四、图形

在图片容器当中创建两个canvas(其中一个可与绘制涂鸦的canvas复用),获取起始点与当前点坐标在最外层的canvas上绘制相应图形,在滑动结束后将图形信息用数组保存起来,遍历数组绘制到下层的canvas上,清空最外层的canvas

箭头绘制需在箭头终点绘制两侧箭头边,具体计算可查看代码和参考的文章

uniapp H5图片编辑器(安卓/iOS适用)的更多相关文章

  1. 移动端H5制作安卓和IOS的坑 持续更新...

    移动端H5制作安卓和IOS的坑 持续更新... 前言:最近参加公司的H5页面创意竞赛,又遇到不少页面在不同系统上的坑.踩坑之余,觉得很多之前遇到的知识点都忘了,索性开一篇博文,把这些坑都统一归纳起来, ...

  2. H5与安卓、IOS的交互,判断微信、移动设备、安卓、ios

    一.通过用户代理可以判断网页当前所在的环境 var browser={ versions:function(){ var u = navigator.userAgent, app = navigato ...

  3. h5与安卓、ios交互

    1.安卓交互 h5调用安卓方法 window.webview.xxx() 安卓调用h5方法, 方法需要在全局注册 window['showUnreadMsg'] = () => { this.$ ...

  4. 点击复制文字到剪贴板兼容性安卓ios

    一般那种活动H5分享可能会用到点击复制文字到剪贴板,很简单的功能 于是搜了一搜:js复制文字到剪贴板,可用结果大致分为两类: 一类是js原生方法,这种方法兼容性不好,不兼容ios: https://d ...

  5. 史上最简单JS复制功能,兼容安卓ios!

    1.JS复制原理: 被复制内容的元素不能被其他元素遮盖,否则无效.  (设置opacity透明为0,不可以设置display:none); 2.常规的复制方法 function copyUrl2() ...

  6. .net 安卓IOS跨平台des加解密双向的(可以互相加解密)

    #region 跨平台加解密(c# 安卓 IOS) // public static string sKey = "12345678"; // /// // /// 解密 // / ...

  7. 安卓ios和angularjs相互调用解决首次调用ios传递标题失败的问题

    1.angular 调用客户端方法放在 try catch中 try { js_invoke.showShareDialog(angular.toJson(obj));  // 在这里放客户端的方法即 ...

  8. 安卓ios各版本及分辨率占比

    Google Play 安装统计数据 只有安卓的 https://developer.android.com/about/dashboards/index.html?hl=zh-cn 腾讯移动分析 安 ...

  9. H5移动端IOS/Android兼容性总结,持续更新中…

    H5移动端IOS/Android兼容性总结,持续更新中… 1. IOS不识别日期 new Date("2018-07-01 08:00:00")在Android下正常显示可以直接进 ...

  10. uni-app h5端跳转到底部导航栏的时候使用方法uni.switchTab跳转刷新页面更新数据

    h5端的uni-app项目 需求:uni-app h5端跳转到底部导航栏的时候使用方法uni.switchTab跳转刷新页面更新数据 百度的方法如下: uni.switchTab({ url: '/p ...

随机推荐

  1. python起航之路 Day1

    一.Python安装 windows 1.下载安装包 https://www.python.org/downloads/2.安装 默认安装路径:C:\python273.配置环境变量 [右键计算机]- ...

  2. hdu4585 Treap与名次树/STL map(C/C++)

    hdu4585 题目地址:https://acm.dingbacode.com/showproblem.php?pid=4585 Shaolin Time Limit: 3000/1000 MS (J ...

  3. android charles 抓不到https包,翻了2天资料总算是找到答案了

    问题, android7.0以上有权限限制,导致很多机子无法用Charles 抓ssl的包. 以下是我自己的坑请大家参考 原因一: 用Charles 工具上的地址去安装 chls.pro/ssl 原因 ...

  4. 【Android异常】关于Notification启动时,startForeground报错

    遇到两个报错: 第一个权限问题报错,好解决 startForeground requires android.permission.FOREGROUND_SERVICE Manifest给下权限就行 ...

  5. python 函数默认值误区

    当创建python函数时,默认值参数实在执行def语句的时候创建的也即是在创建该函数的时候,而不是在调用该函数的时候创建的. def append(x, lst = []): lst.append(x ...

  6. 使用TLS/SSL传输层安全机制实现web项目的通信安全

    自己的web项目在内网ip访问时,浏览器会提示不安全 原因就是因为没有证书,而传输层的TLS/SSL协议,会告诉我们本地客户端的浏览器,我现在访问的web项目的ip地址可能存在安全风险 要解决这个通信 ...

  7. django orm性能优化

    参考: django 分页查询大表,很慢 面试小知识:MySQL索引相关 MySQL 用 limit 为什么会影响性能? 前言 orm性能优化是一件很重要的事,一般万条以上的数据都需要优化处理了. 这 ...

  8. C# 图片 等 文件 读取操作 的一点提示

    源于:在读取图片时,总喜欢首先采用:Image img=Image.FromFile("");操作,这种方式由于 调用图片的程序与图片文件是通过 绝对地址关联的,会造成 当前进程或 ...

  9. revit转tileset 3dmax转tileset cesium展示

    使用revit软件导出fbx模型: 使用glTFExport导出gltf模型,导出的gltf模型具有属性.但是此处导出gltf模型,不是为了在cesium中加载该gltf模型,主要目的是获取组件属性信 ...

  10. 在Win7的64位系统中安装最新版Eclipse或STS

    Eclipse版本为:eclipse-jee-2021-12-R-win32-x86_64 STS版本为:sts-4.13.1.RELEASE 这两个版本中都自带了17.0.1的jre插件,默认会使用 ...