微信小程序实现九宫格切图,保存功能!
效果如下图:

代码如下:
<view class='sudoku'>
<scroll-view scroll-x scroll-y class='canvas-box'>
<canvas canvas-id='canvasIn' id='canvas' class='canvas canvas-in' style='{{canvasWH}}'></canvas>
<!-- wx:if='{{canvasIn}}' -->
<!-- <canvas canvas-id='canvasOut' id='canvasOut' class='canvas canvas-out' style='{{canvasWH}}'></canvas> -->
</scroll-view>
<cover-view class='imgs'>
<cover-view class='imgs-box'>
<cover-image class='img' data-idx='{{index+1}}' src='{{item}}' style='{{maxHeight}}' wx:for='{{imgUrls}}' wx:key='{{index}}' bindtap='saveImg'></cover-image>
</cover-view>
</cover-view>
<cover-view class='btns-box'>
<button bindtap='uploadImg' class='btn btn-cut'>上传</button>
<button bindtap='saveAll' class='btn btn-save'>保存</button>
</cover-view>
</view>
let _this
Page({ /**
* 页面的初始数据
*/
data: {
canvasWH: '',
imgW: 0,
imgH: 0,
uploadFlag: false,
imgUrls: [],
maxHeight: ''
}, /* 上传图片 */
uploadImg() {
const query = wx.createSelectorQuery()
query.select('#canvas').boundingClientRect(function(res) {
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
// sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success(res) {
// 图片大小限制为 最大2M
const imgSize = res.tempFiles[0].size
console.log(res, imgSize, '已选择图片大小') if (imgSize > 1000000) {
wx.showModal({
title: '温馨提示',
content: '图片最大不能超过1M',
showCancel: false
})
return
} const ctx = wx.createCanvasContext('canvasIn')
const canvasW = res.width
const canvasH = res.height
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvasW, canvasH)
ctx.draw() // 获取图片信息
wx.getImageInfo({
src: res.tempFilePaths[0],
success(imgInfo) {
console.log(imgInfo, 'imgInfo')
const imgW = imgInfo.width
const imgH = imgInfo.height _this.setData({
canvasWH: `width: ${imgW}px;height: ${imgH}px`,
imgW,
imgH
}) // 获取图片的大小
ctx.drawImage(res.tempFilePaths[0], 0, 0, imgW, imgH)
ctx.draw()
// 展示新图片
_this.showMiniImg()
},
fail(err) {
console.log(err, '图片信息获取失败')
wx.showModal({
title: '温馨提示',
content: '暂不支持此图片格式',
showCancel: false
})
}
})
},
fail (err) {
console.log(err, '图片选择失败')
}
})
})
query.exec()
}, /* 展示小图 */
showMiniImg() {
let x = 0
let y = 0
let count = 0
let imgUrls = []
const {
imgW,
imgH
} = _this.data const cutW = imgW / 3
const cutH = imgH / 3 const cfgSave = {
x: 0,
y: 0,
width: cutW,
height: cutH,
destWidth: cutW,
destHeight: cutH,
canvasId: 'canvasIn'
}
_this.cutFlag = true const timer = setInterval(() => {
if (_this.cutFlag) {
_this.cutFlag = false
console.log(count, 'cutFlag')
switch (count) {
case 0:
x = 0
y = 0
break
case 1:
x = 1
y = 0
break
case 2:
x = 2
y = 0
break
case 3:
x = 0
y = 1
break
case 4:
x = 1
y = 1
break
case 5:
x = 2
y = 1
break
case 6:
x = 0
y = 2
break
case 7:
x = 1
y = 2
break
case 8:
x = 2
y = 2
break
default:
break
}
cfgSave.x = cutW * x
cfgSave.y = cutH * y wx.canvasToTempFilePath({
...cfgSave,
success(res) {
console.log(res, '剪切') _this.cutFlag = true
count++
wx.showLoading({
title: `裁剪中 ${count}/9`,
mask: true
})
imgUrls.push(res.tempFilePath)
if (count == 9) {
if (imgUrls.length < 9) {
imgUrls = []
cut()
return
}
wx.hideLoading()
_this.setData({
uploadFlag: true,
imgUrls
})
clearInterval(timer)
}
},
fail (err) {
console.log(err , '剪切图片失败')
}
})
}
}, 100)
}, /* 保存图片(单图 / 所有) */
saveImgHandle(e) {
const {
imgW,
imgH,
imgUrls
} = _this.data const cutW = imgW / 3
const cutH = imgH / 3 const cfgSave = {
x: 0,
y: 0,
width: cutW,
height: cutH,
destWidth: cutW,
destHeight: cutH,
canvasId: 'canvasIn',
} if (e) { //保存单张图片
switch (e.currentTarget.dataset.idx) {
case 1:
cfgSave.x = cutW * 0
cfgSave.y = cutH * 0
break
case 2:
cfgSave.x = cutW * 1
cfgSave.y = cutH * 0
break
case 3:
cfgSave.x = cutW * 2
cfgSave.y = cutH * 0
break
case 4:
cfgSave.x = cutW * 0
cfgSave.y = cutH * 1
break
case 5:
cfgSave.x = cutW * 1
cfgSave.y = cutH * 1
break
case 6:
cfgSave.x = cutW * 2
cfgSave.y = cutH * 1
break
case 7:
cfgSave.x = cutW * 0
cfgSave.y = cutH * 2
break
case 8:
cfgSave.x = cutW * 1
cfgSave.y = cutH * 2
break
case 9:
cfgSave.x = cutW * 2
cfgSave.y = cutH * 2
break
default:
break
}
wx.canvasToTempFilePath({
...cfgSave,
success(res) {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(resPhoto) {
wx.showToast({
title: '保存成功'
})
}
})
}
})
} else { //保存所有
let pathArr = []
let x = 0
let y = 0
let count = 0
_this.saveFlag = true const timer = setInterval(() => {
if (_this.saveFlag) { _this.saveFlag = false
console.log(count, 'saveFlag')
switch (count) {
case 0:
x = 0
y = 0
break
case 1:
x = 1
y = 0
break
case 2:
x = 2
y = 0
break
case 3:
x = 0
y = 1
break
case 4:
x = 1
y = 1
break
case 5:
x = 2
y = 1
break
case 6:
x = 0
y = 2
break
case 7:
x = 1
y = 2
break
case 8:
x = 2
y = 2
break
default:
break
}
cfgSave.x = cutW * x
cfgSave.y = cutH * y
wx.canvasToTempFilePath({
...cfgSave,
success(res) {
console.log(res, '保存所有') pathArr.push(res.tempFilePath)
count++
wx.showLoading({
title: `保存中${count}/9`,
})
_this.saveFlag = true
if (count == 9) {
clearInterval(timer)
console.log(pathArr)
// 保存到相册
for (let i = 0; i < pathArr.length; i++) {
wx.saveImageToPhotosAlbum({
filePath: pathArr[i],
success(resPhoto) {
_this.saveFlag = true
if (i == pathArr.length - 1) {
wx.hideLoading()
wx.showToast({
title: '保存成功'
})
}
}
})
}
}
}
})
}
}, 100)
}
}, /* 保存单张图片 */
saveImg(e) {
const {
uploadFlag
} = _this.data
// 判断是否已上传图片
if (uploadFlag) {
wx.showModal({
title: '温馨提示',
content: '要将该图片保存到相册吗?',
success(confirm) {
if (confirm.confirm) {
_this.photoAuthorization(e)
}
}
}) } else {
wx.showModal({
title: '温馨提示',
content: '请先上传图片',
showCancel: false
})
} }, /* 一键保存 */
saveAll() {
const {
uploadFlag
} = _this.data
// 判断是否已上传图片
if (uploadFlag) {
_this.photoAuthorization()
} else {
wx.showModal({
title: '温馨提示',
content: '请先上传图片',
showCancel: false
})
}
}, /* 设置显示图片的最大高度为屏幕高 */
setMaxHeight() {
wx.getSystemInfo({
success: function(res) {
console.log(res)
const windowH = res.windowHeight
const maxHeight = parseInt(windowH / 3)
_this.setData({
maxHeight: `max-height: ${maxHeight}px`
})
},
})
}, /* 相册授权 */
photoAuthorization(event) {
wx.getSetting({
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
// 已授权
if (event) {
_this.saveImgHandle(event)
} else {
_this.saveImgHandle()
}
} else {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
// 已授权
if (event) {
_this.saveImgHandle(event)
} else {
_this.saveImgHandle()
}
},
fail() {
// 未授权
wx.showModal({
title: '温馨提示',
content: '需要获取相册权限',
success(resOpenSetting) {
if (resOpenSetting.confirm) {
wx.openSetting({
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
// 已授权
if (event) {
_this.saveImgHandle(event)
} else {
_this.saveImgHandle()
}
} else {
wx.showModal({
title: '温馨提示',
content: '未获取到授权信息',
showCancel: false
})
}
}
})
}
}
})
}
})
}
}
})
}, /**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
_this = this
_this.setMaxHeight()
}, /**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() { }, /**
* 生命周期函数--监听页面显示
*/
onShow: function() { }, /**
* 生命周期函数--监听页面隐藏
*/
onHide: function() { }, /**
* 生命周期函数--监听页面卸载
*/
onUnload: function() { }, /**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() { }, /**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() { }, /**
* 用户点击右上角分享
*/
onShareAppMessage: function() { }
})
page {
height: %;
background-color: #fff;
overflow: hidden;
}
.sudoku {
height: %;
}
.canvas-box {
position: relative;
width: %;
height: %;
overflow: auto;
}
.canvas {
min-width: %;
height: %;
position: absolute;
top: ;
}
.canvas-in {
z-index: ;
}
.canvas-out {
z-index: ;
background-color: #fff;
}
.imgs{
width: %;
height: %;
position: absolute;
top: ;
z-index: ;
background-color: #fff;
}
.imgs-box{
width: %;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
padding: 8rpx;
box-sizing: border-box;
}
.img{
flex-shrink: ;
width: 33.3%;
padding: 5rpx;
box-sizing: border-box;
}
.btns-box {
position: fixed;
right: 30rpx;
bottom: 120rpx;
z-index: ;
display: flex;
justify-content: space-evenly;
flex-direction: column;
height: 300rpx;
}
.btn {
color: #fff;
width: 100rpx;
height: 100rpx;
border: none;
border-radius: %;
}
.wx-button-cover-view-wrapper {
width: %;
height: %;
display: flex;
justify-content: center;
align-items: center;
}
.wx-button-cover-view-inner {
width: %;
height: %;
display: flex;
justify-content: center;
align-items: center;
}
.btn::after {
border: none;
}
.btn-cut {
background-color: rgba(, , , 0.5);
}
.btn-save {
background-color: rgba(, , , 0.5);
}
微信小程序实现九宫格切图,保存功能!的更多相关文章
- 微信小程序的轮播图swiper问题
微信小程序的轮播图swiper,调用后,怎样覆盖系统的 点,达到自己想要的效果 不多说,先上一图望大家多给意见: 这个是效果图: 微信小程序效果图就成这样子: <view class=" ...
- 微信小程序登陆流程图时序图
微信小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 微信小程序登录流程时序图 说明 调用 wx.login() 获取 临时登录凭证cod ...
- 微信小程序 获取用户信息并保存登录状态
微信小程序 获取用户信息并保存登录状态:http://www.360doc.com/content/18/0124/11/9200790_724662071.shtml
- 微信小程序0.11.122100版本新功能解析
微信小程序0.11.122100版本新功能解析 新版本就不再吐槽了,整的自己跟个愤青似的.人老了,喷不动了,把机会留给年轻人吧.下午随着新版本开放,微信居然破天荒的开放了开发者论坛.我很是担心官方 ...
- 如何自定义微信小程序swiper轮播图面板指示点的样式
https://www.cnblogs.com/myboogle/p/6278163.html 微信小程序的swiper组件是滑块视图容器,也就是说平常我们看到的轮播图就可以用它来做,不过这个组件有很 ...
- 微信小程序之雪碧图(css script)
今天有朋友问我关于微信小程序中如何在不占用大量网络带宽的情况下快速加载图片,我给他推荐了两种方式 1.雪碧图(css script),有过前端经验的朋友应该都有接触过. 2.懒加载. 由于时间关系我就 ...
- 微信小程序之tabbar切卡
最近在研究小程序的时候,遇到了一个问题,就是tabbar切卡,在android上有fragment,在RN上也有提供一个第三方的组件来用,微信小程序,好像没有专门的一个组件来实现这个功能,度娘了大半天 ...
- 自定义微信小程序swiper轮播图面板指示点的样式
微信小程序的swiper组件是滑块视图容器,也就是说平常我们看到的轮播图就可以用它来做,不过这个组件有很多样式是固定的,但是,有时候我们的设计稿的面板指示点是需要个性化的,那么如何去修改swiper组 ...
- 【自定义轮播图】微信小程序自定义轮播图无缝滚动
先试试效果,可以通过设置参数调整样式 微信小程序中的轮播图可以直接使用swiper组件,如下: <swiper indicator-dots="{{indicatorDots}}&qu ...
随机推荐
- Java第三次作业第二题
2. [请复制本程序,作为java程序代码,进行编译,补充填写缺失代码部分,并实现题目要求功能,从而获得空白填写所需的内容.] 定义3个线程,模拟红绿灯的效果 一个线程控制画一个实心红圆 一个线程控制 ...
- [AWS] 01 - What is Amazon EMR
[DE] ML on Big data: MLlib 关于 Amazon EMR 发布版本 利用 Amazon EMR 分析大数据 Amazon Athena 是一种交互式查询服务,让您能够轻松使用标 ...
- Java线程池的拒绝策略
一.简介 jdk1.5 版本新增了JUC并发编程包,极大的简化了传统的多线程开发.前面文章中介绍了线程池的使用,链接地址:https://www.cnblogs.com/eric-fang/p/900 ...
- 大数据处理中的Lambda架构和Kappa架构
首先我们来看一个典型的互联网大数据平台的架构,如下图所示: 在这张架构图中,大数据平台里面向用户的在线业务处理组件用褐色标示出来,这部分是属于互联网在线应用的部分,其他蓝色的部分属于大数据相关组件,使 ...
- Java 基础篇之类与对象
类与对象 类.对象和引用的关系 类和对象的关系 类是对象的模版,对象是类的一个实例,一个类可以有很多对象 一个Java程序中类名相同的类只能有一个,也就是类型不会重名 一个对象只能根据一个类来创建 引 ...
- JVM调优—Jstack
Java命令学习系列(二)——Jstack jstack是java虚拟机自带的一种堆栈跟踪工具. 功能 jstack用于生成java虚拟机当前时刻的线程快照.线程快照是当前java虚拟机内每一条线 ...
- Git项目分支分配
主要分支包含master分支与develop分支,临时分支可以分为: release: 从develop分出 ,是最终要发布的版本. feature: 实现某功能时推荐新建分支,从develop分出. ...
- FastDfs之StorageServer的详细配置介绍
#这个配置文件是否失效 disabled=false #false为有效 true为无效 # 本storage server所属的group名 group_name=group1 # 可以版定一个ip ...
- .net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联
Signalr是以Group.Connect为核心来进行推送,比如,给某个组.某个连接来推送,但实际场景中,核心应该是某个组.某个人:然而一个人可以对应多个连接(浏览器多个tab页):本节就来介绍下自 ...
- Docker 第一个HelloWorld镜像
Docker 创建第一个HelloWorld镜像: 创建Dockerfile FROM alpine CMD "echo" "Hello World!" 通过D ...