图像裁剪器 Cropperjs

近日前端项目中,需要实现上传图片、支持自定义裁剪,生成海报的功能。该项目采用Taro(react语法)实现。具体实现步骤如下:

1、插件安装

yarn add cropperjs -S 

2、引入

在项目中引入cropperjs,一定不要忘记引入样式

import Cropper from "cropperjs"
import "cropperjs/dist/cropper.css"

3、代码实现

import Taro, { Component } from "@tarojs/taro"
import { View, Image, Button } from "@tarojs/components"

import * as Api from "@/api/light"

import { to } from "@/utils/router"
import { toast } from "@/utils/feedBack"
import { lightShare } from "@/utils/share"

import "./index.less"

import Cropper from "cropperjs"
import "cropperjs/dist/cropper.css"
export default class Index extends Component {
  state = {
    picture_img: "",
    afterImg: "", // 确认裁剪的图片
    produceImg: "", // 生成图片
    myCropper: null,
    isUpload: false, // 是否已上传图片
    isCreated: false // 是否已裁剪生成图片
  }

  componentDidShow() {
    const { code = "" } = this.$router.params

    lightShare({
      link: `${window.location.href
        .split("?")[0]
        .replace("makePoster", "light")}?code=${code}`
    })
  }

  componentDidMount() {
    const options = {
      viewMode: 1,
      dragMode: "none",
      initialAspectRatio: 1,
      aspectRatio: 0.8,     // 设置宽高比例
      preview: ".before",
      background: true,    //显示容器的网格背景。(就是后面的马赛克)
      autoCropArea: 0.6,
      zoomOnWheel: false,
      ready: () => {
        const { width, height } = this.myCropper.getContainerData().   // 获取上传图片宽高信息
        this.myCropper.setCropBoxData({        //  设置裁剪区域(初始设置最大裁剪区域)
          width,
          left: 0,
          top: 0
        })
      }
    }
    this.myCropper = new Cropper(this.img.imgRef, options)
  }

  toBack = () => {
    to({ name: "light" })
  }

  // 上传图片
  onPicture = async () => {
    Taro.chooseImage({
      count: 1,
      success: res => {
        this.setState({
          picture_img: res.tempFilePaths[0],
          isUpload: true
        })
      },
      fail: e => {
        console.log(e)
      }
    })
  }

  // 生成海报
  createPoster = async () => {
    const { picture_img, afterImg, isCreated, produceImg } = this.state
    if (!picture_img) return toast("请上传照片!")
    const { base_url, img_url } = await Api.sharePoster({
      avatar_base64: afterImg
    })
    this.setState({
      produceImg: base_url + img_url,
      isCreated: true,
      isUpload: true
    })
  }

  // 取消
  onCancel = () => {
    const { isUpload } = this.state
    this.setState({
      isUpload: false,
      picture_img: ""
    })
  }

  // 确认裁剪
  onConfirm = () => {
    const pic = this.myCropper
      .getCroppedCanvas({
        imageSmoothingQuality: "high"
      })
      .toDataURL("image/jpeg")
    this.setState({
      afterImg: pic,
      isUpload: false
    })
  }

  render() {
    const {
      picture_img,
      isUpload,
      afterImg,
      isCreated,
      produceImg
    } = this.state
    return (
      <View className="container">
        {!produceImg && isUpload ? (
          <View className="poster-mask">
            {/* 裁剪区域 */}
            <View className="img-container">
              <Image
                className="img-area"
                src={picture_img}
                // src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2Fa%2F53f550c675dd9.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1631435691&t=8ef60ec374e799bf4cfb4f3b83b9bb9b"
                ref={img => {
                  this.img = img
                }}
              />
            </View>
            {/* 按钮 */}
            <View className="btn-wrap">
              <Button className="back btn" onClick={this.onCancel}>
                取消
              </Button>
              <Button className="make btn" onClick={this.onConfirm}>
                确认裁剪
              </Button>
            </View>
          </View>
        ) : (
          <View className="poster-img-container">
            {produceImg && isCreated ? (
              <Image src={produceImg} className="poster_img" />
            ) : (
              <View className="make-poster-container">
                {/* 上传海报 */}
                <View className="poster-content">
                  <View className="picture-content">
                    <View
                      className="generate-img"
                      style={
                        afterImg
                          ? { backgroundImage: `url(${afterImg})` }
                          : { backgroundImage: `url(${picture_img})` }
                      }
                    >
                      <View
                        className="caream-wrap"
                        onClick={this.onPicture.bind(this)}
                      >
                        <View className="upload-btn">
                          <Image
                            src="https://img1.halobear.com/upload_page/Fstl6Jkaul8GGuwkweGnxKq02wFs.png"
                            className="camera"
                          />
                          <View className="add">
                            {afterImg ? "替换" : "添加"}照片
                          </View>
                        </View>
                      </View>
                    </View>
                  </View>
                </View>
                {/* 按钮  返回首页、生成海报 */}
                <View className="btn-wrap">
                  <Button className="back btn" onClick={this.toBack}>
                    返回首页
                  </Button>
                  <Button className="make btn" onClick={this.createPoster}>
                    生成海报
                  </Button>
                </View>
              </View>
            )}
          </View>
        )}
      </View>
    )
  }
}

