Commit 396cbd37 authored by jyx's avatar jyx

删除无用代码,优化样式

parent 4ca10570
<template>
<view class="input-search">
<view class="input-search-box" @click="searchClick">
<view class="input-search-box-icon-search"><icons color="#999999" size="36" icon="search" /></view>
<input
v-if="show || searchVal"
:focus="showSync"
:placeholder="placeholder"
:maxlength="maxlength"
class="input-search-input"
confirm-type="search"
type="text"
v-model="searchVal"
@confirm="confirm"
@blur="blur"
@focus="emitFocus"
/>
<text v-else class="input-search-placeholder">{{ placeholder }}</text>
</view>
<view class="input-search-cancel" v-if="show" @click="cancel">取消</view>
</view>
</template>
<script>
export default {
name: 'input-search',
props: {
placeholder: {
type: String,
default: ''
},
maxlength: {
type: [Number, String],
default: 100
},
value: {
type: [Number, String],
default: ''
}
},
data() {
return {
show: false,
showSync: false,
searchVal: ''
};
},
watch: {
value: {
immediate: true,
handler(newVal) {
this.searchVal = newVal;
if (newVal) {
this.show = true;
}
}
},
focus: {
immediate: true,
handler(newVal) {
if (newVal) {
this.show = true;
this.$nextTick(() => {
this.showSync = true;
});
}
}
},
searchVal(newVal, oldVal) {
this.$emit('input', newVal);
}
},
methods: {
searchClick() {
if (this.show) {
return;
}
this.show = true;
this.$nextTick(() => {
this.showSync = true;
});
},
cancel() {
this.searchVal = '';
this.show = false;
this.showSync = false;
// #ifndef APP-PLUS
uni.hideKeyboard();
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord();
// #endif
this.$emit('cancel', '');
},
confirm() {
// #ifndef APP-PLUS
uni.hideKeyboard();
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord();
// #endif
this.$emit('confirm', this.searchVal);
},
blur() {
// #ifndef APP-PLUS
uni.hideKeyboard();
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord();
// #endif
if (!this.searchVal) {
this.show = false;
this.$nextTick(() => {
this.showSync = false;
});
}
this.$emit('blur', this.searchVal);
},
emitFocus(e) {
this.$emit('focus', e.detail);
}
}
};
</script>
<style lang="scss">
.input-search {
display: flex;
flex-direction: row;
position: relative;
padding: 16rpx 32rpx;
&-box {
display: flex;
box-sizing: border-box;
overflow: hidden;
position: relative;
flex: 1;
justify-content: center;
flex-direction: row;
align-items: center;
height: 70rpx;
background-color: #f0f0f0;
padding: 10rpx 16rpx 10rpx 0;
border: 1rpx solid #e5e5e5;
border-radius: 70rpx;
&-icon-search {
display: flex;
flex-direction: row;
padding: 0 16rpx;
justify-content: center;
align-items: center;
color: #808080;
}
}
&-input {
flex: 1;
color: #333;
}
&-placeholder {
color: #808080;
margin-left: 10rpx;
}
&-cancel {
padding-left: 20rpx;
line-height: 70rpx;
color: #333;
cursor: pointer;
}
}
</style>
<template>
<u-popup :show="showDialog" mode="center" round="20rpx" :closeOnClickOverlay="true" @close="close">
<view class="order-wrap">
<u-icon class="close" name="close" color="#929292" size="26" @click="close"></u-icon>
<view class="item-wrap">
<view style="height: 30rpx;" />
<u-icon name="checkmark-circle-fill" color="#F8425A" size="60"></u-icon>
<u-text size="24" align="center" color="#000" text="\n恭喜您,下单成功!"></u-text>
<view class="btn" @click="clickService">联系客服</view>
<view style="color: #6F6F6F;">(购买玩偶全身及售后服务,请咨询客服)</view>
</view>
</view>
</u-popup>
</template>
<script>
import {
message
} from '@/utils/fun';
export default {
name: "order-dialog",
props: {
show: {
type: Boolean,
default: false
},
},
data() {
return {
showDialog: this.show,
dataList: this.list
};
},
watch: {
show: {
handler: function(newVal, oldVal) {
this.showDialog = newVal;
}
},
list: {
handler: function(newVal, oldVal) {
this.list = newVal
}
}
},
methods: {
close() {
this.showDialog = false
this.$emit('dismiss');
},
clickService() {
// this.close()
this.$emit('showServices');
}
},
}
</script>
<style lang="scss">
.order-wrap {
display: flex;
flex-direction: column;
align-items: flex-end;
border-radius: 30rpx;
width: 550rpx;
padding: 30rpx;
background-color: #fff;
}
.item-wrap{
width: 550rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.btn {
margin: 30rpx 0;
border: solid 2rpx #979797;
height: 70rpx;
line-height: 70rpx;
text-align: center;
width: 200rpx;
font-size: 30rpx;
border-radius: 50rpx;
}
.close {
margin-left: auto;
}
</style>
<template>
<u-popup bgColor="#00000000" :show="showDialog" mode="center" round="20rpx" :closeOnClickOverlay="true"
@close="close">
<view class="container">
<image class="bell" src="../../static/index/bells.png"></image>
<view class="container-wrap">
<view style="font-size: 46rpx;font-weight: 700;">温馨提示</view>
<view class="mt-20" style="color: #6F6F6F;">1.人脸照片仅用于建模过程,生成后会自动删除,不会保留您的人脸照片和数据。
</view>
<view style="color: #6F6F6F;margin-top: 10rpx;">
2.请确保你是用的照片获得本人授权同意禁使用未获得本人授权照片的照片。如因照片未授权对他人肖像权造成侵犯所产生的法律责任由本人承担。</view>
<view style="color: red;margin-top: 20rpx;">* 根据《中华人民共和国消费者权益保护法》第二十五条相关规定,定制化产品不支持退换货。</view>
<view class="confirm" @click="confirm">我知道了</view>
</view>
</view>
</u-popup>
</template>
<script>
import {
message
} from '@/utils/fun';
export default {
name: "pic-tip-dialog",
props: {
show: {
type: Boolean,
default: false
},
},
data() {
return {
showDialog: this.show,
dataList: this.list
};
},
watch: {
show: {
handler: function(newVal, oldVal) {
this.showDialog = newVal;
}
},
list: {
handler: function(newVal, oldVal) {
this.list = newVal
}
}
},
methods: {
close() {
this.showDialog = false
this.$emit('dismiss');
},
confirm() {
this.close()
this.$emit('confirm');
}
},
}
</script>
<style lang="scss">
.container {
width: 600rpx;
.bell {
position: relative;
width: 150rpx;
height: 150rpx;
margin-bottom: -75rpx;
left: 225rpx;
}
.container-wrap {
border-radius: 20rpx;
padding: 100rpx 50rpx 50rpx 50rpx;
background-color: #fff;
display: flex;
flex-direction: column;
align-items: center;
}
.confirm {
margin-top: 30rpx;
border-radius: 50rpx;
background-color: #F8425A;
color: #fff;
width: 300rpx;
height: 70rpx;
line-height: 70rpx;
text-align: center;
}
}
</style>
<template>
<u-popup customStyle="background-color:#00000000;" :show="showDialog" mode="center" round="20rpx"
:closeOnClickOverlay="true" @close="close">
<view class="container">
<view class="service-wrap">
<view class="service-item" v-for="(item, index) in dataList" :key="index">
<u-text align="center" :text="item" mode="link" href="https://www.baidu.com"></u-text>
</view>
</view>
<u-icon name="close-circle" color="#fff" size="30" @click="close"></u-icon>
</view>
</u-popup>
</template>
<script>
import {
message
} from '@/utils/fun';
export default {
name: "service-dialog",
props: {
list: {
type: Array,
default: () => {}
},
show: {
type: Boolean,
default: false
},
},
data() {
return {
showDialog: this.show,
dataList: this.list
};
},
watch: {
show: {
handler: function(newVal, oldVal) {
this.showDialog = newVal;
}
},
list: {
handler: function(newVal, oldVal) {
this.list = newVal
}
}
},
methods: {
close() {
this.showDialog = false
this.$emit('dismiss');
},
clickService() {
}
},
}
</script>
<style lang="scss">
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.service-wrap {
border-radius: 30rpx;
margin-bottom: 30rpx;
width: 500rpx;
padding: 20rpx;
background-color: #fff;
.service-item {
padding: 20rpx;
}
}
</style>
<template>
<view :class="'tag ' + color">{{ text }}</view>
</template>
<script>
export default {
name: 'tag',
props: {
value: String
},
data() {
return {
text: '',
color: 'gray'
};
},
watch: {
value: {
immediate: true,
handler() {
this.create();
}
}
},
created() {
this.create();
},
methods: {
create() {
let [text, color] = this.value.split(':');
this.text = text;
this.color = color;
}
}
};
</script>
<style lang="scss">
@import '@/scss/uni.scss';
.tag {
display: inline-block;
line-height: 1;
margin-left: 20rpx;
padding: 10rpx 28rpx;
vertical-align: middle;
font-weight: normal;
font-size: 26rpx;
font-weight: bold;
color: #2F2F2F;
border-radius: 40rpx;
&.blue {
background-color: $color-primary;
}
&.green {
background-image: linear-gradient(90deg,#6FF1A8 ,#60D9EB);
}
&.yellow {
background-color: $color-warning;
}
&.red {
background-color: $color-error;
}
&.gray {
background-color: $color-cancel;
}
}
</style>
<template>
<view>
<view v-if="!hidetags1" class="tags">
<view class="tags-text">{{ text1 }}</view>
</view>
<view class="tags">
<view class="tags-text">{{ text2 }}</view>
<view class="tags-count">{{ currentCount>=100000?'10W+份':currentCount+'份' }}</view>
</view>
</view>
</template>
<script>
export default {
name: 'tags',
props: {
tags: String,
count: Number,
hideTags1: Boolean,
},
data() {
return {
text1: '',
text2: '',
currentCount: 0,
hidetags1: true,
};
},
watch: {
hideTags1: {
handler(newVal, oldVal) {
this.hidetags1 = newVal;
},
immediate: true
},
tags: {
handler(newVal, oldVal) {
let text = newVal.split(',');
this.text1 = text[0];
this.text2 = text[1];
},
immediate: true
},
count: {
handler(newVal, oldVal) {
this.currentCount = newVal;
},
immediate: true
}
}
};
</script>
<style lang="scss">
@import '@/scss/uni.scss';
.tags {
color: #103B50;
// color: $bg-color;
display: inline-block;
border-radius: 4rpx;
line-height: 1;
font-size: 16rpx;
margin-top: 14rpx;
// background-color: $main-color;
background: -webkit-linear-gradient(left, #03E6CA, #5DC6FD);
/* Safari 5.1-6.0 */
background: -o-linear-gradient(right, #03E6CA, #5DC6FD);
/* Opera 11.1-12.0 */
background: -moz-linear-gradient(right, #03E6CA, #5DC6FD);
/* Firefox 3.6-15 */
background: linear-gradient(to right, #03E6CA, #5DC6FD);
/* 标准语法 */
&-text {
display: inline-block;
padding: 7rpx 10rpx;
vertical-align: middle;
}
&-count {
display: inline-block;
background-color: #4b4b4e;
//color: $main-color;
color: #34FFEF;
border: #34FFEF solid 0.2rpx;
padding: 7rpx 10rpx;
vertical-align: middle;
}
&+.tags {
margin-left: 10rpx;
}
}
</style>
<template>
<view class="team-name flex">
<view class="team-name-avatar" style="margin-right: 14rpx;"><image class="team-name-avatar" v-if="headUrl" :src="headUrl" mode="scaleToFill"></image></view>
<view class="flex-1 ellipsis">{{ team }}</view>
</view>
</template>
<script>
export default {
name: 'team-name',
props: {
team: String,
headUrl: [String, Object]
}
};
</script>
<style lang="scss">
@import '@/scss/uni.scss';
.team-name {
color: #ADADAD;
font-size: 12px;;
align-items: center;
&-avatar {
display: inline-block;
height: 30rpx;
width: 30rpx;
border-radius: 50%;
overflow: hidden;
background-color: #d8d8d8;
}
}
</style>
<template>
<view class="time-down-pay">{{ text }}</view>
</template>
<script>
export default {
name: 'time-down-pay',
props: {
time: String
},
data() {
return {
text: '00:00:00',
timespan: 0,
timer: undefined
};
},
// watch: {
// value: {
// immediate: true,
// handler() {
// this.create();
// }
// }
// },
created() {
console.log(this.time)
this.timespan = new Date(this.time).getTime() - new Date().getTime();
this.countdown();
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
countdown() {
if (this.timespan < 0) {
this.text = '已取消'
} else {
this.timer = setInterval(() => {
console.log('11');
let {
timespan
} = this;
this.timespan -= 1000;
if (this.timespan <= 0) {
this.text = '已取消'
} else {
let leftd = Math.floor(timespan / (1000 * 60 * 60 * 24)), //计算天数
lefth = ('00' + Math.floor((timespan / (1000 * 60 * 60)) % 24)).slice(-2), //计算小时数
leftm = ('00' + Math.floor((timespan / (1000 * 60)) % 60)).slice(-2), //计算分钟数
lefts = ('00' + Math.floor((timespan / 1000) % 60)).slice(-2); //计算秒数
this.text = (leftd > 0 ? leftd + '天' : '') + lefth + ':' + leftm + ':' +
lefts; //返回倒计时的字符串
}
}, 1000);
}
}
}
};
</script>
<style lang="scss">
@import '@/scss/uni.scss';
.time-down {
display: inline-block;
margin-left: 10rpx;
}
</style>
<template>
<view :id="elId" class="v-tabs">
<scroll-view
id="scrollContainer"
:scroll-x="scroll"
:scroll-left="scroll ? scrollLeft : 0"
:scroll-with-animation="scroll"
:style="{ position: fixed ? 'fixed' : 'relative', zIndex: 1993 }"
>
<view
class="v-tabs__container"
:style="{
display: scroll ? 'inline-flex' : 'flex',
whiteSpace: scroll ? 'nowrap' : 'normal',
background: bgColor,
height,
padding
}"
>
<view
:class="['v-tabs__container-item', { disabled: !!v.disabled }]"
v-for="(v, i) in tabs"
:key="i"
:style="{
color: current == i ? activeColor : color,
fontSize: current == i ? fontSize : fontSize,
fontWeight: bold && current == i ? 'bold' : '',
justifyContent: !scroll ? 'center' : '',
flex: scroll ? '' : 1,
padding: paddingItem
}"
@click="change(i)"
>
{{ field ? v[field] : v }}
</view>
<view
v-if="!pills"
:class="['v-tabs__container-line', { animation: lineAnimation }]"
:style="{
background: lineColor,
width: lineWidth + 'px',
height: lineHeight,
borderRadius: lineRadius,
left: lineLeft + 'px',
transform: `translateX(-${lineWidth / 2}px)`
}"
></view>
<view
v-else
:class="['v-tabs__container-pills', { animation: lineAnimation }]"
:style="{
background: pillsColor,
borderRadius: pillsBorderRadius,
left: pillsLeft + 'px',
width: currentWidth + 'px',
height
}"
></view>
</view>
</scroll-view>
<view
class="v-tabs__placeholder"
:style="{
height: fixed ? height : '0',
padding
}"
></view>
</view>
</template>
<script>
/**
* v-tabs
* @property {Number} value 选中的下标
* @property {Array} tabs tabs 列表
* @property {String} bgColor = '#fff' 背景颜色
* @property {String} color = '#333' 默认颜色
* @property {String} activeColor = '#2979ff' 选中文字颜色
* @property {String} fontSize = '28rpx' 默认文字大小
* @property {String} activeFontSize = '28rpx' 选中文字大小
* @property {Boolean} bold = [true | false] 选中文字是否加粗
* @property {Boolean} scroll = [true | false] 是否滚动
* @property {String} height = '60rpx' tab 的高度
* @property {String} lineHeight = '10rpx' 下划线的高度
* @property {String} lineColor = '#2979ff' 下划线的颜色
* @property {Number} lineScale = 0.5 下划线的宽度缩放比例
* @property {String} lineRadius = '10rpx' 下划线圆角
* @property {Boolean} pills = [true | false] 是否胶囊样式
* @property {String} pillsColor = '#2979ff' 胶囊背景色
* @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
* @property {String} field 如果是对象,显示的键名
* @property {Boolean} fixed = [true | false] 是否固定
* @property {String} paddingItem = '0 22rpx' 选项的边距
* @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
*
* @event {Function(current)} change 改变标签触发
*/
export default {
props: {
value: {
type: Number,
default: 0
},
tabs: {
type: Array,
default () {
return []
}
},
bgColor: {
type: String,
default: '#fff'
},
padding: {
type: String,
default: '0'
},
color: {
type: String,
default: '#333'
},
activeColor: {
type: String,
default: '#2979ff'
},
fontSize: {
type: String,
default: '28rpx'
},
activeFontSize: {
type: String,
default: '32rpx'
},
bold: {
type: Boolean,
default: true
},
scroll: {
type: Boolean,
default: true
},
height: {
type: String,
default: '70rpx'
},
lineColor: {
type: String,
default: '#2979ff'
},
lineHeight: {
type: String,
default: '10rpx'
},
lineScale: {
type: Number,
default: 0.5
},
lineRadius: {
type: String,
default: '10rpx'
},
pills: {
type: Boolean,
default: true
},
pillsColor: {
type: String,
default: '#2979ff'
},
pillsBorderRadius: {
type: String,
default: '10rpx'
},
field: {
type: String,
default: ''
},
fixed: {
type: Boolean,
default: false
},
paddingItem: {
type: String,
default: '0 22rpx'
},
lineAnimation: {
type: Boolean,
default: true
}
},
data () {
return {
elId: '',
lineWidth: 30,
currentWidth: 0, // 当前选项的宽度
lineLeft: 0, // 滑块距离左侧的位置
pillsLeft: 0, // 胶囊距离左侧的位置
scrollLeft: 0, // 距离左边的位置
containerWidth: 0, // 容器的宽度
current: 0 // 当前选中项
}
},
watch: {
value (newVal) {
this.current = newVal
this.$nextTick(() => {
this.getTabItemWidth()
})
},
current (newVal) {
this.$emit('input', newVal)
},
tabs (newVal) {
this.$nextTick(() => {
this.getTabItemWidth()
})
}
},
methods: {
// 产生随机字符串
randomString (len) {
len = len || 32
let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
let maxPos = $chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
},
// 切换事件
change (index) {
const isDisabled = !!this.tabs[index].disabled
if (this.current !== index && !isDisabled) {
this.current = index
this.$emit('change', index)
}
},
// 获取左移动位置
getTabItemWidth () {
let query = uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
// 获取容器的宽度
query
.select(`#scrollContainer`)
.boundingClientRect((data) => {
if (!this.containerWidth && data) {
this.containerWidth = data.width
}
})
.exec()
// 获取所有的 tab-item 的宽度
query
.selectAll('.v-tabs__container-item')
.boundingClientRect((data) => {
if (!data) {
return
}
let lineLeft = 0
let currentWidth = 0
if (data) {
for (let i = 0; i < data.length; i++) {
if (i < this.current) {
lineLeft += data[i].width
} else if (i == this.current) {
currentWidth = data[i].width
} else {
break
}
}
}
// 当前滑块的宽度
this.currentWidth = currentWidth
// 缩放后的滑块宽度
this.lineWidth = currentWidth * this.lineScale * 1
// 滑块作移动的位置
this.lineLeft = lineLeft + currentWidth / 2
// 胶囊距离左侧的位置
this.pillsLeft = lineLeft
// 计算滚动的距离左侧的位置
if (this.scroll) {
this.scrollLeft = this.lineLeft - this.containerWidth / 2
}
})
.exec()
}
},
mounted () {
this.elId = 'xfjpeter_' + this.randomString()
this.current = this.value
this.$nextTick(() => {
this.getTabItemWidth()
})
}
}
</script>
<style lang="scss" scoped>
.v-tabs {
width: 100%;
box-sizing: border-box;
overflow: hidden;
::-webkit-scrollbar {
display: none;
}
&__container {
min-width: 100%;
position: relative;
display: inline-flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
&-item {
justify-content: center;
width: 120rpx;
display: flex;
align-items: center;
height: 100%;
position: relative;
z-index: 10;
// padding: 0 11px;
transition: all 0.3s;
white-space: nowrap;
&.disabled {
opacity: 0.5;
color: #999;
}
}
&-line {
position: absolute;
bottom: 0;
}
&-pills {
position: absolute;
z-index: 9;
}
&-line,
&-pills {
&.animation {
transition: all 0.3s linear;
}
}
}
}
</style>
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
// }); // });
// //#endif // //#endif
// }, // },
// } // }
export default { export default {
data() { data() {
return { return {
share: { share: {
title: '3D打印你的专属伴侣,点击立刻拥有她/他!', title: '3D打印你的专属伴侣,点击立刻拥有她/他!',
imageUrl: 'http://mints-sh.oss-cn-shanghai.aliyuncs.com/userImg/share.jpg', imageUrl: 'http://mints-sh.oss-cn-shanghai.aliyuncs.com/userImg/share.jpg',
path: '/pages/loading?shareId='+getApp().globalData.userId, path: '/pages/loading?shareId=' + getApp().globalData.userId,
} }
} }
}, },
...@@ -36,4 +36,4 @@ export default { ...@@ -36,4 +36,4 @@ export default {
}, },
} }
\ No newline at end of file
...@@ -107,7 +107,6 @@ ...@@ -107,7 +107,6 @@
"navigationBarBackgroundColor": "#2196f3", "navigationBarBackgroundColor": "#2196f3",
"navigationBarTextStyle": "black" "navigationBarTextStyle": "black"
} }
}] }]
}], }],
// 分包预载配置 // 分包预载配置
...@@ -134,14 +133,12 @@ ...@@ -134,14 +133,12 @@
"scrollIndicator": "none" "scrollIndicator": "none"
} }
}, },
"condition" : { //模式配置,仅开发期间生效 "condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项) "current": 0, //当前激活的模式(list 的索引项)
"list": [ "list": [{
{ "name": "", //模式名称
"name": "", //模式名称 "path": "", //启动页面,必选
"path": "", //启动页面,必选 "query": "" //启动参数,在页面的onLoad函数里面得到
"query": "" //启动参数,在页面的onLoad函数里面得到 }]
}
]
} }
} }
\ No newline at end of file
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
data() { data() {
return { return {
statusBarHeight: app.globalData.statusBarHeight, statusBarHeight: app.globalData.statusBarHeight,
userBean: null, userBean: {},
versionName: app.globalData.versionName versionName: app.globalData.versionName
}; };
}, },
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
<swiper-item v-for="(list, index) in displaySwiperList" :key="index"> <swiper-item v-for="(list, index) in displaySwiperList" :key="index">
<view v-if="Math.abs(displayIndex-index)==0" style="height: 100%;"> <view v-if="Math.abs(displayIndex-index)==0" style="height: 100%;">
<video v-if="Math.abs(displayIndex-index)==0" :id="''+list.vedioId" :controls="isqp" :isplay="true" <video v-if="Math.abs(displayIndex-index)==0" :id="''+list.vedioId" :controls="controls"
play-btn-position="center" :show-play-btn="isqp" :show-progress="true" :loop="!isplay" :autoplay="true" :isplay="true" play-btn-position="center" :loop="!isplay" @ended="ended"
@ended="ended" @controlstoggle="controlstoggle" :show-fullscreen-btn="false" @controlstoggle="controlstoggle" :show-fullscreen-btn="false" :poster="list.coverImage"
@click="tapVideoHover()" :enable-progress-gesture="false" :style="'width:100%; height:100%;'" :show-loading="true" @click="tapVideoHover()" :enable-progress-gesture="false"
:src="list.recommendUrl" object-fit="fill" /> :style="'width:100%; height:100%;'" :src="list.recommendUrl" object-fit="fill" />
</view> </view>
<view v-if="!isqp" class="userInfo flex"> <view v-if="!isqp" class="userInfo flex">
<!-- 点赞 --> <!-- 点赞 -->
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
oid: 0, oid: 0,
isplay: true, // 是否自动播放下一个视频 isplay: true, // 是否自动播放下一个视频
playCount: 2, // 剩余多少视频加载视频列表 playCount: 2, // 剩余多少视频加载视频列表
issp: false,
isqp: false, // 是否全屏 isqp: false, // 是否全屏
urls: "https://xjc.demo.hongcd.com/api/video/videoRecommend?page=1&uid=0", urls: "https://xjc.demo.hongcd.com/api/video/videoRecommend?page=1&uid=0",
isFirstLoad: true, isFirstLoad: true,
...@@ -147,8 +148,7 @@ ...@@ -147,8 +148,7 @@
}); });
}, },
tapVideoHover() { tapVideoHover() {
// 控制是否全屏 this.isqp = !this.issp
this.isqp = !this.isqp
}, },
ended() { ended() {
// 1.播放当前视频结束时触发,自动切换下一个视频 // 1.播放当前视频结束时触发,自动切换下一个视频
...@@ -226,10 +226,12 @@ ...@@ -226,10 +226,12 @@
this.oid = this.originIndex + 1 this.oid = this.originIndex + 1
this.initSwiperData(this.originIndex); this.initSwiperData(this.originIndex);
} }
this.issp = false
this.isqp = false this.isqp = false
}, },
controlstoggle(e) { controlstoggle(e) {
console.log(e.detail.show); console.log(e.detail.show);
this.issp = e.detail.show
}, },
detail(detail) { detail(detail) {
navigateTo(`/pagesC/video/videoDetail?data=` + encodeURIComponent(JSON.stringify(detail)) + navigateTo(`/pagesC/video/videoDetail?data=` + encodeURIComponent(JSON.stringify(detail)) +
......
<template> <template>
<view class="body"> <view class="body">
<status-title :showBack="true">会员界面</status-title> <status-title :showBack="true" icon-color="white" font-color="white">会员界面</status-title>
<view class="section"> <scroll-view scroll-y style="height: 100%;">
<view class="title">
选择套餐 <image style="width: 100%;" src="@/static/bg_vip_2.png" mode="widthFix" />
</view>
<view class="pack-box"> <view class="section">
<view class="pack-item" :class="[{active: index==selectedIndex}]" v-for='(item, index) in vipList' <view class="title">
:key='index' @click="choosePack(item, index)"> 选择套餐
<view class="name row"> </view>
{{item.title}} <view class="pack-box">
</view> <view class="pack-item" :class="[{active: index==selectedIndex}]" v-for='(item, index) in vipList'
<view class="price row"> :key='index' @click="choosePack(item, index)">
{{item.firstPayPrice}} <view class="name row">
</view> {{item.title}}
<view class="origin row" v-if='item.oldPrice'> </view>
原价:{{item.oldPrice}} <view class="price row">
</view> {{item.firstPayPrice}}
<view class="cut-down" v-if='item.oldPrice-item.firstPayPrice>0'> </view>
立省 {{item.oldPrice-item.firstPayPrice}} <view class="origin row" v-if='item.oldPrice'>
原价:{{item.oldPrice}}
</view>
<view class="cut-down" v-if='item.oldPrice-item.firstPayPrice>0'>
立省 {{item.oldPrice-item.firstPayPrice}}
</view>
</view> </view>
</view> </view>
</view> </view>
</view>
<view class="section">
<view class="section"> <button class="apply-button" @click="handlePay">立即开通</button>
<button class="apply-button" </view>
@click="handlePay">立即开通</button>
</view> <image style="width: 100%;" src="@/static/bg_vip_0.png" mode="widthFix" />
<image style="width: 100%;" src="@/static/bg_vip_1.png" mode="widthFix" />
</scroll-view>
</view> </view>
</template> </template>
...@@ -66,27 +74,27 @@ ...@@ -66,27 +74,27 @@
}, },
choosePack(item, index) { choosePack(item, index) {
this.selectedIndex = index; this.selectedIndex = index;
}, },
handlePay(){ handlePay() {
let vipBean = this.vipList[this.selectedIndex]; let vipBean = this.vipList[this.selectedIndex];
message.notify('vipBean 价格=' + vipBean.firstPayPrice); message.notify('vipBean 价格=' + vipBean.firstPayPrice);
// this.post({ // this.post({
// url: '/vip/getVipPayParams', // url: '/vip/getVipPayParams',
// data: { // data: {
// pid: vipBean.pid, // pid: vipBean.pid,
// payChannel: 'WEIXIN' // payChannel: 'WEIXIN'
// }, // },
// showLoading: false, // showLoading: false,
// success: ({ // success: ({
// data // data
// }) => { // }) => {
// let wxParams = data.params // let wxParams = data.params
// // 发起微信支付 // // 发起微信支付
// } // }
// }); // });
} }
} }
} }
...@@ -94,7 +102,7 @@ ...@@ -94,7 +102,7 @@
<style lang="scss"> <style lang="scss">
.body { .body {
background-color: whitesmoke; background-color: black;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -102,12 +110,12 @@ ...@@ -102,12 +110,12 @@
padding: 0 30rpx; padding: 0 30rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: white; background: black;
.title { .title {
font-size: 32rpx; font-size: 32rpx;
font-weight: 700; font-weight: 700;
color: #333; color: white;
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
...@@ -178,6 +186,7 @@ ...@@ -178,6 +186,7 @@
} }
.apply-button { .apply-button {
width: 86%;
border-radius: 50rpx; border-radius: 50rpx;
background: #e8c8ae; background: #e8c8ae;
color: #8d5a29; color: #8d5a29;
......
<template> <template>
<view class="content"> <view style="width: 100%;height: 100%;">
<status-title style="position: absolute;" iconColor="white" :showBack="true"></status-title> <status-title style="position: absolute;" iconColor="white" :showBack="true"></status-title>
<swiper class="swiper" circular @change="swiperChange" :current="current" :vertical="true"> <swiper class="swiper" circular @change="swiperChange" :current="current" :vertical="true">
<swiper-item v-for="(list, index) in displaySwiperList" :key="index" :style="'width:100%; height:100%;'"> <swiper-item v-for="(list, index) in displaySwiperList" :key="index" :style="'width:100%; height:100%;'">
<view :style="'width:100%; height:100%;'"> <view :style="'width:100%; height:100%;'">
<video v-if="Math.abs(displayIndex-index)==0 && list.vedioUrl" :id="list.vedioIndex" <video v-if="Math.abs(displayIndex-index)==0 && list.vedioUrl" :id="list.vedioId"
:controls="isqp" :loop="!isplay" :enable-progress-gesture="false" :show-progress="true" :controls="controls" :loop="!isplay" :enable-progress-gesture="false" :show-loading="true"
:show-play-btn="isqp" :show-loading="true" :show-fullscreen-btn="false" @ended="ended" :show-fullscreen-btn="false" @ended="ended" @controlstoggle="controlstoggle" @click="tapVides()"
@controlstoggle="controlstoggle" @click="tapVides()" @timeupdate="timeupdate" @timeupdate="timeupdate" style="width:100%; height:100%;background: #f56c6c;"
:style="'width:100%; height:100%;'" :src="list.vedioUrl" :poster="data.coverImage" :src="list.vedioUrl" :poster="data.coverImage" class="tsvideo" play-btn-position="center"
class="tsvideo" play-btn-position="center" object-fit="fill" /> object-fit="fill" />
<view v-if="!isqp" class="userInfo"> <view v-if="!isqp" class="userInfo">
<!-- 点赞 --> <!-- 点赞 -->
<view class="flex" style="opacity: 0.9; margin-top: 10rpx;"> <view class="flex" style="opacity: 0.9; margin-top: 10rpx;">
...@@ -142,6 +142,9 @@ ...@@ -142,6 +142,9 @@
import { import {
data data
} from '../../uni_modules/uview-ui/libs/mixin/mixin'; } from '../../uni_modules/uview-ui/libs/mixin/mixin';
import {
ref
} from "vue";
let audo = uni.createInnerAudioContext() let audo = uni.createInnerAudioContext()
export default { export default {
...@@ -171,7 +174,7 @@ ...@@ -171,7 +174,7 @@
oid: 0, oid: 0,
isplay: true, //是否自动播放下一个视频 isplay: true, //是否自动播放下一个视频
duration: 500, duration: 500,
issp: '', issp: false,
isqp: false, isqp: false,
mid: 0, mid: 0,
safeArea: 0, safeArea: 0,
...@@ -217,21 +220,22 @@ ...@@ -217,21 +220,22 @@
}, },
timeupdate(event) { timeupdate(event) {
if (event.detail.currentTime > 0 && this.originList[this.originIndex].vedioIndex > this.data.unlockIndex) { if (event.detail.currentTime > 0 && this.originList[this.originIndex].vedioIndex > this.data.unlockIndex) {
uni.createVideoContext(this.originList[this.originIndex].vedioIndex, this).seek(0); uni.createVideoContext(this.originList[this.originIndex].vedioId, this).seek(0);
uni.createVideoContext(this.originList[this.originIndex].vedioIndex, this).pause(); uni.createVideoContext(this.originList[this.originIndex].vedioId, this).pause();
this.fenji = 2 this.fenji = 2
this.$refs.select.open('bottom'); this.$refs.select.open('bottom');
} }
}, },
selectThisVideo(index, pays) { selectThisVideo(index) {
this.down(); this.down();
if (this.originList[this.originIndex].vedioIndex > this.data.unlockIndex) { if (this.originList[this.originIndex].vedioIndex > this.data.unlockIndex) {
this.fenji = 2 this.fenji = 2
this.$refs.select.open('bottom'); this.$refs.select.open('bottom');
} else { } else {
console.log("AAAAAAA" + index)
this.duration = 20; this.duration = 20;
this.originIndex = index this.originIndex = index
this.initSwiperData(index); this.initSwiperData(this.originIndex);
setTimeout(() => { setTimeout(() => {
this.duration = 500; this.duration = 500;
}, 500) }, 500)
...@@ -256,7 +260,7 @@ ...@@ -256,7 +260,7 @@
this.$refs.select.open('bottom'); this.$refs.select.open('bottom');
}, },
tapVides() { tapVides() {
this.isqp = !this.isqp this.isqp = !this.issp
}, },
getData() { getData() {
this.originList = [] this.originList = []
...@@ -296,7 +300,6 @@ ...@@ -296,7 +300,6 @@
} else { } else {
this.current = 0 this.current = 0
} }
this.isqp = true
console.log('显示swiper Index:', this.displayIndex) console.log('显示swiper Index:', this.displayIndex)
} }
}, },
...@@ -328,18 +331,16 @@ ...@@ -328,18 +331,16 @@
this.oid = this.originList.length - 1 this.oid = this.originList.length - 1
} }
console.log('++++++++++++上一条播放数据 Index:', this.oid) console.log('++++++++++++上一条播放数据 Index:', this.oid)
uni.createVideoContext("" + this.originList[this.oid].vedioIndex, this).stop(); uni.createVideoContext("" + this.originList[this.oid].vedioId, this).stop();
if (this.originList[originIndex].vedioIndex > this.data.unlockIndex) { if (this.originList[originIndex].vedioIndex > this.data.unlockIndex) {
this.isqp = true
this.fenji = 2 this.fenji = 2
this.$refs.select.open('bottom'); this.$refs.select.open('bottom');
} else { } else {
setTimeout(() => { setTimeout(() => {
this.isqp = true console.log('qqqqqq:', this.originList[originIndex].vedioId)
console.log('qqqqqq:', this.originList[originIndex].vedioIndex)
// audo.play() // audo.play()
uni.createVideoContext("" + this.originList[originIndex].vedioIndex, this).play(); uni.createVideoContext("" + this.originList[originIndex].vedioId, this).play();
this.commitVideo() this.commitVideo()
}, 500) }, 500)
} }
...@@ -369,7 +370,8 @@ ...@@ -369,7 +370,8 @@
this.oid = this.originIndex + 1 this.oid = this.originIndex + 1
this.initSwiperData(this.originIndex); this.initSwiperData(this.originIndex);
} }
this.issp = false
this.isqp = false
}, },
initEpisode() { initEpisode() {
this.subList = [] this.subList = []
...@@ -446,10 +448,6 @@ ...@@ -446,10 +448,6 @@
background: #000000; background: #000000;
} }
.content {
height: 100%;
}
.title { .title {
width: 100%; width: 100%;
display: flex; display: flex;
......
## 1.8.24(2022-05-09)
本地缓存:
- 优化示例项目
## 1.8.23(2022-05-09)
本地缓存:
- 优化清除文件缓存的方法
## 1.8.22(2022-05-09)
本次更新:
- 调整计算转盘绘制的方式
## 1.8.21(2022-05-08)
本次更新:
- 调整示例项目中本地图片的引入方式
## 1.8.20(2022-04-29)
本次更新:
- 修复转盘在某个临界点可以出现多次触发的问题
## 1.8.19(2022-04-27)
本次更新:
- 奖品文字的绘制由先前的两行变成多行,根据设定的每行文字的长度分段绘制
## 1.8.18(2022-04-25)
本次更新:
- 减少小程序平台的 delay
## 1.8.17(2022-03-23)
本次更新:
- 新增配置项 `imgCircled` 奖品图片是否裁切为圆形,默认不裁切
## 1.8.16(2022-03-04)
本次更新:
- 示例项目新增绘制时长的计算,方便开发时定位绘制慢的问题
## 1.8.15(2022-03-02)
本次更新:
- 优化一处错误提示信息的展现方式
## 1.8.14(2021-11-29)
本次更新:
- 示例项目中新增开放自定义权重最大值,没有自定义则取权重数组中的最大值
- 更新文档
## 1.8.13(2021-11-03)
本次更新:
- 注释 `1.8.12` 版本中调试时的代码
## 1.8.12(2021-11-03)
本次更新:
- 修复一些老机型不支持 `flex` 导致布局错乱的问题
## 1.8.11(2021-10-29)
本次更新:
- 优化示例项目中模拟接口访问的速度
## 1.8.10(2021-10-19)
本次更新:
- 优化组件代码
- 更新示例项目
## 1.8.9(2021-09-28)
本次更新:
- 移除内置的 `奖品准备中...` 提示
## 1.8.8(2021-09-27)
本次更新:
- 修复 `1.8.6` 引起的非微信小程序平台绘制异常的问题
## 1.8.7(2021-09-23)
本次更新:
- 优化项目中使用到的图片大小
## 1.8.6(2021-09-23)
本次更新:
- 修复小程序平台在绘制 `base64` 格式的图片时无法在真机模式下正常显示的问题
## 1.8.5(2021-09-13)
本次更新:
- 修复一个已知问题
## 1.8.4(2021-09-12)
本次更新:
- 调整 `strFontColor``strFontColors`,现在可以设置每个区块的文字颜色,详见文档说明
## 1.8.3(2021-09-12)
本次更新:
- 修复因 `1.8.0` 改动引起的文字方向、无奖品图时绘制异常的问题
- 新增 `imgDrawed` 是否绘制奖品图片的配置项 ,默认为 `true`
## 1.8.2(2021-09-10)
本次更新:
**不兼容旧版本的更新**
- 移除配置项 `strKey` 字段
- 调整 `prizeList` 结构
## 1.8.1(2021-09-06)
本次更新:
- 修复 `hbx3.1.22` 在小程序平台处理 `id-name` 存在解析错误的问题
## 1.8.0(2021-09-06)
本次更新:
**该版本更新涉及破坏性的变更,请重新查看 `API - Props` 的部分**
- `px` 全面调整为 `rpx` 单位,多个`Props` 的参数相应调整,请查看文档
- 新增 `pixelRatio` 参数,该参数为设计稿的设备像素比基准值,默认为 `2` 倍素
## 1.7.18(2021-09-05)
本次更新:
- 修复一个已知问题
## 1.7.17(2021-08-23)
本次更新:
- 更新示例项目
## 1.7.16(2021-08-14)
本次更新:
- 更新示例项目
## 1.7.15(2021-08-03)
本次更新:
- 新增文字竖向展示的功能,详见文档说明
## 1.7.13(2021-08-02)
本次更新:
- 更新文档
## 1.7.12(2021-07-30)
本次更新:
- 修复示例项目的已知问题
- 现已提供Almost-Lottery抽奖转盘的uniCloud云端一体页面模板
- 现已提供Almost-Lottery抽奖转盘云端一体页面配套的Admin配置中心
## 1.7.11(2021-07-22)
本次更新:
- 修复部分安卓手机文字大小异常的问题
- 字段 `strHeightMultiple` 更换为 `strLineHeight`
## 1.7.10(2021-07-12)
本次更新:
- 修复奖品名称 `name` 为空字符串时无法成功绘制转盘的问题
- 新增 `prizeNameDrawed` 是否绘制奖品名称的配置项,现在可以仅展示奖品图片了
## 1.7.9(2021-07-09)
本次更新:
- 优化组件内部代码
- 修复奖品图片已然是 `base64` 格式时导致转盘绘制失败的问题
- 文档新增QQ群号,让沟通更便捷
## 1.7.8(2021-07-08)
本次更新:
- 调整 `Canvas` 默认宽高为 `280`
## 1.7.7(2021-07-08)
本次更新:
- 新增多个配置项,满足更多自定义需求
- 优化多行文本情况下非中文字符的字节处理
- 修复偶发的第一条数据文本不居中显示的问题
## 1.7.6(2021-07-02)
本次更新:
- 调整 `imageWidth``imageHeight` 字段为 `imgWidth``imgHeight`
- 更新示例项目
## 1.7.5(2021-07-01)
本次更新:
- 新增配置项 `imgMarginStr` 奖品图片距离奖品文字的距离
## 1.7.4(2021-06-28)
本次更新:
- 新增轮盘旋转或指针旋转配置项
- 转盘内置的外环图片以及按钮图片统一调整为 `image` 展示
- 更新相关文档说明
## 1.7.3(2021-06-16)
本次更新:
- 优化错误提示
- 优化示例项目
- 优化文档说明
## 1.7.2(2021-06-11)
本次更新:
- 新增 `canvasId` 参数配置项,多画板情况下需要配置不同的 `canvasId`
- 优化多画板情况下的缓存功能
- 优化示例项目
- 修改文档说明
## 1.7.1(2021-06-10)
本次更新:
- 优化示例项目中的注释
## 1.7.0(2021-06-04)
本次更新:
- 修复 `1.6.1` 引起的多行奖品文字行高异常的问题
- 新增配置转盘外环和抽奖按钮图片的功能,详见文档说明
- 更新示例项目,新增抽奖次数等业务有关的逻辑供参考
## 1.6.1(2021-05-28)
本次更新:
- 修复小程序平台画板模糊的问题
## 1.6.0(2021-05-28)
本次更新:
- 新增奖品区块是否开启描边的配置项,默认不开启
- 调整画板缓存为默认不开启
- 优化代码
- 优化文档说明
- 更新示例项目并修改部分注释
## 1.5.13(2021-05-22)
本次更新:
- 优化文档说明
- 更新示例项目
## 1.5.12(2021-05-22)
本次更新:
- 新增配置项 `strokeColor` 奖品区块边框颜色
- 更新文档说明
## 1.5.11(2021-05-19)
本次更新:
- 新增`strMarginOutside`参数,用于设置奖品文字距离边缘的距离
- 修复奖品文字在某些情况下不是居中显示的问题
## 1.5.10(2021-05-19)
本次更新:
- 修复示例项目中权重值相同时的取值逻辑
## 1.5.9(2021-05-14)
本次更新:
- 调整代码,优化小程序端的展示
## 1.5.8(2021-05-12)
本次更新:
- 文档增加预警提示:不再维护非 `uni_modules` 模式下的版本
## 1.5.7(2021-05-12)
本次更新:
- 修复小程序平台奖品名称不清晰的问题
## 1.5.6(2021-03-18)
本次更新:
- 适配 uni_modules 插件模式
{
"id": "almost-lottery",
"displayName": "Almost-Lottery抽奖转盘",
"version": "1.8.24",
"description": "【荣获2021插件大赛三等奖】提供奇数、缓存等众多配置项,更有抽奖概率、抽奖次数、付费抽奖等功能内置于示例项目中,完美支持APP、各平台小程序、H5、PC,同时提供 uniCloud 云端版本",
"keywords": [
"转盘",
"抽奖",
"大转盘抽奖"
],
"repository": "https://github.com/ialmost/almost-components_uniapp",
"engines": {
"HBuilderX": "^3.1.22"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "n"
}
}
}
}
}
\ No newline at end of file
# almost-lottery
*使用 Canvas 绘制的抽奖转盘,提供奇数、缓存等众多配置项,更有抽奖概率、抽奖次数、付费抽奖等功能内置于示例项目中*
> <br />
>
> 如果用着还行,请支持一下
> - 前往 [GitHub](https://github.com/ialmost/almost-components_uniapp) 给个 Star
> - 前往 [UniApp](https://ext.dcloud.net.cn/plugin?id=1030) 给个五星
> - 使用中遇到问题时,可以添加 **QQ群 20441313**
>
> <br />
## 基于 uniCloud 开发的云端 Almost-Lottery 抽奖转盘,欢迎尝试体验
- [Almost-Lottery抽奖转盘的云端一体页面](https://ext.dcloud.net.cn/plugin?id=5763)
- [Almost-Lottery抽奖转盘的配置中心](https://ext.dcloud.net.cn/plugin?id=5762)
## 高能预警
- 本插件仅支持 `uni_modules` 模式,强烈推荐使用该模式,**非 `uni_modules` 模式不再维护**
- 在使用本插件之前,强烈建议使用 `HBuilderX` 导入示例项目验证可用性并参照修改
## 功能概要
- [x] 可配置奖品文字 **支持横向/竖向展示**
- [x] 可配置每个奖品区块的背景颜色
- [x] 可配置每个奖品区块的奖品文字颜色
- [x] 可配置奖品区块是否开启描边以及边框的颜色,默认不开启
- [x] 可配置转盘外环和抽奖按钮图
- [x] 可配置每个奖品区块的奖品图片,**当图片是网络地址时,小程序端需要配置白名单,H5端需要允许跨域,奖品文字为竖向时不支持展示奖品图片**
- [x] 奖品列表支持奇数,**奇数时需尽量能被 `360` 除尽**
- [x] 可配置内圈与外圈的间距
- [x] 可配置轮盘旋转或指针旋转
- [x] 可配置画板是否缓存,默认不开启
- [x] 更多配置请查看API说明
## 示例项目附加功能
- [x] 中奖概率,**强烈推荐中奖概率应由后端控制**
- [x] 抽奖次数
- [x] 付费抽奖
## 注意事项
- 编译到小程序端时,请务必勾选ES6转ES5
- `@reset-index="prizeIndex = -1"` 必须默认写入到 `template` 中,不可删除
- 每个奖品区块的奖品图片尺寸不宜过大,图片越大,绘制的过程越慢,尽量将图片尺寸控制在 `100*100` 以内,且图片大小控制在 `40KB` 以内
- 关于中奖概率的配置,请下载示例项目,参照 `pages/index/index.vue` 中的代码进行配置
- 组件本身不涉及任何业务逻辑,与业务相关的代码建议都放在 `pages/index/index.vue`
## 代码演示
#### 基础用法
```
// template
// @reset-index="prizeIndex = -1" 必须默认写入到 template 中,不可删除
<almost-lottery
:prizeList="prizeList"
:prizeIndex="prizeIndex"
@reset-index="prizeIndex = -1"
@draw-start="handleDrawStart"
@draw-end="handleDrawEnd"
@finish="handleDrawFinish"
v-if="prizeList.length"
/>
// script
import AlmostLottery from '@/uni_modules/almost-lottery/components/almost-lottery/almost-lottery.vue'
export default {
components: {
AlmostLottery
},
data () {
return {
// 以下是奖品配置数据
// 奖品数据
prizeList: [],
// 中奖下标
prizeIndex: -1
}
},
methods: {
// 本次抽奖开始
handleDrawStart () {
// 这里需要处理你的中奖逻辑,并得出 prizeIndex
// 请查看示例项目中的代码
},
// 本次抽奖结束
handleDrawEnd () {
// 完成抽奖后,这里处理你拿到结果后的逻辑
// 请查看示例项目中的代码
},
// 抽奖转盘绘制完成
handleDrawFinish (res) {
// 抽奖转盘准备就绪后,这里处理你的逻辑
// 请查看示例项目中的代码
// console.log('抽奖转盘绘制完成', res)
}
}
}
```
## API
#### Props
参数 | 说明 | 类型 | 默认值
:---|:---|:---|:---
pixelRatio | 移动端设计稿的像素比基准值,**涉及到 `rpx` 的适配问题** | *`Number`* | `2`
canvasId | Canvas的标识,**多画板情况下需要配置不同的标识** | *`String`* | `'almostLottery'`
lotterySize | 抽奖转盘的整体尺寸,单位 `rpx` | *`Number`* | `600`
actionSize | 抽奖按钮的尺寸,单位 `rpx` | *`Number`* | `200`
canvasMarginOutside | Canvas边缘距离转盘边缘的距离,单位`rpx` | *`Number`* | `90`
prizeIndex | 获奖奖品在奖品列表中的序号,**每次抽奖结束后会自动重置为 `-1`** | *`Number`* | `-1`
prizeList | 奖品列表,支持奇数(尽量能被 `360` 除尽),**为奇数时需要重设 `colors` 参数** | *`Array`* | -
lotteryBg | 转盘外环图片 | `String` | `默认内置的本地图片`
actionBg | 抽奖按钮图片 | `String` | `默认内置的本地图片`
colors | 奖品区块对应的背景颜色,默认 2 个颜色相互交替,**也可以对每个区块设置不同颜色** | *`Array`* | `['#FFFFFF', '#FFBF05']`
prizeNameDrawed | 是否绘制奖品名称 | *`Boolean`* | `true`
stroked | 是否开启奖品区块描边 | *`Boolean`* | `false`
strDirection | 奖品名称展示方向,可选值 `'horizontal'` => 横向 `'vertical'` => 竖向 | *`String`* | `'horizontal'`
strokeColor | 奖品区块边框颜色 | *`String`* | `'#FFBF05'`
rotateType | 旋转的类型,可选值 `'roulette'` => 轮盘旋转 `'pointer'` => 指针旋转 | *`String`* | `'roulette'`
duration | 转盘旋转的动画时长,单位:秒 | *`Number`* | `8`
ringCount | 旋转的圈数 | *`Number`* | `8`
pointerPosition | 点击抽奖按钮指针的位置,可选值 `'edge'` => 指向边界 `'middle'` => 指向中间 | *`String`* | `'edge'`
strFontColors | 奖品文字颜色,默认 2 个颜色相互交替,**也可以对每个区块的文字设置不同颜色,或仅设置一个颜色** | *`Array`* | `['#FFBF05', '#FFFFFF']`
strFontSize | 奖品名称的字号,单位 `rpx` | *`Number`* | `24`
strLineHeight | 奖品名称多行情况下的行高 | *`Number`* | `1.2`
strMaxLen | 奖品名称长度限制,**文字竖向时不生效** | *`Number`* | `12`
strLineLen | 奖品名称在多行情况下第一行文字的长度,**文字竖向时不生效** | *`Number`* | `6`
strMarginOutside | 奖品文字相对轮盘边缘的距离,单位 `rpx` | *`Number`* | `strFontSize 的一半`
imgMarginStr | 奖品图片相对奖品文字的距离,单位 `rpx` | *`Number`* | `60`
imgWidth | 奖品图片的宽度,单位 `rpx` | *`Number`* | `50`
imgHeight | 奖品图片的高度,单位 `rpx` | *`Number`* | `50`
imgDrawed | 是否绘制奖品图片,默认绘制 | *`Boolean`* | `true`
imgCircled | 奖品图片是否裁切为圆形,默认不裁切 | *`Boolean`* | `false`
successMsg | 转盘绘制成功的提示 | *`String`* | `'奖品准备就绪,快来参与抽奖吧'`
failMsg | 转盘绘制失败的提示 | *`String`* | `'奖品仍在准备中,请稍后再来...'`
canvasCached | 是否开启缓存,避免在数据不变的情况下重复绘制,建议在生产环境中开启 | *`Boolean`* | `false`
#### Events
事件名 | 说明 | 回调参数
:---|:---|:---
@reset-index | 每次抽奖结束后重置获奖的序号为 `-1`**该事件必须默认写入到 `template` 中,不可删除** | -
@draw-start | 转盘旋转开始时触发 | -
@draw-end | 转盘旋转结束时触发 | -
@finish | Canvas转盘绘制完成时触发 | `{ ok: 绘制是否成功, data: 转盘的图片, msg: 绘制结果的提示 }`
#### prizeList 数据结构
*请按如下数据字段对你的奖品列表数据结构进行调整*
键名 | 说明 | 类型
:---|:---|:---
prizeId | 奖品对应 `ID` | *`Number`*
prizeName | 奖品名称 | *`String`*
prizeStock | 奖品库存 | *`Number`*
prizeWeight | 奖品权重 | *`Number`*
prizeImage | 奖品图片地址,网络图片仅支持`http``https`协议 | *`String`*
\ No newline at end of file
/**
* 存储 localStorage 数据
* @param {String} name - 缓存数据的标识
* @param {any} content - 缓存的数据内容
*/
export const setStore = (name, content) => {
if (!name) return
if (typeof content !== 'string') {
content = JSON.stringify(content)
}
uni.setStorageSync(name, content)
}
/**
* 获取 localStorage 数据
* @param {String} name - 缓存数据的标识
*/
export const getStore = (name) => {
if (!name) return
return uni.getStorageSync(name)
}
/**
* 清除 localStorage 数据
* @param {String} name - 缓存数据的标识
*/
export const clearStore = (name) => {
if (name) {
uni.removeStorageSync(name)
} else {
console.log('清理本地全部缓存')
uni.clearStorageSync()
}
}
/**
* 绘制圆形
* @param {String} ctx - 图片网络地址
* @param {String} img - 图片地址
* @param {String} x - x 轴偏移量
* @param {String} y - y 轴偏移量
* @param {String} w - 宽
* @param {String} h - 高
*/
export const circleImg = (ctx, img, x, y, w, h) => {
let r = Math.floor(w/2)
let cx = x + r
let cy = y + r
ctx.save()
ctx.beginPath()
ctx.arc(cx, cy, r, 0, Math.PI * 2)
ctx.fill()
ctx.clip()
ctx.drawImage(img, x, y, w, h)
ctx.restore()
}
/**
* 计算文本的长度
* @param {String} text - 文本内容
*/
export const clacTextLen = (text) => {
if (!text) return { byteLen: 0, realLen: 0 }
text += ''
let clacLen = 0
for (let i = 0; i < text.length; i++) {
if ((text.charCodeAt(i) < 0) || (text.charCodeAt(i) > 255)) {
clacLen += 2
} else {
clacLen += 1
}
}
// console.log(`当前文本 ${text} 的长度为 ${clacLen / 2}`)
return {
byteLen: clacLen,
realLen: clacLen / 2
}
}
/**
* 下载文件,并返回临时路径
* @return {String} 临时路径
* @param {String} fileUrl - 网络地址
*/
export const downloadFile = (fileUrl) => {
return new Promise((resolve) => {
uni.downloadFile({
url: fileUrl,
success: (res) => {
// #ifdef MP-ALIPAY
if (res.errMsg === 'downloadFile:ok') {
resolve({
ok: true,
data: res.errMsg,
tempFilePath: res.tempFilePath
})
} else {
resolve({
ok: false,
data: res.errMsg,
msg: '图片下载失败'
})
}
// #endif
// #ifndef MP-ALIPAY
if (res.statusCode === 200) {
resolve({
ok: true,
data: res.errMsg,
tempFilePath: res.tempFilePath
})
} else {
resolve({
ok: false,
data: res.errMsg,
msg: '图片下载失败'
})
}
// #endif
},
fail: (err) => {
resolve({
ok: false,
data: err.errMsg,
msg: '图片下载失败'
})
}
})
})
}
/**
* 清理应用已缓存的文件
*/
export const clearCacheFile = () => {
// #ifndef H5
uni.getSavedFileList({
success: (res) => {
let fileList = res.fileList
if (fileList.length) {
for (let i = 0; i < fileList.length; i++) {
uni.removeSavedFile({
filePath: fileList[i].filePath,
complete: () => {
console.log('清除缓存已完成')
}
})
}
}
},
fail: (err) => {
console.log('getSavedFileList Fail')
}
})
// #endif
}
// 图像转换工具,可用于图像和base64的转换
// https://ext.dcloud.net.cn/plugin?id=123
const getLocalFilePath = (path) => {
if (
path.indexOf('_www') === 0 ||
path.indexOf('_doc') === 0 ||
path.indexOf('_documents') === 0 ||
path.indexOf('_downloads') === 0
) return path
if (path.indexOf('/storage/emulated/0/') === 0) return path
if (path.indexOf('/storage/sdcard0/') === 0) return path
if (path.indexOf('/var/mobile/') === 0) return path
if (path.indexOf('file://') === 0) return path
if (path.indexOf('/') === 0) {
// ios 无法获取本地路径
let localFilePath = plus.os.name === 'iOS' ? path : plus.io.convertLocalFileSystemURL(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substring(1)
}
}
return '_www/' + path
}
export const pathToBase64 = (path) => {
return new Promise((resolve, reject) => {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
let xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
let canvas = document.createElement('canvas')
let c2x = canvas.getContext('2d')
let img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
let tempPath = getLocalFilePath(path)
plus.io.resolveLocalFileSystemURL(tempPath, (entry) => {
entry.file((file) => {
let fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
console.log(error)
reject(error)
}
fileReader.readAsDataURL(file)
}, (error) => {
reject(error)
})
}, (error) => {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: (res) => {
resolve('data:image/png;base64,' + res.data)
},
fail: (error) => {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export const base64ToPath = (base64) => {
return new Promise((resolve, reject) => {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
let type = base64[0].match(/:(.*?);/)[1]
let str = atob(base64[1])
let n = str.length
let array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], {
type: type
})))
}
let extName = base64.match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
let fileName = Date.now() + '.' + extName
if (typeof plus === 'object') {
let bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, () => {
let filePath = '_doc/uniapp_temp/' + fileName
bitmap.save(filePath, {}, () => {
bitmap.clear()
resolve(filePath)
}, (error) => {
bitmap.clear()
reject(error)
})
}, (error) => {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
let filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: () => {
resolve(filePath)
},
fail: (error) => {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
## 0.7.0(2021-07-10)
- chore: 统一css3 变量 命名规范
- chore: 更新文档
## 0.6.9(2021-07-09)
- chore: 统一命名规范,无须主动引入组件
- fix: 修复第一次传入图片路径无自适应问题
- fix: 修复安卓方向导致无法正确得到尺寸问题
## 0.6.8(2021-06-26)
- fix: 修复 钉钉小程序 返回图片为 `null` 问题
## 0.6.7(2021-06-19)
- fix: 修复`@touchstart`书写错误
## 0.6.6(2021-06-19)
- fix: 修复支付宝引用图标的错误
## 0.6.5(2021-06-14)
- fix: 修复锁定比例失效问题
## 0.6.4(2021-04-16)
- 修复因mode引起的高度异常
## 0.6.3(2021-04-13)
- 测试到微信小程序无法进第二次`draw`,故更新使用`v-model`的方式,显示隐藏组件。
- 原先使用v-if显示隐藏组件依然可以使用,若发现无法二次`draw`请使用`v-model`
```html
<l-clipper v-model="show" />
```
```js
data: () => ({
show: false
})
```
## 0.6.2(2021-03-26)
1、修复图片初始化BUG
2、增加`fileType`属性,默认值为`png`
## 0.6.1(2021-03-10)
- 给事件添加阻止冒泡
## 0.6.0(2021-03-06)
增加`source`属性,`Object`类型,key为图片来源类型,value为选项说明。<br>
```js
// source 默认值
{
album: '从相册中选择',
camera: '拍照',
// #ifdef MP-WEIXIN
message: '从微信中选择'
// #endif
}
```
## 0.5.0(2021-02-26)
- 调整为uni_modules目录规范
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
<style type="text/css">
.st0{fill:#606060;}
.st1{fill:none;stroke:#FFFFFF;stroke-width:2.4306;stroke-miterlimit:10;}
.st2{fill:#FFFFFF;}
</style>
<g>
<path class="st2" d="M11.6,11c0.4,0.4,0.6,0.9,0.6,1.5c0,0.6-0.2,1.1-0.6,1.4c-0.4,0.4-0.9,0.6-1.5,0.6c-0.6,0-1.1-0.2-1.5-0.6
c-0.4-0.4-0.6-0.9-0.6-1.4s0.2-1.1,0.6-1.5c0.4-0.4,0.9-0.6,1.5-0.6C10.8,10.4,11.2,10.6,11.6,11z M24.6,18.4V6.7H5.4v12l1.8-1.8
c0.3-0.3,0.6-0.4,1-0.4c0.4,0,0.7,0.1,1,0.4l1.8,1.8l5.8-7c0.3-0.3,0.6-0.5,1.1-0.5c0.4,0,0.8,0.2,1.1,0.5
C18.8,11.6,24.6,18.4,24.6,18.4z M25.6,5.7C25.9,6,26,6.3,26,6.7v16.1c0,0.4-0.1,0.7-0.4,1c-0.3,0.3-0.6,0.4-1,0.4H5.4
c-0.4,0-0.7-0.1-1-0.4c-0.3-0.3-0.4-0.6-0.4-1V6.7c0-0.4,0.1-0.7,0.4-1c0.3-0.3,0.6-0.4,1-0.4h19.3C25,5.3,25.3,5.4,25.6,5.7z"/>
<path class="st1" d="M24.3,21.5H5.7c-0.2,0-0.3-0.2-0.3-0.3V7c0-0.2,0.2-0.3,0.3-0.3h18.6c0.2,0,0.3,0.2,0.3,0.3v14.2
C24.6,21.3,24.5,21.5,24.3,21.5z"/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="30px" height="30px" viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:2.4306;stroke-miterlimit:10;}
.st1{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M17.1,24.2h-12c-0.2,0-0.3-0.2-0.3-0.3v-9.3c0-0.2,0.2-0.3,0.3-0.3h12c0.2,0,0.3,0.2,0.3,0.3v9.3
C17.5,24.1,17.3,24.2,17.1,24.2z"/>
<path class="st0" d="M16.6,5.4c4.8,0,8.7,3.9,8.7,8.7"/>
<polyline class="st0" points="19.3,10.1 14.9,5.6 19.3,1.2 "/>
</g>
</svg>
$clipper-edge-border-width ?= 6rpx
$clipper-confirm-color ?= #07c160
.flex-auto
flex auto
.bg-transparent
background-color rgba(0, 0, 0, 0.9)
transition-duration 0.35s
.lime-clipper
width 100vw
height calc( 100vh - var(--window-top))
background-color rgba(0, 0, 0, 0.9)
position fixed
top var(--window-top)
left 300vw
z-index 1
&.open
left 0
&-mask
position relative
z-index 2
pointer-events: none
&__content
pointer-events: none;
position absolute
border 1rpx solid rgba(255,255,255,.3)
box-sizing border-box
box-shadow: rgba(0, 0, 0, 0.5) 0 0 0 80vh;
background: transparent;
// transition-duration 0.35s
// transition-property left,top
&::before,&::after
content ''
position absolute
border 1rpx dashed rgba(255,255,255,.3)
&::before
width 100%
top 33.33%
height 33.33%
border-left none
border-right none
&::after
width 33.33%
left 33.33%
height 100%
border-top none
border-bottom none
&__edge
position absolute
// left 6rpx
width 34rpx
height 34rpx
border $clipper-edge-border-width solid #ffffff
pointer-events auto
&::before
content ''
position absolute
width 40rpx
height 40rpx
background-color transparent
&:nth-child(1)
left: - $clipper-edge-border-width
top: - $clipper-edge-border-width
border-bottom-width 0 !important
border-right-width 0 !important
&:before
top -50%
left -50%
&:nth-child(2)
right: - $clipper-edge-border-width
top: - $clipper-edge-border-width
border-bottom-width 0 !important
border-left-width 0 !important
&:before
top -50%
left 50%
&:nth-child(3)
left: - $clipper-edge-border-width
bottom: - $clipper-edge-border-width
border-top-width 0 !important
border-right-width 0 !important
&:before
bottom -50%
left -50%
&:nth-child(4)
right: - $clipper-edge-border-width
bottom: - $clipper-edge-border-width
border-top-width 0 !important
border-left-width 0 !important
&:before
bottom -50%
left 50%
&-image
width 100%
max-width inherit
border-style none
position absolute
top 0
left 0
z-index 1
-webkit-backface-visibility hidden
backface-visibility hidden
transform-origin center
&-canvas
position fixed
z-index 10
left -200vw
top -200vw
pointer-events none
&-tools
position absolute
left 0
bottom 10px
width 100%
z-index 99
color #fff
&__btns
font-weight bold
display flex
align-items center
justify-content space-between
width 100%
padding 20rpx 40rpx
box-sizing border-box
.cancel
width 112rpx
height 60rpx
text-align center
line-height 60rpx
.confirm
width 112rpx
height 60rpx
line-height 60rpx
background var(--lime-clipper-confirm-color, $clipper-confirm-color)
border-radius 6rpx
text-align center
image
display block
width 60rpx
height 60rpx
/**
* 判断手指触摸位置
*/
export function determineDirection(clipX, clipY, clipWidth, clipHeight, currentX, currentY) {
/*
* (右下>>1 右上>>2 左上>>3 左下>>4)
*/
let corner;
/**
* 思路:(利用直角坐标系)
* 1.找出裁剪框中心点
* 2.如点击坐标在上方点与左方点区域内,则点击为左上角
* 3.如点击坐标在下方点与右方点区域内,则点击为右下角
* 4.其他角同理
*/
const mainPoint = [clipX + clipWidth / 2, clipY + clipHeight / 2]; // 中心点
const currentPoint = [currentX, currentY]; // 触摸点
if (currentPoint[0] <= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
corner = 3; // 左上
} else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
corner = 2; // 右上
} else if (currentPoint[0] <= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
corner = 4; // 左下
} else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
corner = 1; // 右下
}
return corner;
}
/**
* 图片边缘检测检测时,计算图片偏移量
*/
export function calcImageOffset(data, scale) {
let left = data.imageLeft;
let top = data.imageTop;
scale = scale || data.scale;
let imageWidth = data.imageWidth;
let imageHeight = data.imageHeight;
if ((data.angle / 90) % 2) {
imageWidth = data.imageHeight;
imageHeight = data.imageWidth;
}
const {
clipX,
clipWidth,
clipY,
clipHeight
} = data;
// 当前图片宽度/高度
const currentImageSize = (size) => (size * scale) / 2;
const currentImageWidth = currentImageSize(imageWidth);
const currentImageHeight = currentImageSize(imageHeight);
left = clipX + currentImageWidth >= left ? left : clipX + currentImageWidth;
left = clipX + clipWidth - currentImageWidth <= left ? left : clipX + clipWidth - currentImageWidth;
top = clipY + currentImageHeight >= top ? top : clipY + currentImageHeight;
top = clipY + clipHeight - currentImageHeight <= top ? top : clipY + clipHeight - currentImageHeight;
return {
left,
top,
scale
};
}
/**
* 图片边缘检测时,计算图片缩放比例
*/
export function calcImageScale(data, scale) {
scale = scale || data.scale;
let {
imageWidth,
imageHeight,
clipWidth,
clipHeight,
angle
} = data
if ((angle / 90) % 2) {
imageWidth = imageHeight;
imageHeight = imageWidth;
}
if (imageWidth * scale < clipWidth) {
scale = clipWidth / imageWidth;
}
if (imageHeight * scale < clipHeight) {
scale = Math.max(scale, clipHeight / imageHeight);
}
return scale;
}
/**
* 计算图片尺寸
*/
export function calcImageSize(width, height, data) {
let imageWidth = width,
imageHeight = height;
let {
clipWidth,
clipHeight,
sysinfo,
width: originWidth,
height: originHeight
} = data
if (imageWidth && imageHeight) {
if (imageWidth / imageHeight > (clipWidth || originWidth) / (clipWidth || originHeight)) {
imageHeight = clipHeight || originHeight;
imageWidth = (width / height) * imageHeight;
} else {
imageWidth = clipWidth || originWidth;
imageHeight = (height / width) * imageWidth;
}
} else {
let sys = sysinfo || uni.getSystemInfoSync();
imageWidth = sys.windowWidth;
imageHeight = 0;
}
return {
imageWidth,
imageHeight
};
}
/**
* 勾股定理求斜边
*/
export function calcPythagoreanTheorem(width, height) {
return Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
}
/**
* 拖动裁剪框时计算
*/
export function clipTouchMoveOfCalculate(data, event) {
const clientX = event.touches[0].clientX;
const clientY = event.touches[0].clientY;
let {
clipWidth,
clipHeight,
clipY: oldClipY,
clipX: oldClipX,
clipStart,
isLockRatio,
maxWidth,
minWidth,
maxHeight,
minHeight
} = data;
maxWidth = maxWidth / 2;
minWidth = minWidth / 2;
minHeight = minHeight / 2;
maxHeight = maxHeight / 2;
let width = clipWidth,
height = clipHeight,
clipY = oldClipY,
clipX = oldClipX,
// 获取裁剪框实际宽度/高度
// 如果大于最大值则使用最大值
// 如果小于最小值则使用最小值
sizecorrect = () => {
width = width <= maxWidth ? (width >= minWidth ? width : minWidth) : maxWidth;
height = height <= maxHeight ? (height >= minHeight ? height : minHeight) : maxHeight;
},
sizeinspect = () => {
if ((width > maxWidth || width < minWidth || height > maxHeight || height < minHeight) && isLockRatio) {
sizecorrect();
return false;
} else {
sizecorrect();
return true;
}
};
//if (clipStart.corner) {
height = clipStart.height + (clipStart.corner > 1 && clipStart.corner < 4 ? 1 : -1) * (clipStart.y - clientY);
//}
switch (clipStart.corner) {
case 1:
width = clipStart.width - clipStart.x + clientX;
if (isLockRatio) {
height = width / (clipWidth / clipHeight);
}
if (!sizeinspect()) return;
break;
case 2:
width = clipStart.width - clipStart.x + clientX;
if (isLockRatio) {
height = width / (clipWidth / clipHeight);
}
if (!sizeinspect()) {
return;
} else {
clipY = clipStart.clipY - (height - clipStart.height);
}
break;
case 3:
width = clipStart.width + clipStart.x - clientX;
if (isLockRatio) {
height = width / (clipWidth / clipHeight);
}
if (!sizeinspect()) {
return;
} else {
clipY = clipStart.clipY - (height - clipStart.height);
clipX = clipStart.clipX - (width - clipStart.width);
}
break;
case 4:
width = clipStart.width + clipStart.x - clientX;
if (isLockRatio) {
height = width / (clipWidth / clipHeight);
}
if (!sizeinspect()) {
return;
} else {
clipX = clipStart.clipX - (width - clipStart.width);
}
break;
default:
break;
}
return {
width,
height,
clipX,
clipY
};
}
/**
* 单指拖动图片计算偏移
*/
export function imageTouchMoveOfCalcOffset(data, clientXForLeft, clientYForLeft) {
let left = clientXForLeft - data.touchRelative[0].x,
top = clientYForLeft - data.touchRelative[0].y;
return {
left,
top
};
}
<template>
</template>
<script>
</script>
<style>
</style>
{
"id": "lime-clipper",
"displayName": "图片剪刀",
"version": "0.7.0",
"description": "一款自我感觉良好的图片裁剪插件",
"keywords": [
"图片裁剪",
"缩放",
"旋转",
"拖动"
],
"repository": "https://gitee.com/liangei/lime-clipper",
"engines": {
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "305716444"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment