效果如下图:

代码如下:

<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);
}

最新文章

  1. 前端开发根据url进行页面跳转控制以及实现菜单栏手风琴效果
  2. Bellman-Ford 算法及其优化
  3. poj 1222 EXTENDED LIGHTS OUT(位运算+枚举)
  4. angularJS内置指令一览
  5. jquery 节点操作大全
  6. Android 省市县 三级联动(android-wheel的使用)
  7. 利用npoi把多个DataTable导入Excel多个sheet中
  8. A股暴跌三日市值蒸发4.2万亿 股民人均浮亏超2万
  9. stable_sort()与sort
  10. spring boot sharding-jdbc实现分佈式读写分离和分库分表的实现
  11. Web从入门到放弃&lt;3&gt;
  12. CSS3布局之多列布局columns详解
  13. if选择语句与switch选择语句的比较、区别及应用场景
  14. solt插槽的使用。
  15. labelImg:no module named pyqt4
  16. 用PNChart绘制饼状图简介
  17. Git清空历史,清空历史删除的文件,降低.git 文件大小
  18. 解决VS2010连接VSS时,Access to file&quot;\\***\rights.dat&quot; denied
  19. 【linux系列】压缩和解压缩tar
  20. Java考试题之十

热门文章

  1. 快速获取dom到body左侧和顶部的距离,简单粗暴无bug-getBoundingClientRect
  2. Android远程服务AIDL开发过程中容易遇见的两个问题
  3. git rebase 与 merge 的那些事儿~(详细图解,通俗易懂)
  4. 删除pdf中的链接
  5. .Net Reactor混淆导致匿名类处理出现的问题处理分析
  6. Spring Boot 整合 Web 开发
  7. linux 修改文件权限指令chmod
  8. 实现一个3D图片轮播插件 —— 更新版
  9. golang 你所不知道的 log 和 fmt
  10. http转换为https