当前位置:   article > 正文

【微信小程序】实现图片拖动、放大、缩小、旋转、滤镜和切图功能_微信小程序canvas缩放

微信小程序canvas缩放

本文介绍使用微信小程序API+canvas来实现图片的可拖动、放大、缩小和旋转,并可对选中的图片进行不同效果的滤镜和不同形状的切图,且可对最终效果进行保存到本地。
最终效果:
在这里插入图片描述

  1. 文件index.wxml和index.wxss代码如下,这一块比较简单,可自行查看,不做过多分析:
<view class='contentWarp'>
  <block wx:for="{{itemList}}" wx:key="id">
    <view class='touchWrap' style='transform: scale({{item.scale}});top:{{item.top}}px;left:{{item.left}}px; z-index:{{item.active?100:1}}'>
      <view class='imgWrap {{item.active? "touchActive":""}}' style="transform: rotate({{item.angle}}deg); border: {{item.active?4*item.oScale:0}}rpx #fff dashed;">
        <image src='{{item.image}}' data-id='{{item.id}}' style='width:{{item.width}}px;height:{{item.height}}px;' bindtouchstart='WraptouchStart' bindtouchmove='WraptouchMove' bindtouchend='WraptouchEnd'  mode="widthFix"></image>
        <image class='x' src='../../images/del.png' style='transform: scale({{item.oScale}});transform-origin:center;' data-id='{{item.id}}' bindtap='deleteItem'></image>
        <image class='o' src='../../images/scale.png' style='transform: scale({{item.oScale}});transform-origin:center;' data-id='{{item.id}}' bindtouchstart='oTouchStart' bindtouchmove='oTouchMove' bindtouchend='WraptouchEnd'></image>
      </view>
    </view>
  </block>
</view>
<!-- 右下角操作按钮 -->
<view class="operation-buttons">
  <image src="../../images/upload.png" bindtap="uploadImg"></image>
  <image src="../../images/fliters.png" bindtap="toggleFliters"></image>
  <image src="../../images/shapes.png" bindtap="toggleShapes"></image>
  <image src="../../images/synthesis.png" bindtap="openMask"></image>
</view>
<!-- 各种过滤效果 -->
<view class="fliters" hidden="{{!showFliters}}">
  <block wx:for="{{fliters}}" wx:key="id">
    <image data-fliter="{{item.fliter}}" src="{{item.src}}" bindtap="imgEffects"></image>
  </block>
</view>
<!-- 各种形状 -->
<view class="shapes" hidden="{{!showShapes}}">
  <block wx:for="{{shapes}}" wx:key="id">
    <image data-shape="{{item.shape}}" src="{{item.src}}" bindtap="imgEffects"></image>
  </block>
</view>
<!-- 保存显示效果图 -->
<view class='canvasWrap' hidden="{{!showCanvas}}">
  <image class="resImg" bindlongtap="saveImg" src="{{canvasTemImg}}" mode="widthFix"></image>
  <view class='btn_view'>
    <button bindtap='saveImg'>保存到手机</button>
    <button bindtap='disappearCanvas'>关闭</button>
  </view>
</view>
<!-- 画布 -->
<canvas class='maskCanvas' canvas-id="maskCanvas" style='width:{{canvasWidth}}px; height:{{canvasHeight}}px;'></canvas>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

wxss:

/**index.wxss**/
.contentWarp {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  margin: auto;
}
 
.touchWrap {
  transform-origin: center;
  position: absolute;
  z-index: 100;
}
 
.imgWrap {
  box-sizing: border-box;
  width: 100%;
  transform-origin: center;
  float: left;
  border: 5rpx transparent dashed;
}
 
.imgWrap image {
  float: left;
}
 
.touchActive .x {
  display: block;
}
 
.touchActive .o {
  display: block;
}
 
.x {
  position: absolute;
  top: -25rpx;
  left: -25rpx;
  z-index: 500;
  display: none;
  width: 50rpx;
  height: 50rpx;
  overflow: hidden;
  font-weight: bold;
  color: #d1e3f1;
}
 
