|
|
- Page({
-
- data: {
- // movable-view左上角相对于movable-area的坐标x,y,
- // 由于movable-area左上角位于屏幕原点,因此x,y也是movable-view相对于屏幕的坐标
- x: 0,
- y: 0,
- scale: 1, // 用来控制moveable-view的缩放比例,回撤重置时需要
-
- src: {
- // 图片的源文件数据
- path: '',
- orientation: 'up',
- // width和height在最初时和屏幕尺寸做比较,做一个合适的缩放
- // 在截图的时候,计算方框在源图片的位置也需要用到width和height
- width: 0,
- height: 0,
- ratio: 1, // 图片的长宽比,最开始需要根据ratio判断图片的形状是长图还是宽图,进行合适的居中放置
- },
- image: {
- // 最初图片在屏幕上显示的宽度和高度
- // 经过缩放后也是基于这两个尺寸计算新的尺寸
- initialWidth: 0,
- initialHeight: 0,
- // 控制最初图片在屏幕中的位置
- initialX: 0,
- initialY: 0,
- // 经过缩放移动后图片在屏幕中的位置
- // 截图时找方框在源图片中的位置,是基于屏幕坐标系,所以需要图片的当前位置
- curX: 0,
- curY: 0,
- // 图片当前的缩放比例,用于计算图片当前显示的尺寸大小
- curScale: 1
- },
- // 屏幕尺寸windowWidth和windowHeight
- windowWidth: 0,
- windowHeight: 0,
- cropBorder: {
- // 截图的方框相对于屏幕中的位置
- x: 0,
- y: 0,
- // 截图方框的尺寸
- size: 0
- },
- },
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad: function(options) {
- this.takePhoto()
- },
- setImgInfo(options){
- let that = this;
- let _src = JSON.parse(options);
- _src.ratio = _src.height / _src.width;
- let systemInfo = wx.getSystemInfoSync();
- // 屏幕内框范围(这里定义左右边界30,上下边际50)
- // 但是因为movable-view能超出movable-area的范围太小,为了尽量放大图片的活动范围,这里取消了这个边界
- // let borderWidth = systemInfo.windowWidth - 2 * 30
- // let borderHeight = systemInfo.windowHeight - 2 * 50
- let _image = that.data.image
- if (_src.width > systemInfo.windowWidth && _src.height > systemInfo.windowHeight) {
- // 如果图片尺寸大于屏幕尺寸,需要缩放
- if (_src.ratio > 1) {
- // 如果是长图,按照宽度进行缩放
- _image.initialWidth = systemInfo.windowWidth
- // >> 0用来取整
- _image.initialHeight = (_src.ratio * systemInfo.windowWidth) >> 0
- } else {
- // 如果是宽图,按照高度进行缩放
- _image.initialWidth = systemInfo.windowHeight,
- _image.initialHeight = (systemInfo.windowHeight / _src.ratio) >> 0
- }
- } else {
- _image.initialWidth = _src.width
- _image.initialHeight = _src.height
- }
- // 控制图片在屏幕居中
- _image.initialX = 0//(systemInfo.windowWidth - _image.initialWidth) >> 1
- _image.initialY = 0//(systemInfo.windowHeight - _image.initialHeight) >> 1
- console.log(JSON.stringify(_image))
- // 定义方框的位置和尺寸
- let _cropBorder = {}
- _cropBorder.size = systemInfo.windowWidth * 0.8
- _cropBorder.x = (systemInfo.windowWidth - _cropBorder.size) >> 1
- _cropBorder.y = (systemInfo.windowHeight - _cropBorder.size) >> 1
- that.setData({
- src: _src,
- image: _image,
- cropBorder: _cropBorder,
- windowWidth: systemInfo.windowWidth,
- windowHeight: systemInfo.windowHeight
- })
-
- setTimeout(()=>{
- that.drawFrame()
- },500)
- },
- /**
- * 移动movable-view的回调
- */
- onChange(e) {
- console.log(e.detail)
- let that = this;
- that.setData({
- 'image.curX': e.detail.x,
- 'image.curY': e.detail.y
- })
- },
-
- /**
- * 缩放moveable-view的回调
- */
- onScale(e) {
- console.log(e.detail)
- let that = this;
- that.setData({
- 'image.curX': e.detail.x,
- 'image.curY': e.detail.y,
- 'image.curScale': e.detail.scale
- })
- },
- // 拍照
- takePhoto() {
- var that=this,
- width = that.data.screenW,
- height = that.data.screenW;
- wx.chooseImage({
- count:1,
- sizeType: ['original', 'compressed'],
- sourceType: ['album', 'camera'],
- success:function(res){
- const tempFilePaths = res.tempFilePaths[0];
- wx.getImageInfo({
- src: tempFilePaths,
- success: function(msg) {
- let data = JSON.stringify(msg)
- that.setImgInfo(data)
- }
- })
- },
- fail:function(error){
- console.error("调用本地相册文件时出错")
- console.warn(error)
- },
- // // 确定提交图片
- // complete:function(back){
- // console.log(back)
- // }
- })
- },
- // 绘制方框
- drawFrame(){
- let that = this;
- let cropBorder = that.data.cropBorder
- console.log(cropBorder,"cropBorder")
- this.context = wx.createCanvasContext('myCanvas')
- // 设置背景黑色透明度0.5,不要使用opacity,会导致后期截出来的图片也是半透明
- this.context.setFillStyle('rgba(0,0,0,0.5)')
- this.context.fillRect(0, 0, that.data.windowWidth, that.data.windowHeight)
- // 挖出来一个方框,这个方框区域就是全透明了
- this.context.clearRect(cropBorder.x, cropBorder.y, cropBorder.size, cropBorder.size * (4/3))
- // 画方框的外框
- this.context.setStrokeStyle('white')
- // 往外画大一圈,这样在canvas上填充图片的时候框线就不会变细啦
- this.context.strokeRect(cropBorder.x - 1, cropBorder.y - 1, cropBorder.size + 2, (cropBorder.size * (4/3)) + 2)
- this.context.draw()
- },
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady: function() {
- // let that = this;
- // let cropBorder = that.data.cropBorder
- // this.context = wx.createCanvasContext('myCanvas')
- // // 设置背景黑色透明度0.5,不要使用opacity,会导致后期截出来的图片也是半透明
- // this.context.setFillStyle('rgba(0,0,0,0.5)')
- // this.context.fillRect(0, 0, that.data.windowWidth, that.data.windowHeight)
- // // 挖出来一个方框,这个方框区域就是全透明了
- // this.context.clearRect(cropBorder.x, cropBorder.y, cropBorder.size, cropBorder.size)
- // // 画方框的外框
- // this.context.setStrokeStyle('white')
- // // 往外画大一圈,这样在canvas上填充图片的时候框线就不会变细啦
- // this.context.strokeRect(cropBorder.x - 1, cropBorder.y - 1, cropBorder.size + 2, cropBorder.size + 2)
- // this.context.draw()
- },
-
- /**
- * 取消截图
- */
- cancel(event) {
- wx.navigateBack()
- },
-
- /**
- * 回撤,这地方有个问题:
- * 本来是想图片一次性移动和缩放回到最初的位置和大小,但是发现点击第一次只能实现图片移动到初始点
- * 点击第二次才是缩放到初始大小
- * 后来发现小程序移动有一个过程,会不停地回调onChange(),
- * 如果一定要实现,只能是当onChange中x,y归0之后再控制缩放,
- * 但是x和y是浮点数,零判断不精确而且影响性能,所以放弃了。
- */
- reset(event) {
- let that = this;
- that.setData({
- scale: 1,
- x: 0,
- y: 0,
- })
- },
-
- /**
- * 点击完成的回调
- * 完成截图,回传图片到上一页
- */
- complete(event) {
- let that = this
- let src = that.data.src
- console.log(src)
- let cropBorder = this.data.cropBorder
- let image = that.data.image
- // 当前图片显示的大小
- let curImageWidth = image.initialWidth * image.curScale
- let curImageHeight = image.initialHeight * image.curScale
- // 将方框位置换算到源图片中的位置srcX,srcY
- let srcX = (cropBorder.x - image.curX) / curImageWidth * src.width
- // canvas的height是100%,而bottom是120rpx,因此canvas的位置不是在原点,需要减去这个120rpx
- // 置于这里为什么要有个120,因为底部栏也是透明的,但字是亮的,我想呈现底部栏在上方不被遮罩挡住的效果
- let srcY = (cropBorder.y - image.curY - 120 / 750 * that.data.windowWidth) / curImageHeight * src.height
- // 方框区域映射到源图片中的尺寸
- let srcWidth = cropBorder.size / curImageWidth * src.width
- let srcHeight = (cropBorder.size * (4/3)) / curImageHeight * src.height
- console.log('srcX = ' + srcX + ', srcY = ' + srcY + ', srcWidth = ' + srcWidth + ', srcHeight = ' + srcHeight + ', cropX = ' + cropBorder.x + ', cropY = ' + cropBorder.y + ', cropSize = ' + cropBorder.size)
- // 绘制图片不要透明啦,不然会看到重影
- this.context.setFillStyle('rgba(0,0,0,1)')
- // 鉴于尺寸的精确度,方框内图片的覆盖在y方向会有微微的偏移,
- // 但是一旦截图就返回上一页了,强迫症患者没有后悔的余地。
- this.context.drawImage(src.path, srcX, srcY, srcWidth, srcHeight, cropBorder.x, cropBorder.y, cropBorder.size, cropBorder.size)
- // 这里绘图一定要有回调,不然图片还没绘制完成就截图那就GG了
- this.context.draw(true, function(res) {
- wx.canvasToTempFilePath({
- canvasId: 'myCanvas',
- x: cropBorder.x,
- y: cropBorder.y,
- width: cropBorder.size,
- height: cropBorder.size,
- destWidth: cropBorder.size,
- destHeight: cropBorder.size,
- fileType: 'jpg',
- success: function(data) {
- console.log(data)
- // 将图片回传到上一页
- var pages = getCurrentPages();
- if (pages.length > 1) {
- var prePage = pages[pages.length - 2];
- var facepicture = wx.getFileSystemManager().readFileSync(data.tempFilePath, "base64")
- prePage.setData({
- avatarPath: data.tempFilePath,
- chooseface: true,
- facepic: `${facepicture}`
- })
- }
- wx.navigateBack()
- },
- fail: function(err) {
- console.log(err)
- }
- })
- })
- },
-
- /**
- * 生命周期函数--监听页面显示
- */
- onShow: function() {
-
- },
-
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide: function() {
-
- },
-
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload: function() {
-
- },
-
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh: function() {
-
- },
-
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom: function() {
-
- },
-
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage: function() {
-
- }
- })
|