4、效果图

在这里插入图片描述

5、常用参数options

 1、viewMode —— 定义cropper的视图模式
	(https://img-blog.csdnimg.cn/8e0ab5f02ad34b298a8d72a6e58a089b.png)
	  类型: Number;默认:0;
      0: 无限制 (3可以移动到2外)
      1: 限制裁剪框不超过画布的大小。(3只能在2内移动)
      2:限制最小画布大小以适合容器。如果画布和容器的比例不同,则最小画布将被维度之一的额外空间包围。(2不全部铺满1)
      3:限制最小画布尺寸以填充适合容器。如果画布和容器的比例不同,容器将无法在其中一个维度中容纳整个画布。 (2整个填充1)

 2、dragMode —— 定义cropper的拖拽模式。
      类型: String;默认:'crop'
      'crop': 创建一个新的裁剪框
      'move': 移动画布
      'none': 没做什么

 3、aspectRatio —— 定义裁剪框的宽高比
      类型: Number;默认: NaN
      定义裁剪框的初始纵横比。默认情况下,它与画布(图像包装器)的纵横比相同。

 4、background —— 显示容器的网格背景(就是后面的马赛克)
 	  类型: Boolean;默认: true
 5、modal —— 显示图片上方的黑色模态并在裁剪框下面。
      类型: Boolean;默认: true
 6、guides —— 显示在裁剪框内的虚线。
      类型: Boolean;默认: true
 7、autoCrop —— 当初始化时,可以自动生成图像。(就是自动显示裁剪框,改成false裁剪框自动消失)
	  类型: Boolean;默认: true

 8、autoCropArea —— 自动裁剪区域
      类型: Number;默认值:(0.8图像的 80%)
      它是一个介于 0 和 1 之间的数字。定义自动裁剪区域大小(百分比)。

 9、ready —— 插件准备完成执行的函数(只执行一次)
      类型: Function;默认: null

5、常用方法

   1、getContainerData() —— 输出容器大小数据
        类型: Object
        width: 容器的当前宽度 ;height: 容器的当前高度

   2、getData([rounded])  —— 输出最终裁剪的区域位置和大小数据
   	    https://img-blog.csdnimg.cn/0092151f621d4346a3081ccd6ac53321.png
        rounded 类型:Boolean 默认:false;设置true可以获取其所有数据;
        返回的数据类型:Object;
        - x裁切框距离左边的距离
        - y裁切框距离顶部的距离
        - width裁切框的宽度
        - height裁切框的高度
        - rotate裁切框的旋转的角度
        - scaleX缩放图像的横坐标
        - scaleY缩放图像的纵坐标

   3、setData(data) —— 用新数据改变裁切区域的位置和大小(以原始图像为基础)。
        data类型: Object

   4、setCropBoxData —— 输出剪切框的位置和大小数据
   		返回的数据类型:Object;
   		- left剪切框距离左边的距离
   		- top剪切框距离顶部的距离
  		- width剪切框的宽度
  		- height剪切框的高度

6 、结尾

以上内容为本次项目中所涉及和掌握到的常用参数和方法,更多参数和方法可以自行去cropperjs文档深入了解和学习。
文档链接:cropperjs
.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值