微信小程序·上传头像剪切图片到本地

微信小程序·上传头像剪切图片到本地

微信小程序·上传头像剪切图片到本地

组件化

.wxml 子组件文件

<view class="container">
  <view class="top {{moving?'bg-5':'bg-9'}}" style="height:{{(systemInfo.windowHeight-300)/2}}px;"></view>
  <view class="left {{moving?'bg-5':'bg-9'}}" style="width: {{(systemInfo.windowWidth-300)/2}}px;top: {{(systemInfo.windowHeight-300)/2}}px;height: 300px;"></view>
  <view class="right {{moving?'bg-5':'bg-9'}}" style="width: {{(systemInfo.windowWidth-300)/2}}px;top: {{(systemInfo.windowHeight-300)/2}}px;height: 300px;"></view>
  <view class="bottom {{moving?'bg-5':'bg-9'}}" style="top:{{(systemInfo.windowHeight-300)/2+300}}px;"></view>
  <canvas canvas-id="myCanvas" class="canvas">

  </canvas>
  <movable-area scale-area class="movable-area" style="top: {{(systemInfo.windowHeight-300)/2}}px;left: {{(systemInfo.windowWidth-300)/2}}px;">
    <movable-view scale-min="1" animation="{{false}}" bindscale="onScale" bindchange="onMove" x="{{x}}" y="{{y}}" scale direction="all" style="width: {{image_w}}px;height: {{image_h}}px;">
      <image class="image" bindload="onImageLoad" src="{{imageUrl}}"></image>
    </movable-view>
  </movable-area>
  <view class="footer">
    <view class="button" bindtap="cancel">取消</view>
    <view class="button" style="background-color: #4CE0E0;color: #fff;" bindtap="getImage">确定</view>
  </view>
</view>

.wxss 子组件文件

.container {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  background: #000;
  z-index: 80;
}

.top {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 99;
}

.left {
  position: fixed;
  left: 0;
  z-index: 99;
}

.right {
  position: fixed;
  right: 0;
  z-index: 99;
}

.bottom {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 99;
}

.bg-5 {
  background: rgba(0, 0, 0, 0.3);
}

.bg-9 {
  background: rgba(0, 0, 0, 0.8);
  transition-duration: .5s;
  transition-property: background;
}

.canvas {
  position: absolute;
  top: 0;
  left: -1000px;
  width: 300px;
  height: 300px;
}

.movable-area {
  position: fixed;
  width: 300px;
  height: 300px;
}

.image {
  width: 100%;
  height: 100%;
  display: flex;
}

.footer {
  position: absolute;
  left: 0;
  bottom: 0;
  padding-bottom: env(safe-area-inset-bottom);
  height: calc(140rpx + env(safe-area-inset-bottom));
  width: 100%;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  z-index: 100;
  background-color: rgba(0, 0, 0, 0.8);
  box-sizing: border-box;
}

.button {
  width: 300rpx;
  height: 100rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #fff;
  border-radius: 100rpx;
  margin-left: 50rpx;
}

.js 子组件文件

const debounce = function (fn, delay = 3000) {
  let timer = null
  const _debounce = function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
  return _debounce
}
Component({
  properties: {
    imageUrl: {
      type: String,
      value: ''
    },
    show: {
      type: Boolean,
      value: false
    }
  },
  data: {
    moving: false,
  },
  lifetimes: {
    ready() {
      this.context = wx.createCanvasContext('myCanvas', this);
      this.setData({
        systemInfo: wx.getSystemInfoSync()
      })
    }
  },
  methods: {
    // 初始化图片大小
    onImageLoad: function (e) {
      let {
        width,
        height
      } = e.detail, h = 300, w = 300, x = 0, y = 0;
      if (width < height) {
        h = height * w / width;
        y = -(h - 300) / 2;
      }
      if (height < width) {
        w = width * h / height;
        x = -(w - 300) / 2;
      }
      this.x = x;
      this.y = y;
      this.scale = 1;
      this.setData({
        image_w: w,
        image_h: h,
        original_w: width,
        original_h: height,
        x,
        y
      })
      this.getDramParams();
    },
    getDramParams: function () {
      let {
        original_w,
        original_h,
        image_w,
        image_h
      } = this.data, {
        x,
        y,
        scale
      } = this;
      //console.log(x, y, scale)
      let sourceX = Math.abs(original_h * x / image_h),
        sourceY = Math.abs(original_w * y / image_w);
      this.context.drawImage(this.properties.imageUrl, sourceX / scale, sourceY / scale, Math.min(original_h, original_w) / scale, Math.min(original_h, original_w) / scale, 0, 0, 300, 300);
      this.context.draw()
    },
    // 获取图片
    getImage: function () {
      wx.canvasToTempFilePath({
        canvasId: 'myCanvas',
        success: res => {
          //console.log(res)
          this.setData({
            image: res.tempFilePath,
            show: false
          })
          this.triggerEvent('returnImageUrl', {
            imageUrl: res.tempFilePath
          })
        }
      }, this)
    },
    // 拖动图片
    onMove: function (e) {
      //console.log(e)
      let {
        x,
        y
      } = e.detail;
      this.x = x;
      this.y = y;
      this.setBg();
      debounce(this.getDramParams(), 300)
    },
    onScale: function (e) {
      let {
        x,
        y,
        scale
      } = e.detail;
      this.x = x;
      this.y = y;
      this.scale = scale;
      this.setBg();
      debounce(this.getDramParams(), 300)
    },
    setBg: function () {
      if (!this.data.moving) {
        this.setData({
          moving: true
        })
      }
      if (this.timer) clearInterval(this.timer);
      let count = 0;
      this.timer = setInterval(() => {
        count += 1000;
        if (count >= 1000) {
          clearInterval(this.timer);
          this.setData({
            moving: false
          })
        }
      }, 1000);
    },
    cancel: function (e) {
      this.setData({
        show: false
      })
    }
  }
})

父组件 引用方式: imageUrl 本地图像图片地址 bind:returnImageUrl 为接收剪切后保存图片地址

<img_photo imageUrl="{{url}}" bind:returnImageUrl="putImageUrl" ></img_photo>

708 Views
分享你的喜爱
linwute
linwute

我要像梦一样自由,像大地一样宽容;
在艰辛放逐的路上,点亮生命的光芒;
我要像梦一样自由,像天空一样坚强;
在曲折蜿蜒的路上,体验生命的意义;

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注