.o {
  position: absolute;
  bottom: -25rpx;
  right: -25rpx;
  width: 50rpx;
  height: 50rpx;
  text-align: center;
  display: none;
  overflow: hidden;
  font-weight: bold;
  color: #d1e3f1;
}
 
.active {
  background-color: rgb(78, 114, 151);
}
 
.active view {
  border: none;
}
 
.touchActive {
  z-index: 400;
}
 
.operation-buttons {
  position: absolute;
  bottom: 100rpx;
  right: 20rpx;
  display: flex;
  flex-direction: column;
  z-index: 101;
}
 
.operation-buttons image {
  width: 100rpx;
  height: 100rpx;
  margin-top: 40rpx;
}
 
.canvasWrap {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 999;
  text-align: center;
}
 
.maskCanvas {
  position: absolute;
  left: -200%;
  top: 0;
}
 
.btnView view {
  padding-bottom: 20rpx;
}
 
.hand {
  position: absolute;
  left: 100rpx;
  right: 0;
  margin: auto;
  z-index: 100;
}
 
.getUserInfoBtn {
  position: initial;
  border: none;
  background-color: none;
}
 
.getUserInfoBtn::after {
  border: none;
}
 
.btn_view {
  display: flex;
  padding: 20rpx;
}
 
.btn_view button {
  width: 210rpx;
  font-size: 28rpx;
  background-color: #eb4985;
  color: #fff;
  line-height: 80rpx;
}
 
.resImg {
  width: 75%;
  margin-top: 10px;
}
 
/* 特效样式 */
.fliters {
  display: flex;
  flex-direction: column;
  position: absolute;
  bottom: 382rpx;
  right: 120rpx;
  z-index: 201;
}
 
.shapes {
  display: flex;
  flex-direction: column;
  position: absolute;
  bottom: 242rpx;
  right: 120rpx;
  z-index: 201;
}
 
.fliters image, .shapes image {
  width: 60rpx;
  height: 60rpx;
  border: 2rpx solid #eb4985;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  1. 文件index.js存放所有功能的逻辑代码,相对比较复杂,下面分开来分析几个重点方法:

    1)方法uploadImg+setDropItem:获取上传图片的信息,跟设置的最大宽高进行判断(maxWidth, maxHeight),然后根据判断的结果进行缩放,避免大图溢出,且设置图片的地址、坐标、定位和是否选中等信息;用于后面功能使用,支持多图使用;

    2)方法WraptouchStart+WraptouchMove:获取图片移动坐标和触发时坐标的差值,加上图片本来的坐标来实现移动效果,注意要把移动坐标赋值给触发时坐标(items[index].lx = e.touches[0].clientX),不然会导致移动有问题;

    3)方法oTouchStart+oTouchMove:获取拖动后图片的半径跟触发时图片的半径的比值,再使用scale来实现缩放功能(items[index].disPtoO / items[index].r);获取触发时的图片角度+拖动后图片的角度,再使用rotate来实现旋转功能(items[index].angle = items[index].rotate);

    4)方法imgEffects:调用滤镜方法util.imgFliters(详细可到https://jingyan.baidu.com/article/ed15cb1b9fd9bb1be3698183.html查看),根据设置的滤镜值,进行不同的滤镜处理;而调用形状方法util.imgShapes,根据设置的形状值,进行不同的切图效果;

    5)方法synthesis:用来把所有图片的最终效果合成一个画布,用于保存图片到本地使用;

    6)方法saveImg:把画布保存到本地相册。

js:

let index = 0, // 当前点击图片的index
  items = [], // 图片数组信息
  itemId = 1, // 图片id,用于识别点击图片
  fliter = 'init', // 默认过滤类型(原图)
  shape = 'init'; // 默认形状(原图)
const hCw = 1.62; // 图片宽高比
const canvasPre = 1; // 展示的canvas占mask的百分比
const maskCanvas = wx.createCanvasContext('maskCanvas', this); // 创建 canvas 的绘图上下文 CanvasContext 对象
 
