uniapp实现拍照涂鸦
admin
2024-03-21 05:44:53
0

为什么要实现这个功能?

uniapp做的项目,某些页面有拍照功能,就单纯的调用摄像头拍照,却无法对照片进行编辑标注。属于优化项,但是可以有的那种。

实现思路和逻辑 

只是简单的涂鸦,像在图片上签名一样,没有那种美颜啥的功能,所以难度不是很大。思路也比较简单:

1.接收到相机拍摄到的图片

2.将图片导入进canvas中

3.对canvas监听开始触摸事件和触摸移动事件

4.将canvas导出图片,返回给上一个页面。

 参考文章

实现过程中参考了其他博主的文章,文章链接如下:

 https://www.cnblogs.com/buaa17373407hjh/p/12970816.html

 https://www.cnblogs.com/CaraganaMicrophylla/p/16381145.html

实现代码 

 两个方面,一个是拍照之后直接将图片传到编辑页面。第二个是,从图片预览去将图片传入编辑页面。

拍照逻辑

				uni.chooseImage({count: 1,sourceType: 拍照的话使用['camera'],sizeType: ['compressed'],success : function(res){uni.navigateTo({url:照片编辑页面的url,events: {acceptDataFromOpenedPage: function(data) {console.log(data)},getEditCompleteImg: function(imgData) {// 代码处理逻辑,用数组存id和资源picturesArray.push({id: 自定义值,src: imgData中的图片url})}},success:function(openRes){openRes.eventChannel.emit('acceptDataFromOpenerPage', { data: res.tempFilePaths[0] })}})},fail: function(error){console.log(error);},complete: function(res){console.log(res);}})

 chooseImage方法和navigateTo方法在uniapp的官网都有具体文档。

https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage 

 uni.navigateTo(OBJECT) | uni-app官网

 success是打开另一个页面成功后,将数据传过去,代码里面传递的是图片的url。

events是注册的事件监听,可以在图片编辑页面,重新将数据传递回来。

选择照片逻辑

主要是调用uniapp的图片预览功能,支持长按弹出菜单项。代码如下

				uni.previewImage({urls,    // 图片资源url组成的数组current,        // 默认打开的下标longPressActions: {itemList:['编辑图片'],success:function(data){console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片')// 拿到图片的url     urls[data.index]// 关闭图片预览,跳转到图片编辑页面plus.nativeUI.closePreviewImage();uni.navigateTo({url:图片编辑页面的url,events: {acceptDataFromOpenedPage: function(data) {console.log(data)},getEditCompleteImg: function(imgData) {console.log(imgData)// 和之前一样的处理逻辑}},success:function(res){res.eventChannel.emit('acceptDataFromOpenerPage', { data: urls[data.index] })}})},error:function(err){console.log(err)}}})

 uni.chooseImage(OBJECT) | uni-app官网

图片编辑逻辑 

需要一个canvas来将图片绘制。一个编辑保存按钮,一个清除重置按钮。

编辑保存按钮逻辑 

				uni.canvasToTempFilePath({canvasId: 'shareCanvas',    // canvas元素的id值destHeight: this.initImgHeight,    // initImgHeight是传入图片时获取到的图片高度destWidth: this.initImgWidth,        // 传入图片原先的宽度success: function (res) {// eventChannel.emit('someEvent', {data: 'data from test page for someEvent'});vm.eventChannel.emit('getEditCompleteImg', {data: res.tempFilePath});// 返回页面uni.navigateBack()}})

 清除重置按钮逻辑

                // 清除重新绘制let vm = this;console.log('重新绘制')// 重新绘制图片   targetImgUrl为原先图片的url    editWidth是canvas的宽度vm.drawContext.drawImage(vm.targetImgUrl,0,0,vm.editWidth,vm.editHeight)vm.drawContext.draw()// 重新设置颜色    这是封装的一个方法,画笔颜色宽度什么的vm.updateDrawContext()

在mounted中拿到canvas的宽度,高度在拿到图片的高度宽度信息获取宽高比后,动态设置高度。

			uni.createSelectorQuery().in(this).select(canvas元素设置的类名).boundingClientRect(data => {// console.log(JSON.stringify(data))// {"id":"","dataset":{},"left":12,"right":308,"top":12,"bottom":315,"width":296,"height":303}// this.editHeight = data.heightthis.editWidth = data.widthconsole.log('读取到的',this.editWidth)}).exec()

在onLoad里面获取图片的url,然后获取图片的高度和宽度存到data中。

			const ctx = uni.createCanvasContext(canvas元素设置的id值)// 设置线条this.drawContext = ctxlet vm = thisvm.eventChannel.on('acceptDataFromOpenerPage', function(data) {console.log(data)vm.targetImgUrl = data.data// 获取图片的宽高uni.getImageInfo({src: data.data,success: function (image) {vm.initImgWidth = image.width;vm.initImgHeight = image.height;console.log('图片高度:',vm.initImgHeight)console.log('图片宽度:',vm.initImgWidth)console.log('图片纵横比',image.width/image.height)// 避免图片拉伸,保持纵横比const widthHeight = image.height/image.widthvm.editHeight = widthHeight*vm.editWidthconsole.log('画布的高度',vm.editHeight)console.log('画布的宽度',vm.editWidth)vm.drawContext.drawImage(data.data,0,0,vm.editWidth,vm.editHeight)vm.drawContext.draw()// 设置画笔颜色vm.updateDrawContext()},error: function (err) {console.log(err)},complete:function(end){console.log(end)}});})

导航栏返回和底部手机返回键

在onBackPress中设置

图片涂鸦绘制逻辑 

在getImageInfo中,已经将图片绘制到canvas中。剩下的就是设置canvas的开始触摸事件,触摸滑动事件,触摸结束事件等。

具体逻辑可以看这篇文章,canvas签名的逻辑,也是参考文章中的链接: 

uniapp中使用canvas - 小兔儿_乖乖 - 博客园

			touchstart: function (e) {// 取出x、y的值let {x,y} = e.changedTouches[0]// 绘制线条起点this.drawContext.beginPath()this.drawContext.moveTo(x, y)// 起点与移动的连接断开this.moveX = ''this.moveY = ''},touchmove: function (e) {// 取出x, y的值let {x,y} = e.changedTouches[0]// 防止线条出现断点if (this.moveX && this.moveY) {this.drawContext.moveTo(this.moveX, this.moveY)this.drawContext.lineTo(this.moveX, this.moveY)}this.drawContext.lineTo(x, y)this.moveX = xthis.moveY = ythis.drawContext.stroke()// ture,保留之前的内容this.drawContext.draw(true)},

 

相关内容

热门资讯

在黄龙看流星雨!四川黄龙景区举... 8月是英仙座流星雨最佳观测期 封面新闻记者 杨金祝 8月15日至17日,为期三天的“星耀黄龙,探秘英...
开屏跑腿|昆明瀑布公园为何无水... 最近,有市民向开屏新闻反映,他们在位于北市区的昆明瀑布公园游玩时发现,公园里的瀑布居然是干的,一点水...
金鞭溪景区执法人员紧急救助外籍... 近日,金鞭溪景区上演了一幕暖心救援:一名越南籍游客因蜂蛰引发严重过敏,生命垂危之际,景区执法中队突破...
雷曼光电LED户外广告屏登陆南... 在非洲广阔湛蓝的天空与充满活力的城市背景之下,雷曼光电的LED户外显示屏,为南非主要城市约翰内斯堡某...
洪峰过境,山西黄河壶口瀑布旅游... 8月19日,山西黄河壶口瀑布旅游区对外通报,因洪峰过境,黄河壶口瀑布旅游区(山西·吉县)水位较高,不...
抓住暑期尾巴!来釜山露营吧 随着暑假接近尾声 不少市民游客选择走出家门 奔赴山间乡野 露营等户外休闲方式持续升温 大家踏青赏景、...
泡制菟丝子药酒的最佳选择:清香... 菟丝子作为一种传统的中药材,常被用于药酒泡制中,被认为能帮助养生保健。泡酒这种方式能够将菟丝子的有效...
古井贡酒推出26度年份原浆“轻... 8月19日,《每日经济新闻》记者从古井贡酒获悉,公司正式推出年份原浆“轻度古20”,该产品容量为37...
早餐新选择:煎饼果子,营养美味... 清晨的街头,煎饼果子摊前永远排着长队。那香气腾腾的饼皮、滋滋冒油的鸡蛋,搭配上酥脆的薄脆,一口下去,...
恩施旅游隐藏玩法全攻略!让你玩... 恩施土家族苗族自治州,这个藏在湖北西南部的秘境,远不止大峡谷和土司城那么简单!今天小编带你解锁那些连...
平价早餐、咖啡水饮即将上线!让... “有了这个服务点方便多了!”一早从上海赶到无锡参加葬礼的邱老伯在生命旅人咖啡店买了两瓶矿泉水。 据悉...
500亿文创酒宴开席,“黄小西... 当飞天茅台价格剧烈波动时,茅台官方转身将更多精力投向文创酒领域,试图通过文创酒的差异化布局分散单一产...
145万人次参加!滇池国际咖啡... 8月18日,为期9天的2025滇池国际咖啡文化嘉年华正式落下帷幕。这场以“与全球共萃、与万物共生”为...
微生物配方解锁巧克力新风味!科... 你知道吗?巧克力的香味居然能被‘调教’出来! 最近一项研究火了,科学家发现通过控制可可豆发酵过程...
以真材实料做良心糕点,用一片初... 推开新疆塔城市疆趣食品厂的门,浓郁的麦香与烘烤的暖意瞬间包裹全身。老板王会鹏站在操作间门口,指尖还沾...
别错过秋天的“滋补宝”!入秋吃... 内容整理自:中国中医药报 进入秋季,即使处于阴雨天气,人们依然会觉得身体干燥了许多。此时从饮食养生的...
【汤医科普】二十四节气里的养生... 当世界卫生组织(WHO)将“气候适应性健康”列为全球公共卫生重点议题时,中国年轻人正在用保温杯里泡枸...
“出伏”后身体最怕这3件事!养... 8月18日是三伏天的最后一天 长达30天的三伏终于画上句号 一年中暑气最盛的日子要结束了 即将开启凉...
原创 吃... 一碗面七个人吃还要无限次续面,这是有多大的心脏才能想到这个办法。 我支持店家的做法,续面两次,已经做...