|
@@ -0,0 +1,1492 @@
|
|
|
+<template>
|
|
|
+<div class="vue-image-crop-upload" v-show="value">
|
|
|
+ <div class="vicp-wrap" v-loading="loading1">
|
|
|
+ <div class="vicp-close" @click="off">
|
|
|
+ <i class="vicp-icon4"></i>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="vicp-step1" v-show="step == 1">
|
|
|
+ <div class="vicp-drop-area" @dragleave="preventDefault" @dragover="preventDefault" @dragenter="preventDefault" @click="handleClick" @drop="handleChange">
|
|
|
+ <i class="vicp-icon1" v-show="loading != 1">
|
|
|
+ <i class="vicp-icon1-arrow"></i>
|
|
|
+ <i class="vicp-icon1-body"></i>
|
|
|
+ <i class="vicp-icon1-bottom"></i>
|
|
|
+ </i>
|
|
|
+ <span class="vicp-hint" v-show="loading !== 1">{{ lang.hint }}</span>
|
|
|
+ <span class="vicp-no-supported-hint" v-show="!isSupported">{{ lang.noSupported }}</span>
|
|
|
+ <input type="file" v-show="false" v-if="step == 1" @change="handleChange" ref="fileinput">
|
|
|
+ </div>
|
|
|
+ <div class="vicp-error" v-show="hasError">
|
|
|
+ <i class="vicp-icon2"></i> {{ errorMsg }}
|
|
|
+ </div>
|
|
|
+ <div class="vicp-operate">
|
|
|
+ <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="vicp-step2" v-if="step == 2">
|
|
|
+ <div class="vicp-crop">
|
|
|
+ <div class="vicp-crop-left" v-show="true">
|
|
|
+ <div class="vicp-img-container">
|
|
|
+ <img :src="sourceImgUrl" :style="sourceImgStyle" class="vicp-img" draggable="false"
|
|
|
+ @drag="preventDefault"
|
|
|
+ @dragstart="preventDefault"
|
|
|
+ @dragend="preventDefault"
|
|
|
+ @dragleave="preventDefault"
|
|
|
+ @dragover="preventDefault"
|
|
|
+ @dragenter="preventDefault"
|
|
|
+ @drop="preventDefault"
|
|
|
+ @touchstart="imgStartMove"
|
|
|
+ @touchmove="imgMove"
|
|
|
+ @touchend="createImg"
|
|
|
+ @touchcancel="createImg"
|
|
|
+ @mousedown="imgStartMove"
|
|
|
+ @mousemove="imgMove"
|
|
|
+ @mouseup="createImg"
|
|
|
+ @mouseout="createImg"
|
|
|
+ ref="img">
|
|
|
+ <div class="vicp-img-shade vicp-img-shade-1" :style="sourceImgShadeStyle"></div>
|
|
|
+ <div class="vicp-img-shade vicp-img-shade-2" :style="sourceImgShadeStyle"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="vicp-range">
|
|
|
+ <input type="range" :value="scale.range" step="1" min="0" max="100" @input="zoomChange">
|
|
|
+ <i @mousedown="startZoomSub" @mouseout="endZoomSub" @mouseup="endZoomSub" class="vicp-icon5"></i>
|
|
|
+ <i @mousedown="startZoomAdd" @mouseout="endZoomAdd" @mouseup="endZoomAdd" class="vicp-icon6"></i>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="vicp-rotate" v-if="!noRotate">
|
|
|
+ <i @mousedown="startRotateLeft" @mouseout="endRotate" @mouseup="endRotate">↺</i>
|
|
|
+ <i @mousedown="startRotateRight" @mouseout="endRotate" @mouseup="endRotate">↻</i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="vicp-crop-right" v-show="true">
|
|
|
+ <div class="vicp-preview">
|
|
|
+ <div class="vicp-preview-item" v-if="!noSquare">
|
|
|
+ <img :src="createImgUrl" :style="previewStyle">
|
|
|
+ <span>{{ lang.preview }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="vicp-preview-item vicp-preview-item-circle" v-if="!noCircle">
|
|
|
+ <img :src="createImgUrl" :style="previewStyle">
|
|
|
+ <span>{{ lang.preview }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="vicp-operate">
|
|
|
+ <a @click="setStep(1)" @mousedown="ripple">{{ lang.btn.back }}</a>
|
|
|
+ <!-- 保存按钮 -->
|
|
|
+ <a class="vicp-operate-btn" @click="prepareUpload" @mousedown="ripple">{{ lang.btn.save }}</a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="vicp-step3" v-if="step == 3">
|
|
|
+ <div class="vicp-upload">
|
|
|
+ <span class="vicp-loading" v-show="loading === 1">{{ lang.loading }}</span>
|
|
|
+ <div class="vicp-progress-wrap">
|
|
|
+ <span class="vicp-progress" v-show="loading === 1" :style="progressStyle"></span>
|
|
|
+ </div>
|
|
|
+ <div class="vicp-error" v-show="hasError">
|
|
|
+ <i class="vicp-icon2"></i> {{ errorMsg }}
|
|
|
+ </div>
|
|
|
+ <div class="vicp-success" v-show="loading === 2">
|
|
|
+ <i class="vicp-icon3"></i> {{ lang.success }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="vicp-operate">
|
|
|
+ <a @click="setStep(2)" @mousedown="ripple">{{ lang.btn.back }}</a>
|
|
|
+ <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <canvas v-show="false" :width="width" :height="height" ref="canvas"></canvas>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+function kong(){}
|
|
|
+ /* eslint-disable */
|
|
|
+'use strict'
|
|
|
+import request from '@/utils/request'
|
|
|
+import language from './utils/language.js'
|
|
|
+import mimes from './utils/mimes.js'
|
|
|
+import data2blob from './utils/data2blob.js'
|
|
|
+import effectRipple from './utils/effectRipple.js'
|
|
|
+import moment from 'moment'
|
|
|
+import axios from "axios"
|
|
|
+export default {
|
|
|
+ props: {
|
|
|
+ // 域,上传文件name,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
|
|
|
+ field: {
|
|
|
+ type: String,
|
|
|
+ 'default': 'avatar'
|
|
|
+ },
|
|
|
+ // 原名key,类似于id,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
|
|
|
+ ki: {
|
|
|
+ 'default': 0
|
|
|
+ },
|
|
|
+ // 显示该控件与否
|
|
|
+ value: {
|
|
|
+ 'default': true
|
|
|
+ },
|
|
|
+ // 上传地址
|
|
|
+ url: {
|
|
|
+ type: String,
|
|
|
+ 'default': ''
|
|
|
+ },
|
|
|
+ // 其他要上传文件附带的数据,对象格式
|
|
|
+ params: {
|
|
|
+ type: Object,
|
|
|
+ 'default': null
|
|
|
+ },
|
|
|
+ // Add custom headers
|
|
|
+ headers: {
|
|
|
+ type: Object,
|
|
|
+ 'default': null
|
|
|
+ },
|
|
|
+ // 剪裁图片的宽
|
|
|
+ width: {
|
|
|
+ type: Number,
|
|
|
+ default: 200
|
|
|
+ },
|
|
|
+ // 剪裁图片的高
|
|
|
+ height: {
|
|
|
+ type: Number,
|
|
|
+ default: 200
|
|
|
+ },
|
|
|
+ // 不显示旋转功能
|
|
|
+ noRotate: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
+ // 不预览圆形图片
|
|
|
+ noCircle: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ // 不预览方形图片
|
|
|
+ noSquare: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ // 单文件大小限制
|
|
|
+ maxSize: {
|
|
|
+ type: Number,
|
|
|
+ 'default': 10240
|
|
|
+ },
|
|
|
+ // 语言类型
|
|
|
+ langType: {
|
|
|
+ type: String,
|
|
|
+ 'default': 'zh'
|
|
|
+ },
|
|
|
+ // 语言包
|
|
|
+ langExt: {
|
|
|
+ type: Object,
|
|
|
+ 'default': null
|
|
|
+ },
|
|
|
+ // 图片上传格式
|
|
|
+ imgFormat: {
|
|
|
+ type: String,
|
|
|
+ 'default': 'png'
|
|
|
+ },
|
|
|
+ // 是否支持跨域
|
|
|
+ withCredentials: {
|
|
|
+ type: Boolean,
|
|
|
+ 'default': false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ const that = this
|
|
|
+ const {
|
|
|
+ imgFormat,
|
|
|
+ langType,
|
|
|
+ langExt,
|
|
|
+ width,
|
|
|
+ height
|
|
|
+ } = that
|
|
|
+ let isSupported = true
|
|
|
+ const allowImgFormat = [
|
|
|
+ 'jpg',
|
|
|
+ 'png'
|
|
|
+ ]
|
|
|
+ const tempImgFormat = allowImgFormat.indexOf(imgFormat) === -1 ? 'jpg' : imgFormat
|
|
|
+ const lang = language[langType] ? language[langType] : language['en']
|
|
|
+ const mime = mimes[tempImgFormat]
|
|
|
+ // 规范图片格式
|
|
|
+ that.imgFormat = tempImgFormat
|
|
|
+ if (langExt) {
|
|
|
+ Object.assign(lang, langExt)
|
|
|
+ }
|
|
|
+ if (typeof FormData !== 'function') {
|
|
|
+ isSupported = false
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ loading1: false,
|
|
|
+ // 图片的mime
|
|
|
+ mime,
|
|
|
+ // 语言包
|
|
|
+ lang,
|
|
|
+ // 浏览器是否支持该控件
|
|
|
+ isSupported,
|
|
|
+ // 浏览器是否支持触屏事件
|
|
|
+ isSupportTouch: document.hasOwnProperty('ontouchstart'),
|
|
|
+ // 步骤
|
|
|
+ step: 1, // 1选择文件 2剪裁 3上传
|
|
|
+ // 上传状态及进度
|
|
|
+ loading: 0, // 0未开始 1正在 2成功 3错误
|
|
|
+ progress: 0,
|
|
|
+ // 是否有错误及错误信息
|
|
|
+ hasError: false,
|
|
|
+ errorMsg: '',
|
|
|
+ // 需求图宽高比
|
|
|
+ ratio: width / height,
|
|
|
+ // 原图地址、生成图片地址
|
|
|
+ sourceImg: null,
|
|
|
+ sourceImgUrl: '',
|
|
|
+ createImgUrl: '',
|
|
|
+ // 原图片拖动事件初始值
|
|
|
+ sourceImgMouseDown: {
|
|
|
+ on: false,
|
|
|
+ mX: 0, // 鼠标按下的坐标
|
|
|
+ mY: 0,
|
|
|
+ x: 0, // scale原图坐标
|
|
|
+ y: 0
|
|
|
+ },
|
|
|
+ // 生成图片预览的容器大小
|
|
|
+ previewContainer: {
|
|
|
+ width: 100,
|
|
|
+ height: 100
|
|
|
+ },
|
|
|
+ // 原图容器宽高
|
|
|
+ sourceImgContainer: { // sic
|
|
|
+ width: 240,
|
|
|
+ height: 184 // 如果生成图比例与此一致会出现bug,先改成特殊的格式吧,哈哈哈
|
|
|
+ },
|
|
|
+ // 原图展示属性
|
|
|
+ scale: {
|
|
|
+ zoomAddOn: false, // 按钮缩放事件开启
|
|
|
+ zoomSubOn: false, // 按钮缩放事件开启
|
|
|
+ range: 1, // 最大100
|
|
|
+ rotateLeft: false, // 按钮向左旋转事件开启
|
|
|
+ rotateRight: false, // 按钮向右旋转事件开启
|
|
|
+ degree: 0, // 旋转度数
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ width: 0,
|
|
|
+ height: 0,
|
|
|
+ maxWidth: 0,
|
|
|
+ maxHeight: 0,
|
|
|
+ minWidth: 0, // 最宽
|
|
|
+ minHeight: 0,
|
|
|
+ naturalWidth: 0, // 原宽
|
|
|
+ naturalHeight: 0
|
|
|
+ },
|
|
|
+ config: null,
|
|
|
+ getFiles:{}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 进度条样式
|
|
|
+ progressStyle() {
|
|
|
+ const {
|
|
|
+ progress
|
|
|
+ } = this
|
|
|
+ return {
|
|
|
+ width: progress + '%'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 原图样式
|
|
|
+ sourceImgStyle() {
|
|
|
+ const {
|
|
|
+ scale,
|
|
|
+ sourceImgMasking
|
|
|
+ } = this
|
|
|
+ const top = scale.y + sourceImgMasking.y + 'px'
|
|
|
+ const left = scale.x + sourceImgMasking.x + 'px'
|
|
|
+ return {
|
|
|
+ top,
|
|
|
+ left,
|
|
|
+ width: scale.width + 'px',
|
|
|
+ height: scale.height + 'px',
|
|
|
+ transform: 'rotate(' + scale.degree + 'deg)', // 旋转时 左侧原始图旋转样式
|
|
|
+ '-ms-transform': 'rotate(' + scale.degree + 'deg)', // 兼容IE9
|
|
|
+ '-moz-transform': 'rotate(' + scale.degree + 'deg)', // 兼容FireFox
|
|
|
+ '-webkit-transform': 'rotate(' + scale.degree + 'deg)', // 兼容Safari 和 chrome
|
|
|
+ '-o-transform': 'rotate(' + scale.degree + 'deg)' // 兼容 Opera
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 原图蒙版属性
|
|
|
+ sourceImgMasking() {
|
|
|
+ const {
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ ratio,
|
|
|
+ sourceImgContainer
|
|
|
+ } = this
|
|
|
+ const sic = sourceImgContainer
|
|
|
+ const sicRatio = sic.width / sic.height // 原图容器宽高比
|
|
|
+ let x = 0
|
|
|
+ let y = 0
|
|
|
+ let w = sic.width
|
|
|
+ let h = sic.height
|
|
|
+ let scale = 1
|
|
|
+ if (ratio < sicRatio) {
|
|
|
+ scale = sic.height / height
|
|
|
+ w = sic.height * ratio
|
|
|
+ x = (sic.width - w) / 2
|
|
|
+ }
|
|
|
+ if (ratio > sicRatio) {
|
|
|
+ scale = sic.width / width
|
|
|
+ h = sic.width / ratio
|
|
|
+ y = (sic.height - h) / 2
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ scale, // 蒙版相对需求宽高的缩放
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ width: w,
|
|
|
+ height: h
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 原图遮罩样式
|
|
|
+ sourceImgShadeStyle() {
|
|
|
+ const {
|
|
|
+ sourceImgMasking,
|
|
|
+ sourceImgContainer
|
|
|
+ } = this
|
|
|
+ const sic = sourceImgContainer
|
|
|
+ const sim = sourceImgMasking
|
|
|
+ const w = sim.width == sic.width ? sim.width : (sic.width - sim.width) / 2
|
|
|
+ const h = sim.height == sic.height ? sim.height : (sic.height - sim.height) / 2
|
|
|
+ return {
|
|
|
+ width: w + 'px',
|
|
|
+ height: h + 'px'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ previewStyle() {
|
|
|
+ const {
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ ratio,
|
|
|
+ previewContainer
|
|
|
+ } = this
|
|
|
+ const pc = previewContainer
|
|
|
+ let w = pc.width
|
|
|
+ let h = pc.height
|
|
|
+ const pcRatio = w / h
|
|
|
+ if (ratio < pcRatio) {
|
|
|
+ w = pc.height * ratio
|
|
|
+ }
|
|
|
+ if (ratio > pcRatio) {
|
|
|
+ h = pc.width / ratio
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ width: w + 'px',
|
|
|
+ height: h + 'px'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ value(newValue) {
|
|
|
+ if (newValue && this.loading != 1) {
|
|
|
+ this.reset()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+
|
|
|
+ // 19.12.13 获取oss数据
|
|
|
+ get_sign(callback) {
|
|
|
+ axios('https://intesys.cms.g107.com/integral.php/Api/get_signature').then(res => {
|
|
|
+ this.config = res.data.data
|
|
|
+ callback()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ random_string(len) {
|
|
|
+ len = len || 32
|
|
|
+ var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
|
|
|
+ var maxPos = chars.length
|
|
|
+ var pwd = ''
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
+ pwd += chars.charAt(Math.floor(Math.random() * maxPos))
|
|
|
+ }
|
|
|
+ return pwd
|
|
|
+ },
|
|
|
+ upload_oss(item) {
|
|
|
+ let self = this
|
|
|
+ const photo = item // 获取图片对象
|
|
|
+ const photoName = item.name // 原图片的名称
|
|
|
+ const url = 'https://integralsys.oss-cn-shenzhen.aliyuncs.com'
|
|
|
+ const user_info = this.$store.getters.user_info || JSON.parse(localStorage.getItem('user_info'))
|
|
|
+ let date = moment().format('YYYY/MM/DD')
|
|
|
+ let param = new FormData()
|
|
|
+ let randomStr = this.random_string(32)
|
|
|
+ let key = 'intesys/gdy/'+user_info.site_id+'/'+date + '/' + randomStr + photoName
|
|
|
+ param.append('Filename', photoName)
|
|
|
+ param.append('key', key)
|
|
|
+ param.append('policy', this.config.policy)
|
|
|
+ param.append('OSSAccessKeyId', this.config.accessid)
|
|
|
+ param.append('success_action_status', '200') // 不要问为什么,照做
|
|
|
+ param.append('callback', this.config.callback)
|
|
|
+ param.append('signature', this.config.signature)
|
|
|
+ param.append('file', photo) // 这个**切记**一定要放到最后去 append ,不然阿里云会一直报 key 的错误
|
|
|
+ axios.post(url, param, {
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'multipart/form-data'
|
|
|
+ }
|
|
|
+ }).then(response => {
|
|
|
+ self.loading1 = false
|
|
|
+ if(response.data.Status == 'Ok'){
|
|
|
+ let dataUrl = {status: 1,url: url + '/' + key}
|
|
|
+ self.$emit('crop-upload-success', dataUrl)
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ console.log('err == ', err)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ base64toFile(dataurl, filename) {
|
|
|
+ var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
|
|
|
+ bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
|
|
+ while(n--){
|
|
|
+ u8arr[n] = bstr.charCodeAt(n);
|
|
|
+ }
|
|
|
+ return new File([u8arr], filename, {type:mime});
|
|
|
+ },
|
|
|
+ go_oss_upload(getFiles){
|
|
|
+ let self = this
|
|
|
+ self.loading1 = true
|
|
|
+ this.get_sign(function () {
|
|
|
+ self.upload_oss(getFiles[0])
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 点击波纹效果
|
|
|
+ ripple(e) {
|
|
|
+ effectRipple(e)
|
|
|
+ },
|
|
|
+ // 关闭控件
|
|
|
+ off() {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$emit('input', false)
|
|
|
+ this.$emit('close')
|
|
|
+ if (this.step == 3 && this.loading == 2) {
|
|
|
+ this.setStep(1)
|
|
|
+ }
|
|
|
+ }, 200)
|
|
|
+ },
|
|
|
+ // 设置步骤
|
|
|
+ setStep(no) {
|
|
|
+ // 延时是为了显示动画效果呢,哈哈哈
|
|
|
+ setTimeout(() => {
|
|
|
+ this.step = no
|
|
|
+ }, 200)
|
|
|
+ },
|
|
|
+ /* 图片选择区域函数绑定
|
|
|
+ ---------------------------------------------------------------*/
|
|
|
+ preventDefault(e) {
|
|
|
+ e.preventDefault()
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ handleClick(e) {
|
|
|
+ if (this.loading !== 1) {
|
|
|
+ if (e.target !== this.$refs.fileinput) {
|
|
|
+ e.preventDefault()
|
|
|
+ if (document.activeElement !== this.$refs) {
|
|
|
+ this.$refs.fileinput.click()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleChange(e) {
|
|
|
+ e.preventDefault()
|
|
|
+ if (this.loading !== 1) {
|
|
|
+ const files = e.target.files || e.dataTransfer.files
|
|
|
+ this.getFiles= e.target.files || e.dataTransfer.files
|
|
|
+ this.reset()
|
|
|
+ if (this.checkFile(files[0])) {
|
|
|
+ this.setSourceImg(files[0])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /* ---------------------------------------------------------------*/
|
|
|
+ // 检测选择的文件是否合适
|
|
|
+ checkFile(file) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ lang,
|
|
|
+ maxSize
|
|
|
+ } = that
|
|
|
+ // 仅限图片
|
|
|
+ if (file.type.indexOf('image') === -1) {
|
|
|
+ that.hasError = true
|
|
|
+ that.errorMsg = lang.error.onlyImg
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // 超出大小
|
|
|
+ if (file.size / 1024 > maxSize) {
|
|
|
+ that.hasError = true
|
|
|
+ that.errorMsg = lang.error.outOfSize + maxSize + 'kb'
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ // 重置控件
|
|
|
+ reset() {
|
|
|
+ const that = this
|
|
|
+ that.loading = 0
|
|
|
+ that.hasError = false
|
|
|
+ that.errorMsg = ''
|
|
|
+ that.progress = 0
|
|
|
+ },
|
|
|
+ // 设置图片源
|
|
|
+ setSourceImg(file) {
|
|
|
+ let that = this,
|
|
|
+ fr = new FileReader()
|
|
|
+ fr.onload = function(e) {
|
|
|
+ that.sourceImgUrl = fr.result
|
|
|
+ that.startCrop()
|
|
|
+ }
|
|
|
+ fr.readAsDataURL(file)
|
|
|
+ },
|
|
|
+ // 剪裁前准备工作
|
|
|
+ startCrop() {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ ratio,
|
|
|
+ scale,
|
|
|
+ sourceImgUrl,
|
|
|
+ sourceImgMasking,
|
|
|
+ lang
|
|
|
+ } = that,
|
|
|
+ sim = sourceImgMasking,
|
|
|
+ img = new Image()
|
|
|
+ img.src = sourceImgUrl
|
|
|
+ img.onload = function() {
|
|
|
+ let nWidth = img.naturalWidth,
|
|
|
+ nHeight = img.naturalHeight,
|
|
|
+ nRatio = nWidth / nHeight,
|
|
|
+ w = sim.width,
|
|
|
+ h = sim.height,
|
|
|
+ x = 0,
|
|
|
+ y = 0
|
|
|
+ // 图片像素不达标
|
|
|
+ if (nWidth < width || nHeight < height) {
|
|
|
+ that.hasError = true
|
|
|
+ that.errorMsg = lang.error.lowestPx + width + '*' + height
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (ratio > nRatio) {
|
|
|
+ h = w / nRatio
|
|
|
+ y = (sim.height - h) / 2
|
|
|
+ }
|
|
|
+ if (ratio < nRatio) {
|
|
|
+ w = h * nRatio
|
|
|
+ x = (sim.width - w) / 2
|
|
|
+ }
|
|
|
+ scale.range = 0
|
|
|
+ scale.x = x
|
|
|
+ scale.y = y
|
|
|
+ scale.width = w
|
|
|
+ scale.height = h
|
|
|
+ scale.degree = 0
|
|
|
+ scale.minWidth = w
|
|
|
+ scale.minHeight = h
|
|
|
+ scale.maxWidth = nWidth * sim.scale
|
|
|
+ scale.maxHeight = nHeight * sim.scale
|
|
|
+ scale.naturalWidth = nWidth
|
|
|
+ scale.naturalHeight = nHeight
|
|
|
+ that.sourceImg = img
|
|
|
+ that.createImg()
|
|
|
+ that.setStep(2)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 鼠标按下图片准备移动
|
|
|
+ imgStartMove(e) {
|
|
|
+ e.preventDefault()
|
|
|
+ // 支持触摸事件,则鼠标事件无效
|
|
|
+ if (this.isSupportTouch && !e.targetTouches) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ let et = e.targetTouches ? e.targetTouches[0] : e,
|
|
|
+ {
|
|
|
+ sourceImgMouseDown,
|
|
|
+ scale
|
|
|
+ } = this,
|
|
|
+ simd = sourceImgMouseDown
|
|
|
+ simd.mX = et.screenX
|
|
|
+ simd.mY = et.screenY
|
|
|
+ simd.x = scale.x
|
|
|
+ simd.y = scale.y
|
|
|
+ simd.on = true
|
|
|
+ },
|
|
|
+ // 鼠标按下状态下移动,图片移动
|
|
|
+ imgMove(e) {
|
|
|
+ e.preventDefault()
|
|
|
+ // 支持触摸事件,则鼠标事件无效
|
|
|
+ if (this.isSupportTouch && !e.targetTouches) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ let et = e.targetTouches ? e.targetTouches[0] : e,
|
|
|
+ {
|
|
|
+ sourceImgMouseDown: {
|
|
|
+ on,
|
|
|
+ mX,
|
|
|
+ mY,
|
|
|
+ x,
|
|
|
+ y
|
|
|
+ },
|
|
|
+ scale,
|
|
|
+ sourceImgMasking
|
|
|
+ } = this,
|
|
|
+ sim = sourceImgMasking,
|
|
|
+ nX = et.screenX,
|
|
|
+ nY = et.screenY,
|
|
|
+ dX = nX - mX,
|
|
|
+ dY = nY - mY,
|
|
|
+ rX = x + dX,
|
|
|
+ rY = y + dY
|
|
|
+ if (!on) return
|
|
|
+ if (rX > 0) {
|
|
|
+ rX = 0
|
|
|
+ }
|
|
|
+ if (rY > 0) {
|
|
|
+ rY = 0
|
|
|
+ }
|
|
|
+ if (rX < sim.width - scale.width) {
|
|
|
+ rX = sim.width - scale.width
|
|
|
+ }
|
|
|
+ if (rY < sim.height - scale.height) {
|
|
|
+ rY = sim.height - scale.height
|
|
|
+ }
|
|
|
+ scale.x = rX
|
|
|
+ scale.y = rY
|
|
|
+ },
|
|
|
+ // 按钮按下开始向右旋转
|
|
|
+ startRotateRight(e) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ scale
|
|
|
+ } = that
|
|
|
+ scale.rotateRight = true
|
|
|
+ function rotate() {
|
|
|
+ if (scale.rotateRight) {
|
|
|
+ const degree = ++scale.degree
|
|
|
+ that.createImg(degree)
|
|
|
+ setTimeout(function() {
|
|
|
+ rotate()
|
|
|
+ }, 60)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rotate()
|
|
|
+ },
|
|
|
+ // 按钮按下开始向右旋转
|
|
|
+ startRotateLeft(e) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ scale
|
|
|
+ } = that
|
|
|
+ scale.rotateLeft = true
|
|
|
+ function rotate() {
|
|
|
+ if (scale.rotateLeft) {
|
|
|
+ const degree = --scale.degree
|
|
|
+ that.createImg(degree)
|
|
|
+ setTimeout(function() {
|
|
|
+ rotate()
|
|
|
+ }, 60)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rotate()
|
|
|
+ },
|
|
|
+ // 停止旋转
|
|
|
+ endRotate() {
|
|
|
+ const {
|
|
|
+ scale
|
|
|
+ } = this
|
|
|
+ scale.rotateLeft = false
|
|
|
+ scale.rotateRight = false
|
|
|
+ },
|
|
|
+ // 按钮按下开始放大
|
|
|
+ startZoomAdd(e) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ scale
|
|
|
+ } = that
|
|
|
+ scale.zoomAddOn = true
|
|
|
+ function zoom() {
|
|
|
+ if (scale.zoomAddOn) {
|
|
|
+ const range = scale.range >= 100 ? 100 : ++scale.range
|
|
|
+ that.zoomImg(range)
|
|
|
+ setTimeout(function() {
|
|
|
+ zoom()
|
|
|
+ }, 60)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ zoom()
|
|
|
+ },
|
|
|
+ // 按钮松开或移开取消放大
|
|
|
+ endZoomAdd(e) {
|
|
|
+ this.scale.zoomAddOn = false
|
|
|
+ },
|
|
|
+ // 按钮按下开始缩小
|
|
|
+ startZoomSub(e) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ scale
|
|
|
+ } = that
|
|
|
+ scale.zoomSubOn = true
|
|
|
+ function zoom() {
|
|
|
+ if (scale.zoomSubOn) {
|
|
|
+ const range = scale.range <= 0 ? 0 : --scale.range
|
|
|
+ that.zoomImg(range)
|
|
|
+ setTimeout(function() {
|
|
|
+ zoom()
|
|
|
+ }, 60)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ zoom()
|
|
|
+ },
|
|
|
+ // 按钮松开或移开取消缩小
|
|
|
+ endZoomSub(e) {
|
|
|
+ const {
|
|
|
+ scale
|
|
|
+ } = this
|
|
|
+ scale.zoomSubOn = false
|
|
|
+ },
|
|
|
+ zoomChange(e) {
|
|
|
+ this.zoomImg(e.target.value)
|
|
|
+ },
|
|
|
+ // 缩放原图
|
|
|
+ zoomImg(newRange) {
|
|
|
+ const that = this
|
|
|
+ const {
|
|
|
+ sourceImgMasking,
|
|
|
+ sourceImgMouseDown,
|
|
|
+ scale
|
|
|
+ } = this
|
|
|
+ const {
|
|
|
+ maxWidth,
|
|
|
+ maxHeight,
|
|
|
+ minWidth,
|
|
|
+ minHeight,
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ range
|
|
|
+ } = scale
|
|
|
+ const sim = sourceImgMasking
|
|
|
+ // 蒙版宽高
|
|
|
+ const sWidth = sim.width
|
|
|
+ const sHeight = sim.height
|
|
|
+ // 新宽高
|
|
|
+ const nWidth = minWidth + (maxWidth - minWidth) * newRange / 100
|
|
|
+ const nHeight = minHeight + (maxHeight - minHeight) * newRange / 100
|
|
|
+ // 新坐标(根据蒙版中心点缩放)
|
|
|
+ let nX = sWidth / 2 - (nWidth / width) * (sWidth / 2 - x)
|
|
|
+ let nY = sHeight / 2 - (nHeight / height) * (sHeight / 2 - y)
|
|
|
+ // 判断新坐标是否超过蒙版限制
|
|
|
+ if (nX > 0) {
|
|
|
+ nX = 0
|
|
|
+ }
|
|
|
+ if (nY > 0) {
|
|
|
+ nY = 0
|
|
|
+ }
|
|
|
+ if (nX < sWidth - nWidth) {
|
|
|
+ nX = sWidth - nWidth
|
|
|
+ }
|
|
|
+ if (nY < sHeight - nHeight) {
|
|
|
+ nY = sHeight - nHeight
|
|
|
+ }
|
|
|
+ // 赋值处理
|
|
|
+ scale.x = nX
|
|
|
+ scale.y = nY
|
|
|
+ scale.width = nWidth
|
|
|
+ scale.height = nHeight
|
|
|
+ scale.range = newRange
|
|
|
+ setTimeout(function() {
|
|
|
+ if (scale.range == newRange) {
|
|
|
+ that.createImg()
|
|
|
+ }
|
|
|
+ }, 300)
|
|
|
+ },
|
|
|
+ // 生成需求图片
|
|
|
+ createImg(e) {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ mime,
|
|
|
+ sourceImg,
|
|
|
+ scale: {
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ degree
|
|
|
+ },
|
|
|
+ sourceImgMasking: {
|
|
|
+ scale
|
|
|
+ }
|
|
|
+ } = that,
|
|
|
+ canvas = that.$refs.canvas,
|
|
|
+ ctx = canvas.getContext('2d')
|
|
|
+ if (e) {
|
|
|
+ // 取消鼠标按下移动状态
|
|
|
+ that.sourceImgMouseDown.on = false
|
|
|
+ }
|
|
|
+ canvas.width = that.width
|
|
|
+ canvas.height = that.height
|
|
|
+ ctx.clearRect(0, 0, that.width, that.height)
|
|
|
+ // 将透明区域设置为白色底边
|
|
|
+ ctx.fillStyle = '#fff'
|
|
|
+ ctx.fillRect(0, 0, that.width, that.height)
|
|
|
+ ctx.translate(that.width * 0.5, that.height * 0.5)
|
|
|
+ ctx.rotate(Math.PI * degree / 180)
|
|
|
+ ctx.translate(-that.width * 0.5, -that.height * 0.5)
|
|
|
+ ctx.drawImage(sourceImg, x / scale, y / scale, width / scale, height / scale)
|
|
|
+ that.createImgUrl = canvas.toDataURL(mime)
|
|
|
+
|
|
|
+ // this.getFiles= this.base64toFile(this.createImgUrl,'flif')
|
|
|
+ },
|
|
|
+ prepareUpload() {
|
|
|
+ const {
|
|
|
+ url,
|
|
|
+ createImgUrl,
|
|
|
+ field,
|
|
|
+ ki
|
|
|
+ } = this
|
|
|
+ this.$emit('crop-success', createImgUrl, field, ki)
|
|
|
+ if (typeof url === 'string' && url) {
|
|
|
+ this.getFiles = {0:this.base64toFile(this.createImgUrl,moment().format('YYYY/MM/DD')+'.png')}
|
|
|
+ this.go_oss_upload(this.getFiles)
|
|
|
+ } else {
|
|
|
+ this.off()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 上传图片
|
|
|
+ upload() {
|
|
|
+ let that = this,
|
|
|
+ {
|
|
|
+ lang,
|
|
|
+ imgFormat,
|
|
|
+ mime,
|
|
|
+ url,
|
|
|
+ params,
|
|
|
+ headers,
|
|
|
+ field,
|
|
|
+ ki,
|
|
|
+ createImgUrl,
|
|
|
+ withCredentials
|
|
|
+ } = this,
|
|
|
+ fmData = new FormData()
|
|
|
+ fmData.append(field, data2blob(createImgUrl, mime), field + '.' + imgFormat)
|
|
|
+ // 添加其他参数
|
|
|
+ if (typeof params === 'object' && params) {
|
|
|
+ Object.keys(params).forEach((k) => {
|
|
|
+ fmData.append(k, params[k])
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 监听进度回调
|
|
|
+ const uploadProgress = function(event) {
|
|
|
+ if (event.lengthComputable) {
|
|
|
+ that.progress = 100 * Math.round(event.loaded) / event.total
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 上传文件
|
|
|
+ that.reset()
|
|
|
+ that.loading = 1
|
|
|
+ that.setStep(3)
|
|
|
+ request('post',url,fmData).then(resData => {
|
|
|
+ that.loading = 2
|
|
|
+ that.$emit('crop-upload-success', resData.data)
|
|
|
+ }).catch(err => {
|
|
|
+ if (that.value) {
|
|
|
+ that.loading = 3
|
|
|
+ that.hasError = true
|
|
|
+ that.errorMsg = lang.fail
|
|
|
+ that.$emit('crop-upload-fail', err, field, ki)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ // 绑定按键esc隐藏此插件事件
|
|
|
+ document.addEventListener('keyup', (e) => {
|
|
|
+ if (this.value && (e.key == 'Escape' || e.keyCode == 27)) {
|
|
|
+ this.off()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<!--
|
|
|
+<style lang='sass' src="./scss/upload.scss">
|
|
|
+</style> -->
|
|
|
+
|
|
|
+<style>
|
|
|
+@charset "UTF-8";
|
|
|
+@-webkit-keyframes vicp_progress {
|
|
|
+ 0% {
|
|
|
+ background-position-y: 0; }
|
|
|
+ 100% {
|
|
|
+ background-position-y: 40px; } }
|
|
|
+@keyframes vicp_progress {
|
|
|
+ 0% {
|
|
|
+ background-position-y: 0; }
|
|
|
+ 100% {
|
|
|
+ background-position-y: 40px; } }
|
|
|
+@-webkit-keyframes vicp {
|
|
|
+ 0% {
|
|
|
+ opacity: 0;
|
|
|
+ -webkit-transform: scale(0) translatey(-60px);
|
|
|
+ transform: scale(0) translatey(-60px); }
|
|
|
+ 100% {
|
|
|
+ opacity: 1;
|
|
|
+ -webkit-transform: scale(1) translatey(0);
|
|
|
+ transform: scale(1) translatey(0); } }
|
|
|
+@keyframes vicp {
|
|
|
+ 0% {
|
|
|
+ opacity: 0;
|
|
|
+ -webkit-transform: scale(0) translatey(-60px);
|
|
|
+ transform: scale(0) translatey(-60px); }
|
|
|
+ 100% {
|
|
|
+ opacity: 1;
|
|
|
+ -webkit-transform: scale(1) translatey(0);
|
|
|
+ transform: scale(1) translatey(0); } }
|
|
|
+.vue-image-crop-upload {
|
|
|
+ position: fixed;
|
|
|
+ display: block;
|
|
|
+ -webkit-box-sizing: border-box;
|
|
|
+ box-sizing: border-box;
|
|
|
+ z-index: 10000;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-color: rgba(0, 0, 0, 0.65);
|
|
|
+ -webkit-tap-highlight-color: transparent;
|
|
|
+ -moz-tap-highlight-color: transparent; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ position: fixed;
|
|
|
+ display: block;
|
|
|
+ -webkit-box-sizing: border-box;
|
|
|
+ box-sizing: border-box;
|
|
|
+ z-index: 10000;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ margin: auto;
|
|
|
+ width: 600px;
|
|
|
+ height: 330px;
|
|
|
+ padding: 25px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ -webkit-animation: vicp 0.12s ease-in;
|
|
|
+ animation: vicp 0.12s ease-in; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-close {
|
|
|
+ position: absolute;
|
|
|
+ right: -30px;
|
|
|
+ top: -30px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 {
|
|
|
+ position: relative;
|
|
|
+ display: block;
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ cursor: pointer;
|
|
|
+ -webkit-transition: -webkit-transform 0.18s;
|
|
|
+ transition: -webkit-transform 0.18s;
|
|
|
+ transition: transform 0.18s;
|
|
|
+ transition: transform 0.18s, -webkit-transform 0.18s;
|
|
|
+ -webkit-transform: rotate(0);
|
|
|
+ -ms-transform: rotate(0);
|
|
|
+ transform: rotate(0); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after, .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 12px;
|
|
|
+ left: 4px;
|
|
|
+ width: 20px;
|
|
|
+ height: 3px;
|
|
|
+ -webkit-transform: rotate(45deg);
|
|
|
+ -ms-transform: rotate(45deg);
|
|
|
+ transform: rotate(45deg);
|
|
|
+ background-color: #fff; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after {
|
|
|
+ -webkit-transform: rotate(-45deg);
|
|
|
+ -ms-transform: rotate(-45deg);
|
|
|
+ transform: rotate(-45deg); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover {
|
|
|
+ -webkit-transform: rotate(90deg);
|
|
|
+ -ms-transform: rotate(90deg);
|
|
|
+ transform: rotate(90deg); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area {
|
|
|
+ position: relative;
|
|
|
+ -webkit-box-sizing: border-box;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 35px;
|
|
|
+ height: 170px;
|
|
|
+ background-color: rgba(0, 0, 0, 0.03);
|
|
|
+ text-align: center;
|
|
|
+ border: 1px dashed rgba(0, 0, 0, 0.08);
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 {
|
|
|
+ display: block;
|
|
|
+ margin: 0 auto 6px;
|
|
|
+ width: 42px;
|
|
|
+ height: 42px;
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-arrow {
|
|
|
+ display: block;
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-bottom: 14.7px solid rgba(0, 0, 0, 0.3);
|
|
|
+ border-left: 14.7px solid transparent;
|
|
|
+ border-right: 14.7px solid transparent; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-body {
|
|
|
+ display: block;
|
|
|
+ width: 12.6px;
|
|
|
+ height: 14.7px;
|
|
|
+ margin: 0 auto;
|
|
|
+ background-color: rgba(0, 0, 0, 0.3); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-bottom {
|
|
|
+ -webkit-box-sizing: border-box;
|
|
|
+ box-sizing: border-box;
|
|
|
+ display: block;
|
|
|
+ height: 12.6px;
|
|
|
+ border: 6px solid rgba(0, 0, 0, 0.3);
|
|
|
+ border-top: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint {
|
|
|
+ display: block;
|
|
|
+ padding: 15px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ line-height: 30px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-no-supported-hint {
|
|
|
+ display: block;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ padding: 30px;
|
|
|
+ width: 100%;
|
|
|
+ height: 60px;
|
|
|
+ line-height: 30px;
|
|
|
+ background-color: #eee;
|
|
|
+ text-align: center;
|
|
|
+ color: #666;
|
|
|
+ font-size: 14px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover {
|
|
|
+ cursor: pointer;
|
|
|
+ border-color: rgba(0, 0, 0, 0.1);
|
|
|
+ background-color: rgba(0, 0, 0, 0.05); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop {
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left {
|
|
|
+ float: left; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container {
|
|
|
+ position: relative;
|
|
|
+ display: block;
|
|
|
+ width: 240px;
|
|
|
+ height: 180px;
|
|
|
+ background-color: #e5e5e0;
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img {
|
|
|
+ position: absolute;
|
|
|
+ display: block;
|
|
|
+ cursor: move;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -moz-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ user-select: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade {
|
|
|
+ -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ position: absolute;
|
|
|
+ background-color: rgba(241, 242, 243, 0.8); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-1 {
|
|
|
+ top: 0;
|
|
|
+ left: 0; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-2 {
|
|
|
+ bottom: 0;
|
|
|
+ right: 0; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate {
|
|
|
+ position: relative;
|
|
|
+ width: 240px;
|
|
|
+ height: 18px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i {
|
|
|
+ display: block;
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ border-radius: 100%;
|
|
|
+ line-height: 18px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ background-color: rgba(0, 0, 0, 0.08);
|
|
|
+ color: #fff;
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:hover {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: rgba(0, 0, 0, 0.14); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:first-child {
|
|
|
+ float: left; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:last-child {
|
|
|
+ float: right; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range {
|
|
|
+ position: relative;
|
|
|
+ margin: 30px 0 10px 0;
|
|
|
+ width: 240px;
|
|
|
+ height: 18px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5,
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ border-radius: 100%;
|
|
|
+ background-color: rgba(0, 0, 0, 0.08); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5:hover,
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6:hover {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: rgba(0, 0, 0, 0.14); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5 {
|
|
|
+ left: 0; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5::before {
|
|
|
+ position: absolute;
|
|
|
+ content: '';
|
|
|
+ display: block;
|
|
|
+ left: 3px;
|
|
|
+ top: 8px;
|
|
|
+ width: 12px;
|
|
|
+ height: 2px;
|
|
|
+ background-color: #fff; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
|
|
|
+ right: 0; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::before {
|
|
|
+ position: absolute;
|
|
|
+ content: '';
|
|
|
+ display: block;
|
|
|
+ left: 3px;
|
|
|
+ top: 8px;
|
|
|
+ width: 12px;
|
|
|
+ height: 2px;
|
|
|
+ background-color: #fff; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::after {
|
|
|
+ position: absolute;
|
|
|
+ content: '';
|
|
|
+ display: block;
|
|
|
+ top: 3px;
|
|
|
+ left: 8px;
|
|
|
+ width: 2px;
|
|
|
+ height: 12px;
|
|
|
+ background-color: #fff; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range] {
|
|
|
+ display: block;
|
|
|
+ padding-top: 5px;
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 180px;
|
|
|
+ height: 8px;
|
|
|
+ vertical-align: top;
|
|
|
+ background: transparent;
|
|
|
+ -webkit-appearance: none;
|
|
|
+ -moz-appearance: none;
|
|
|
+ appearance: none;
|
|
|
+ cursor: pointer;
|
|
|
+ /* 滑块
|
|
|
+ ---------------------------------------------------------------*/
|
|
|
+ /* 轨道
|
|
|
+ ---------------------------------------------------------------*/ }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus {
|
|
|
+ outline: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-thumb {
|
|
|
+ -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ -webkit-appearance: none;
|
|
|
+ appearance: none;
|
|
|
+ margin-top: -3px;
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ background-color: #61c091;
|
|
|
+ border-radius: 100%;
|
|
|
+ border: none;
|
|
|
+ -webkit-transition: 0.2s;
|
|
|
+ transition: 0.2s; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-thumb {
|
|
|
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ -moz-appearance: none;
|
|
|
+ appearance: none;
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ background-color: #61c091;
|
|
|
+ border-radius: 100%;
|
|
|
+ border: none;
|
|
|
+ -webkit-transition: 0.2s;
|
|
|
+ transition: 0.2s; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-thumb {
|
|
|
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
|
|
+ appearance: none;
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ background-color: #61c091;
|
|
|
+ border: none;
|
|
|
+ border-radius: 100%;
|
|
|
+ -webkit-transition: 0.2s;
|
|
|
+ transition: 0.2s; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-moz-range-thumb {
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ width: 14px;
|
|
|
+ height: 14px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-ms-thumb {
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ width: 14px;
|
|
|
+ height: 14px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-webkit-slider-thumb {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
|
|
+ margin-top: -4px;
|
|
|
+ width: 14px;
|
|
|
+ height: 14px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-runnable-track {
|
|
|
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ width: 100%;
|
|
|
+ height: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 2px;
|
|
|
+ border: none;
|
|
|
+ background-color: rgba(68, 170, 119, 0.3); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-track {
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ width: 100%;
|
|
|
+ height: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 2px;
|
|
|
+ border: none;
|
|
|
+ background-color: rgba(68, 170, 119, 0.3); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-track {
|
|
|
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
|
|
+ width: 100%;
|
|
|
+ cursor: pointer;
|
|
|
+ background: transparent;
|
|
|
+ border-color: transparent;
|
|
|
+ color: transparent;
|
|
|
+ height: 6px;
|
|
|
+ border-radius: 2px;
|
|
|
+ border: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-lower {
|
|
|
+ background-color: rgba(68, 170, 119, 0.3); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-upper {
|
|
|
+ background-color: rgba(68, 170, 119, 0.15); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-webkit-slider-runnable-track {
|
|
|
+ background-color: rgba(68, 170, 119, 0.5); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-moz-range-track {
|
|
|
+ background-color: rgba(68, 170, 119, 0.5); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-lower {
|
|
|
+ background-color: rgba(68, 170, 119, 0.45); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-upper {
|
|
|
+ background-color: rgba(68, 170, 119, 0.25); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right {
|
|
|
+ float: right; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview {
|
|
|
+ height: 150px;
|
|
|
+ overflow: hidden; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item {
|
|
|
+ position: relative;
|
|
|
+ padding: 5px;
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ float: left;
|
|
|
+ margin-right: 16px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item span {
|
|
|
+ position: absolute;
|
|
|
+ bottom: -30px;
|
|
|
+ width: 100%;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #bbb;
|
|
|
+ display: block;
|
|
|
+ text-align: center; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item img {
|
|
|
+ position: absolute;
|
|
|
+ display: block;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ margin: auto;
|
|
|
+ padding: 3px;
|
|
|
+ background-color: #fff;
|
|
|
+ border: 1px solid rgba(0, 0, 0, 0.15);
|
|
|
+ overflow: hidden;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -moz-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ user-select: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item.vicp-preview-item-circle {
|
|
|
+ margin-right: 0; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item.vicp-preview-item-circle img {
|
|
|
+ border-radius: 100%; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload {
|
|
|
+ position: relative;
|
|
|
+ -webkit-box-sizing: border-box;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 35px;
|
|
|
+ height: 170px;
|
|
|
+ background-color: rgba(0, 0, 0, 0.03);
|
|
|
+ text-align: center;
|
|
|
+ border: 1px dashed #ddd; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading {
|
|
|
+ display: block;
|
|
|
+ padding: 15px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #999;
|
|
|
+ line-height: 30px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap {
|
|
|
+ margin-top: 12px;
|
|
|
+ background-color: rgba(0, 0, 0, 0.08);
|
|
|
+ border-radius: 3px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress {
|
|
|
+ position: relative;
|
|
|
+ display: block;
|
|
|
+ height: 5px;
|
|
|
+ border-radius: 3px;
|
|
|
+ background-color: #4a7;
|
|
|
+ -webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
|
|
|
+ box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
|
|
|
+ -webkit-transition: width 0.15s linear;
|
|
|
+ transition: width 0.15s linear;
|
|
|
+ background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
|
|
|
+ background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
|
|
|
+ background-size: 40px 40px;
|
|
|
+ -webkit-animation: vicp_progress 0.5s linear infinite;
|
|
|
+ animation: vicp_progress 0.5s linear infinite; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ display: block;
|
|
|
+ top: -3px;
|
|
|
+ right: -3px;
|
|
|
+ width: 9px;
|
|
|
+ height: 9px;
|
|
|
+ border: 1px solid rgba(245, 246, 247, 0.7);
|
|
|
+ -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
|
|
|
+ box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
|
|
|
+ border-radius: 100%;
|
|
|
+ background-color: #4a7; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error,
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success {
|
|
|
+ height: 100px;
|
|
|
+ line-height: 100px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-operate {
|
|
|
+ position: absolute;
|
|
|
+ right: 20px;
|
|
|
+ bottom: 20px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-operate a {
|
|
|
+ position: relative;
|
|
|
+ float: left;
|
|
|
+ display: block;
|
|
|
+ margin-left: 10px;
|
|
|
+ width: 100px;
|
|
|
+ height: 36px;
|
|
|
+ line-height: 36px;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #4a7;
|
|
|
+ border-radius: 2px;
|
|
|
+ overflow: hidden;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -moz-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ user-select: none; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-operate a:hover {
|
|
|
+ background-color: rgba(0, 0, 0, 0.03); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-error,
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-success {
|
|
|
+ display: block;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 24px;
|
|
|
+ height: 24px;
|
|
|
+ color: #d10;
|
|
|
+ text-align: center;
|
|
|
+ vertical-align: top; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-success {
|
|
|
+ color: #4a7; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-icon3 {
|
|
|
+ position: relative;
|
|
|
+ display: inline-block;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ top: 4px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-icon3::after {
|
|
|
+ position: absolute;
|
|
|
+ top: 3px;
|
|
|
+ left: 6px;
|
|
|
+ width: 6px;
|
|
|
+ height: 10px;
|
|
|
+ border-width: 0 2px 2px 0;
|
|
|
+ border-color: #4a7;
|
|
|
+ border-style: solid;
|
|
|
+ -webkit-transform: rotate(45deg);
|
|
|
+ -ms-transform: rotate(45deg);
|
|
|
+ transform: rotate(45deg);
|
|
|
+ content: ''; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-icon2 {
|
|
|
+ position: relative;
|
|
|
+ display: inline-block;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ top: 4px; }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-icon2::after, .vue-image-crop-upload .vicp-wrap .vicp-icon2::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 9px;
|
|
|
+ left: 4px;
|
|
|
+ width: 13px;
|
|
|
+ height: 2px;
|
|
|
+ background-color: #d10;
|
|
|
+ -webkit-transform: rotate(45deg);
|
|
|
+ -ms-transform: rotate(45deg);
|
|
|
+ transform: rotate(45deg); }
|
|
|
+ .vue-image-crop-upload .vicp-wrap .vicp-icon2::after {
|
|
|
+ -webkit-transform: rotate(-45deg);
|
|
|
+ -ms-transform: rotate(-45deg);
|
|
|
+ transform: rotate(-45deg); }
|
|
|
+.e-ripple {
|
|
|
+ position: absolute;
|
|
|
+ border-radius: 100%;
|
|
|
+ background-color: rgba(0, 0, 0, 0.15);
|
|
|
+ background-clip: padding-box;
|
|
|
+ pointer-events: none;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -moz-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ user-select: none;
|
|
|
+ -webkit-transform: scale(0);
|
|
|
+ -ms-transform: scale(0);
|
|
|
+ transform: scale(0);
|
|
|
+ opacity: 1; }
|
|
|
+ .e-ripple.z-active {
|
|
|
+ opacity: 0;
|
|
|
+ -webkit-transform: scale(2);
|
|
|
+ -ms-transform: scale(2);
|
|
|
+ transform: scale(2);
|
|
|
+ -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
|
|
+ transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
|
|
+ transition: opacity 1.2s ease-out, transform 0.6s ease-out;
|
|
|
+ transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; }
|
|
|
+</style>
|