const util = require('../../utils/util.js');
Page({
  /**
   * 页面的初始数据
   */
  data: {
    itemList: [],
    showFliters: false, // 默认不显示过滤效果框
    showShapes: false, // 默认不显示形状效果框
    fliters: [{
      fliter: 'init',
      src: '../../images/init.jpg'
    }, {
      fliter: 'bw',
      src: '../../images/bw.jpg'
    }, {
      fliter: 'groundGlass',
      src: '../../images/groundGlass.jpg'
    }, {
      fliter: 'pictureStory',
      src: '../../images/pictureStory.jpg'
    }, {
      fliter: 'reminiscence',
      src: '../../images/reminiscence.jpg'
    }, {
      fliter: 'sketch',
      src: '../../images/sketch.jpg'
    }],
    shapes: [{
      shape: 'circle',
      src: '../../images/init.jpg'
    }, {
      shape: 'star',
      src: '../../images/init.jpg'
    }, {
      shape: 'irregularityHeart',
      src: '../../images/init.jpg'
    }, {
      shape: 'SudokuHeart',
      src: '../../images/init.jpg'
    }]
  },
 
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    items = this.data.itemList;
    wx.getSystemInfo({ // 获取系统信息
      success: sysData => {
        this.sysData = sysData
        // 设置画布宽高,this.sysData.windowWidth为屏幕的宽度
        this.setData({
          canvasWidth: this.sysData.windowWidth * canvasPre, // 如果觉得不清晰的话,可以把所有组件、宽高放大一倍
          canvasHeight: this.sysData.windowWidth * canvasPre * hCw,
        })
      }
    })
  },
  // 上传图片
  uploadImg() {
    let that = this;
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success (res) {
        // tempFilePath可以作为img标签的src属性显示图片
        that.setDropItem({
          url: res.tempFilePaths[0]
        });
      }
    })
  },
  // 设置图片的信息
  setDropItem(imgData) {
    let data = {}; // 存储图片信息
    // 获取图片信息,网络图片需先配置download域名才能生效
    wx.getImageInfo({
      src: imgData.url,
      success: res => {
        // 初始化数据
        let maxWidth = 150, maxHeight = 150; // 设置最大宽高
        if (res.width > maxWidth || res.height > maxHeight) { // 原图宽或高大于最大值就执行
            if (res.width / res.height > maxWidth / maxHeight) { // 判断比例使用最大值的宽或高作为基数计算
                data.width = maxWidth;
                data.height = Math.round(maxWidth * (res.height / res.width));
            } else {
                data.height = maxHeight;
                data.width = Math.round(maxHeight * (res.width / res.height));
            }   
        }
        data.image = imgData.url; // 显示地址
        data.initImage = imgData.url; // 原始地址
        data.id = ++itemId; // id
        data.top = 0; // top定位
        data.left = 0; // left定位
        // 圆心坐标
        data.x = data.left + data.width / 2;
        data.y = data.top + data.height / 2;
        data.scale = 1; // scale缩放
        data.rotate = 1; // 旋转角度
        data.active = false; // 选中状态
        items[items.length] = data; // 每增加一张图片数据增加一条信息
        this.setData({
          itemList: items
        })
      }
    })
  },
  // 点击图片
  WraptouchStart: function(e) {
    // 循环图片数组获取点击的图片信息
    for (let i = 0; i < items.length; i++) {
      items[i].active = false;
      if (e.currentTarget.dataset.id == items[i].id) {
        index = i;
        items[index].active = true;
      }
    }
    this.setData({
      itemList: items
    })
 
    // 获取点击的坐标值
    items[index].lx = e.touches[0].clientX;
    items[index].ly = e.touches[0].clientY;
  },
  // 拖动图片
  WraptouchMove(e) {
    items[index]._lx = e.touches[0].clientX;
    items[index]._ly = e.touches[0].clientY;
 
    items[index].left += items[index]._lx - items[index].lx;
    items[index].top += items[index]._ly - items[index].ly;
    items[index].x += items[index]._lx - items[index].lx;
    items[index].y += items[index]._ly - items[index].ly;
 
    items[index].lx = e.touches[0].clientX;
    items[index].ly = e.touches[0].clientY;
 
    this.setData({
      itemList: items
    })
  },
  // 放开图片
  WraptouchEnd() {
    this.synthesis(); // 调用合成图方法
  },
  // 点击伸缩图标
  oTouchStart(e) {
    //找到点击的那个图片对象,并记录
    for (let i = 0; i < items.length; i++) {
      items[i].active = false;
      if (e.currentTarget.dataset.id == items[i].id) {
        index = i;
        items[index].active = true;
      }
    }
    //获取作为移动前角度的坐标
    items[index].tx = e.touches[0].clientX;
    items[index].ty = e.touches[0].clientY;
    //移动前的角度
    items[index].anglePre = this.countDeg(items[index].x, items[index].y, items[index].tx, items[index].ty);
    //获取图片半径
    items[index].r = this.getDistancs(items[index].x, items[index].y, items[index].left, items[index].top);
  },
  oTouchMove: function(e) {
    //记录移动后的位置
    items[index]._tx = e.touches[0].clientX;
    items[index]._ty = e.touches[0].clientY;
    //移动的点到圆心的距离
    items[index].disPtoO = this.getDistancs(items[index].x, items[index].y, items[index]._tx, items[index]._ty - 10)
 
    items[index].scale = items[index].disPtoO / items[index].r;
 
    //移动后位置的角度
    items[index].angleNext = this.countDeg(items[index].x, items[index].y, items[index]._tx, items[index]._ty)
    //角度差
    items[index].new_rotate = items[index].angleNext - items[index].anglePre;
 
    //叠加的角度差
    items[index].rotate += items[index].new_rotate;
    items[index].angle = items[index].rotate; //赋值
 
    //用过移动后的坐标赋值为移动前坐标
    items[index].tx = e.touches[0].clientX;
    items[index].ty = e.touches[0].clientY;
    items[index].anglePre = this.countDeg(items[index].x, items[index].y, items[index].tx, items[index].ty)
 
    //赋值setData渲染
    this.setData({
      itemList: items
    })
  },
  // 计算坐标点到圆心的距离
  getDistancs(cx, cy, pointer_x, pointer_y) {
    var ox = pointer_x - cx;
    var oy = pointer_y - cy;
    return Math.sqrt(
      ox * ox + oy * oy
    );
  },
  /*
   *参数cx和cy为图片圆心坐标
   *参数pointer_x和pointer_y为手点击的坐标
   *返回值为手点击的坐标到圆心的角度
   */
  countDeg: function(cx, cy, pointer_x, pointer_y) {
    var ox = pointer_x - cx;
    var oy = pointer_y - cy;
    var to = Math.abs(ox / oy);
    var angle = Math.atan(to) / (2 * Math.PI) * 360;
    if (ox < 0 && oy < 0) //相对在左上角,第四象限,js中坐标系是从左上角开始的,这里的象限是正常坐标系  
    {
      angle = -angle;
    } else if (ox <= 0 && oy >= 0) //左下角,3象限  
    {
      angle = -(180 - angle)
    } else if (ox > 0 && oy < 0) //右上角,1象限  
    {
      angle = angle;
    } else if (ox > 0 && oy > 0) //右下角,2象限  
    {
      angle = 180 - angle;
    }
    return angle;
  },
  deleteItem: function(e) {
    let newList = [];
    for (let i = 0; i < items.length; i++) {
      if (e.currentTarget.dataset.id != items[i].id) {
        newList.push(items[i])
      }
    }
    if (newList.length > 0) {
      newList[newList.length - 1].active = true; // 剩下图片组最后一个选中
    }
    items = newList;
    this.setData({
      itemList: items
    })
  },
  // 打开遮罩层
  openMask() {
    this.synthesis();
    this.setData({
      showCanvas: true
    })
  },
  synthesis() { // 合成图片
    maskCanvas.save();
    maskCanvas.beginPath();
 
    // 画背景色(白色)
    maskCanvas.setFillStyle('#fff');
    maskCanvas.fillRect(0, 0, this.data.canvasWidth, this.data.canvasHeight);
 
    items.forEach((currentValue, index) => {
      maskCanvas.save();
      maskCanvas.translate(0, 0);
      maskCanvas.beginPath();
      maskCanvas.translate(currentValue.x, currentValue.y); // 圆心坐标
      maskCanvas.rotate(currentValue.angle * Math.PI / 180);
      maskCanvas.translate(-(currentValue.width * currentValue.scale / 2), -(currentValue.height * currentValue.scale / 2))
      maskCanvas.drawImage(currentValue.image, 0, 0, currentValue.width * currentValue.scale, currentValue.height * currentValue.scale);
      maskCanvas.restore();
    })
    // reserve 参数为 false,则在本次调用绘制之前 native 层会先清空画布再继续绘制
    maskCanvas.draw(false, (e) => {
      wx.canvasToTempFilePath({
        canvasId: 'maskCanvas',
        success: res => {
          this.setData({
            canvasTemImg: res.tempFilePath
          })
        }
      }, this);
    })
  },
  // 点击切换显示过滤框
  toggleFliters() {
    this.setData({
      showFliters: !this.data.showFliters,
      showShapes: false
    });
  },
  // 点击切换显示形状框
  toggleShapes() {
    this.setData({
      showShapes: !this.data.showShapes,
      showFliters: false
    });
  },
  // 图片特效
  imgEffects(e) {
    fliter = e.currentTarget.dataset.fliter || 'init';
    shape = e.currentTarget.dataset.shape || 'init';
    let that = this;
    items.forEach((currentValue, index) => {
      if (currentValue.active) {
        maskCanvas.save();
        maskCanvas.beginPath();
        util.imgShapes(maskCanvas, 0, 0, currentValue.width, currentValue.width, shape, 0, currentValue); // 图片剪切不同形状
        maskCanvas.clearRect(0, 0, currentValue.width, currentValue.height);
        maskCanvas.drawImage(currentValue.initImage, 0, 0, currentValue.width, currentValue.height);
 
        maskCanvas.draw(false, function() {
          wx.canvasGetImageData({ // 获取canvas区域的像素数据
            canvasId: 'maskCanvas',
            x: 0,
            y: 0,
            width: currentValue.width,
            height: currentValue.height,
            success(res) {
              let imageData = res.data;
              util.imgFliters(maskCanvas, fliter, res); // 调用图片滤镜函数
 
              maskCanvas.clearRect(0, 0, currentValue.width, currentValue.height); // 清除旧的,不然会导致卡顿
 
              maskCanvas.restore();
              wx.canvasPutImageData({ // 将像素数据绘制到canvas
                canvasId: 'maskCanvas',
                x: 0,
                y: 0,
                width: currentValue.width,
                height: currentValue.height,
                data: imageData,
                success(res) {
                  wx.canvasToTempFilePath({
                    canvasId: 'maskCanvas',
                    width: currentValue.width,
                    height: currentValue.height,
                    destWidth: currentValue.width,
                    destHeight: currentValue.height,
                    success: res => {
                      items[index].image = res.tempFilePath
                      that.setData({
                        itemList: items
                      })
                    }
                  }, this)
                }
              })
            }
          });
        })
      };
    })
  },
  // 关闭遮罩层
  disappearCanvas() {
    this.setData({
      showCanvas: false
    })
  },
  // 保存图片到系统相册
  saveImg: function() {
    wx.saveImageToPhotosAlbum({
      filePath: this.data.canvasTemImg,
      success: res => {
        wx.showToast({
          title: '保存成功',
          icon: "success"
        })
      },
      fail: res => {
        wx.openSetting({
          success: settingdata => {
            if (settingdata.authSetting['scope.writePhotosAlbum']) {
              console.log('获取权限成功,给出再次点击图片保存到相册的提示。')
            } else {
              console.log('获取权限失败,给出不给权限就无法正常使用的提示')
            }
          },
          fail: error => {
            console.log(error)
          }
        })
        wx.showModal({
          title: '提示',
          content: '保存失败,请确保相册权限已打开',
        })
      }
    })
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/384325
推荐阅读
相关标签
  

闽ICP备14008679号