You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
4.2 KiB

5 months ago
<template>
<view class="v-sign-pen">
<view class="label" v-if="label">{{ label }}</view>
<view class="options">
<view
class="opt-item"
:style="{
minHeight: minWrapHeight,
marginRight: space + 'rpx'
}"
v-for="item in csizes"
:key="item.size"
@click="onItemClick(item)"
>
<view
:class="type"
:style="{
border:
border && currentSelect.size === item.size
? `${borderWidth}rpx solid ${activeColor}`
: ''
}"
>
<view class="inner" :style="[defaultInnerStyle(item)]"></view>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* v-sign-pen 画笔v-sign 子组件
* @description 设置 v-sign 画笔的线宽
* @tutorial
* @property {String} type 选项样式 line / circle
* @property {String} label 标签
* @property {Array} sizes 画笔大小数组单位 px
* @property {String} color 选项颜色
* @property {String} activeColor 选中项颜色
* @property {Boolean} border 选中项是否有边框
* @property {Number} borderWidth 边框大小单位 rpx
* @property {String} space 选项间隙单位 rpx
* @property {Number} bigger 圆点变大变粗倍数
* @property {Number} minSize 圆点最小大小单位 px
* @event {Function} change 选择画笔大小时触发
* @example
**/
// v-sign 父组件提供的接口
let vSignInterface
// 选项样式
const type_style = {
CIRCLE: 'circle',
LINE: 'line'
}
export default {
name: 'v-sign-pen',
props: {
// 选项样式
type: {
type: String,
default: type_style.CIRCLE
},
label: {
type: String
},
// 画笔大小数组,单位是px
sizes: {
type: Array,
default: () => [2, 4, 6, 8, 10]
},
// 选项颜色
color: {
type: String,
default: '#333'
},
// 选中项颜色
activeColor: {
type: String,
default: '#333'
},
// 选中项是否有边框
border: {
type: Boolean,
default: true
},
// 边框大小, 单位 rpx
borderWidth: {
type: Number,
default: 4
},
// 选项间隙, 单位 rpx
space: {
type: Number,
default: 20
},
// 圆点变大变粗倍数
bigger: {
type: Number,
default: 2
},
// 圆点最小大小,单位 px
minSize: {
type: Number,
default: 4
}
},
inject: ['getSignInterface'],
data() {
return {
type_style,
currentSelect: null,
csizes: [],
maxSize: 0,
maxCsize: 0
}
},
computed: {
minWrapHeight() {
let height
switch (this.type) {
case type_style.CIRCLE:
height = this.maxCsize + 10 + 'px'
break
case type_style.LINE:
height = this.maxSize + 4 + 'px'
break
}
return height
}
},
created() {
this.csizes = this.sizes.map((size, index) => {
const csize = (index + 1) * this.bigger + this.minSize
this.maxSize = csize > this.maxSize ? csize : this.maxSize
this.maxCsize = csize > this.maxCsize ? csize : this.maxCsize
return {
size,
csize
}
})
this.currentSelect = this.csizes[0]
},
mounted() {
vSignInterface = this.getSignInterface()
this.setLineWidth()
},
methods: {
onItemClick(opt) {
this.currentSelect = opt
this.setLineWidth()
this.$emit('change', opt.size)
},
setLineWidth() {
vSignInterface.setLineWidth(this.currentSelect.size)
},
defaultInnerStyle(item) {
let width
let height
switch (this.type) {
case type_style.CIRCLE:
width = `${item.csize}px`
height = `${item.csize}px`
break
case type_style.LINE:
width = '20px'
height = `${item.size}px`
break
}
const background = this.currentSelect.size === item.size ? this.activeColor : this.color
return {
width,
height,
background
}
}
}
}
</script>
<style lang="scss" scoped>
.v-sign-pen {
padding: 12rpx;
.label {
font-size: 28rpx;
color: #333;
}
.options {
display: flex;
align-items: flex-end;
.opt-item {
display: flex;
align-items: flex-end;
justify-content: center;
&:last-child {
margin-right: 0;
}
&:active {
transition: transform 0.3s;
transform: scale(1.1);
}
.circle {
border-radius: 50%;
padding: 4rpx;
.inner {
border-radius: 50%;
}
}
.line {
padding: 4rpx;
}
}
}
}
</style>