提交 3b7b5d79 编写于 作者: Q qiang

feat(h5): 优化 picker 组件大屏展示效果

上级 b8efb97d
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
</transition> </transition>
<div <div
:class="{ 'uni-actionsheet_toggle': visible }" :class="{ 'uni-actionsheet_toggle': visible }"
:style="actionSheetStyle.content" :style="popupStyle.content"
class="uni-actionsheet" class="uni-actionsheet"
> >
<div class="uni-actionsheet__menu"> <div class="uni-actionsheet__menu">
...@@ -38,13 +38,16 @@ ...@@ -38,13 +38,16 @@
取消 取消
</div> </div>
</div> </div>
<div :style="actionSheetStyle.triangle" /> <div :style="popupStyle.triangle" />
</div> </div>
</uni-actionsheet> </uni-actionsheet>
</template> </template>
<script> <script>
import popup from './mixins/popup'
export default { export default {
name: 'ActionSheet', name: 'ActionSheet',
mixins: [popup],
props: { props: {
title: { title: {
type: String, type: String,
...@@ -69,75 +72,6 @@ export default { ...@@ -69,75 +72,6 @@ export default {
default: false default: false
} }
}, },
data () {
return {
width: 0,
height: 0,
top: top
}
},
computed: {
actionSheetStyle () {
const style = {}
const contentStyle = style.content = {}
const triangleStyle = style.triangle = {}
const popover = this.popover
function getNumber (value) {
return Number(value) || 0
}
if (this.width >= 500 && popover) {
Object.assign(triangleStyle, {
position: 'absolute',
width: '0',
height: '0',
'margin-left': '-6px',
'border-style': 'solid'
})
const popoverLeft = getNumber(popover.left)
const popoverWidth = getNumber(popover.width)
const popoverTop = getNumber(popover.top)
const popoverHeight = getNumber(popover.height)
const center = (popoverLeft + popoverWidth) / 2
contentStyle.transform = 'none !important'
const contentLeft = Math.max(0, center - 300 / 2)
contentStyle.left = `${contentLeft}px`
let triangleLeft = Math.max(12, center - contentLeft)
triangleLeft = Math.min(300 - 12, triangleLeft)
triangleStyle.left = `${triangleLeft}px`
const vcl = this.height / 2
if (popoverTop + popoverHeight - vcl > vcl - popoverTop) {
contentStyle.top = 'auto'
contentStyle.bottom = `${this.height - popoverTop + 6}px`
triangleStyle.bottom = '-6px'
triangleStyle['border-width'] = '6px 6px 0 6px'
triangleStyle['border-color'] = '#fcfcfd transparent transparent transparent'
} else {
contentStyle.top = `${popoverTop + popoverHeight + 6}px`
triangleStyle.top = '-6px'
triangleStyle['border-width'] = '0 6px 6px 6px'
triangleStyle['border-color'] = 'transparent transparent #fcfcfd transparent'
}
}
return style
}
},
mounted () {
const fixSize = () => {
const {
windowWidth,
windowHeight,
windowTop
} = uni.getSystemInfoSync()
this.width = windowWidth
this.height = windowHeight + windowTop
this.top = windowTop
}
this.$watch('visible', value => value && fixSize())
window.addEventListener('resize', fixSize)
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', fixSize)
})
},
methods: { methods: {
_close (tapIndex) { _close (tapIndex) {
this.$emit('close', tapIndex) this.$emit('close', tapIndex)
......
export default {
data () {
return {
popupWidth: 0,
popupHeight: 0
}
},
computed: {
popupStyle () {
const style = {}
const contentStyle = style.content = {}
const triangleStyle = style.triangle = {}
const popover = this.popover
function getNumber (value) {
return Number(value) || 0
}
if (this.popupWidth >= 500 && popover) {
Object.assign(triangleStyle, {
position: 'absolute',
width: '0',
height: '0',
'margin-left': '-6px',
'border-style': 'solid'
})
const popoverLeft = getNumber(popover.left)
const popoverWidth = getNumber(popover.width)
const popoverTop = getNumber(popover.top)
const popoverHeight = getNumber(popover.height)
const center = (popoverLeft + popoverWidth) / 2
contentStyle.transform = 'none !important'
const contentLeft = Math.max(0, center - 300 / 2)
contentStyle.left = `${contentLeft}px`
let triangleLeft = Math.max(12, center - contentLeft)
triangleLeft = Math.min(300 - 12, triangleLeft)
triangleStyle.left = `${triangleLeft}px`
const vcl = this.popupHeight / 2
if (popoverTop + popoverHeight - vcl > vcl - popoverTop) {
contentStyle.top = 'auto'
contentStyle.bottom = `${this.popupHeight - popoverTop + 6}px`
triangleStyle.bottom = '-6px'
triangleStyle['border-width'] = '6px 6px 0 6px'
triangleStyle['border-color'] = '#fcfcfd transparent transparent transparent'
} else {
contentStyle.top = `${popoverTop + popoverHeight + 6}px`
triangleStyle.top = '-6px'
triangleStyle['border-width'] = '0 6px 6px 6px'
triangleStyle['border-color'] = 'transparent transparent #fcfcfd transparent'
}
}
return style
}
},
mounted () {
const fixSize = () => {
const {
windowWidth,
windowHeight,
windowTop
} = uni.getSystemInfoSync()
this.popupWidth = windowWidth
this.popupHeight = windowHeight + windowTop
}
this.$watch('visible', value => value && fixSize())
window.addEventListener('resize', fixSize)
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', fixSize)
})
}
}
...@@ -12,12 +12,13 @@ ...@@ -12,12 +12,13 @@
<transition name="uni-fade"> <transition name="uni-fade">
<div <div
v-show="visible" v-show="visible"
class="uni-mask" class="uni-mask uni-picker-mask"
@click="_cancel" @click="_cancel"
/> />
</transition> </transition>
<div <div
:class="{'uni-picker-toggle':visible}" :class="{ 'uni-picker-toggle': visible }"
:style="popupStyle.content"
class="uni-picker" class="uni-picker"
> >
<div <div
...@@ -38,20 +39,21 @@ ...@@ -38,20 +39,21 @@
</div> </div>
</div> </div>
<v-uni-picker-view <v-uni-picker-view
v-if="visible" v-if="contentVisible"
:value.sync="valueArray" :value.sync="valueArray"
class="uni-picker-content" class="uni-picker-content"
> >
<v-uni-picker-view-column <v-uni-picker-view-column
v-for="(rangeItem,index0) in rangeArray" v-for="(rangeItem, index0) in rangeArray"
:key="index0" :key="index0"
> >
<div <div
v-for="(item,index) in rangeItem" v-for="(item, index) in rangeItem"
:key="index" :key="index"
class="uni-picker-item" class="uni-picker-item"
> >
{{ typeof item==='object'?item[rangeKey]||'':item }}{{ units[index0]||'' }} {{ typeof item === "object" ? item[rangeKey] || "" : item
}}{{ units[index0] || "" }}
</div> </div>
</v-uni-picker-view-column> </v-uni-picker-view-column>
</v-uni-picker-view> </v-uni-picker-view>
...@@ -59,6 +61,7 @@ ...@@ -59,6 +61,7 @@
<!-- <div v-if="units.length" class="uni-picker-units"> <!-- <div v-if="units.length" class="uni-picker-units">
<div v-for="(item,index) in units" :key="index">{{item}}</div> <div v-for="(item,index) in units" :key="index">{{item}}</div>
</div>--> </div>-->
<div :style="popupStyle.triangle" />
</div> </div>
</div> </div>
<div> <div>
...@@ -70,6 +73,7 @@ ...@@ -70,6 +73,7 @@
<script> <script>
import { emitter } from 'uni-mixins' import { emitter } from 'uni-mixins'
import { formatDateTime } from 'uni-shared' import { formatDateTime } from 'uni-shared'
import popup from '../../../components/app/popup/mixins/popup'
function getDefaultStartValue () { function getDefaultStartValue () {
if (this.mode === mode.TIME) { if (this.mode === mode.TIME) {
...@@ -122,7 +126,7 @@ const fields = { ...@@ -122,7 +126,7 @@ const fields = {
} }
export default { export default {
name: 'Picker', name: 'Picker',
mixins: [emitter], mixins: [emitter, popup],
props: { props: {
name: { name: {
type: String, type: String,
...@@ -173,6 +177,8 @@ export default { ...@@ -173,6 +177,8 @@ export default {
return { return {
valueSync: null, valueSync: null,
visible: false, visible: false,
contentVisible: false,
popover: null,
valueChangeSource: '', valueChangeSource: '',
timeArray: [], timeArray: [],
dateArray: [], dateArray: [],
...@@ -221,8 +227,19 @@ export default { ...@@ -221,8 +227,19 @@ export default {
return [] return []
} }
} }
}, },
watch: { watch: {
visible (val) {
if (val) {
clearTimeout(this.__contentVisibleDelay)
this.contentVisible = val
} else {
this.__contentVisibleDelay = setTimeout(() => {
this.contentVisible = val
}, 300)
}
},
value () { value () {
this._setValueSync() this._setValueSync()
}, },
...@@ -247,8 +264,7 @@ export default { ...@@ -247,8 +264,7 @@ export default {
const max = dateArray[2].length const max = dateArray[2].length
const day = Number(dateArray[2][valueArray[2]]) || 1 const day = Number(dateArray[2][valueArray[2]]) || 1
const realDay = new Date( const realDay = new Date(
`${dateArray[0][valueArray[0]]}/${ `${dateArray[0][valueArray[0]]}/${dateArray[1][valueArray[1]]
dateArray[1][valueArray[1]]
}/${day}` }/${day}`
).getDate() ).getDate()
if (realDay < day) { if (realDay < day) {
...@@ -292,7 +308,7 @@ export default { ...@@ -292,7 +308,7 @@ export default {
}) })
}, },
methods: { methods: {
_show () { _show (event) {
if (this.disabled) { if (this.disabled) {
return return
} }
...@@ -301,6 +317,13 @@ export default { ...@@ -301,6 +317,13 @@ export default {
$picker.remove(); $picker.remove();
(document.querySelector('uni-app') || document.body).appendChild($picker) (document.querySelector('uni-app') || document.body).appendChild($picker)
$picker.style.display = 'block' $picker.style.display = 'block'
const rect = event.currentTarget.getBoundingClientRect()
this.popover = {
top: rect.top,
left: rect.left,
width: rect.width,
height: rect.height
}
setTimeout(() => { setTimeout(() => {
this.visible = true this.visible = true
}, 20) }, 20)
...@@ -633,4 +656,35 @@ uni-picker[disabled] { ...@@ -633,4 +656,35 @@ uni-picker[disabled] {
text-align: center; text-align: center;
transform: translateX(2em); transform: translateX(2em);
} */ } */
@media screen and (min-width: 500px) {
.uni-mask.uni-picker-mask {
background: none;
}
.uni-picker-container .uni-picker {
width: 300px;
left: 50%;
right: auto;
top: 50%;
bottom: auto;
transform: translate(-50%, -50%);
opacity: 0;
border-radius: 5px;
transition: opacity 0.3s, visibility 0.3s;
box-shadow: 0px 0 20px 5px rgba(0, 0, 0, 0.3);
}
.uni-picker-container .uni-picker-header {
border-radius: 5px 5px 0 0;
}
.uni-picker-container .uni-picker-content {
/* transform 用于解决 Safari overflow 失效的问题 */
transform: translate(0 0);
overflow: hidden;
border-radius: 0 0 5px 5px;
}
.uni-picker-container .uni-picker.uni-picker-toggle {
opacity: 1;
transform: translate(-50%, -50%);
}
}
</style> </style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册