智能照明系统APP-本地串口
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.
 
 
 
 
 
 
LightingSystemApp-serial/.svn/pristine/6e/6ed55ee6b8d618c051aae2e37eb...

610 lines
18 KiB

<template>
<uni-scroll-view v-on="$listeners">
<div
ref="wrap"
class="uni-scroll-view"
>
<div
ref="main"
:style="{'overflow-x': scrollX?'auto':'hidden','overflow-y': scrollY?'auto':'hidden'}"
class="uni-scroll-view"
>
<div
ref="content"
class="uni-scroll-view-content"
>
<div
v-if="refresherEnabled"
ref="refresherinner"
:style="{'background-color': refresherBackground, 'height': refresherHeight + 'px'}"
class="uni-scroll-view-refresher"
>
<div
v-if="refresherDefaultStyle !== 'none'"
class="uni-scroll-view-refresh"
>
<div class="uni-scroll-view-refresh-inner">
<svg
v-if="refreshState=='pulling'"
:style="{'transform': 'rotate('+ refreshRotate +'deg)'}"
fill="#2BD009"
class="uni-scroll-view-refresh__icon"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
<path
d="M0 0h24v24H0z"
fill="none"
/>
</svg>
<svg
v-if="refreshState=='refreshing'"
class="uni-scroll-view-refresh__spinner"
width="24"
height="24"
viewBox="25 25 50 50"
>
<circle
cx="50"
cy="50"
r="20"
fill="none"
style="color: #2BD009;"
stroke-width="3"
/>
</svg>
</div>
</div>
<slot
v-if="refresherDefaultStyle=='none'"
name="refresher"
/>
</div>
<slot />
</div>
</div>
</div>
</uni-scroll-view>
</template>
<script>
import scroller from 'uni-mixins/scroller/index'
import {
supportsPassive
} from 'uni-shared'
import {
initScrollBounce,
disableScrollBounce
} from 'uni-platform/helpers/scroll'
const passiveOptions = supportsPassive ? {
passive: true
} : false
// const PULLING = 'pulling'
// const REFRESHING = 'refreshing'
export default {
name: 'ScrollView',
mixins: [scroller],
props: {
scrollX: {
type: [Boolean, String],
default: false
},
scrollY: {
type: [Boolean, String],
default: false
},
upperThreshold: {
type: [Number, String],
default: 50
},
lowerThreshold: {
type: [Number, String],
default: 50
},
scrollTop: {
type: [Number, String],
default: 0
},
scrollLeft: {
type: [Number, String],
default: 0
},
scrollIntoView: {
type: String,
default: ''
},
scrollWithAnimation: {
type: [Boolean, String],
default: false
},
enableBackToTop: {
type: [Boolean, String],
default: false
},
refresherEnabled: {
type: [Boolean, String],
default: false
},
refresherThreshold: {
type: Number,
default: 45
},
refresherDefaultStyle: {
type: String,
default: 'back'
},
refresherBackground: {
type: String,
default: '#fff'
},
refresherTriggered: {
type: [Boolean, String],
default: false
}
},
data () {
return {
lastScrollTop: this.scrollTopNumber,
lastScrollLeft: this.scrollLeftNumber,
lastScrollToUpperTime: 0,
lastScrollToLowerTime: 0,
refresherHeight: 0,
refreshRotate: 0,
refreshState: ''
}
},
computed: {
upperThresholdNumber () {
var val = Number(this.upperThreshold)
return isNaN(val) ? 50 : val
},
lowerThresholdNumber () {
var val = Number(this.lowerThreshold)
return isNaN(val) ? 50 : val
},
scrollTopNumber () {
return Number(this.scrollTop) || 0
},
scrollLeftNumber () {
return Number(this.scrollLeft) || 0
}
},
watch: {
scrollTopNumber (val) {
this._scrollTopChanged(val)
},
scrollLeftNumber (val) {
this._scrollLeftChanged(val)
},
scrollIntoView (val) {
this._scrollIntoViewChanged(val)
},
refresherTriggered (val) {
// TODO
if (val === true) {
this._setRefreshState('refreshing')
} else if (val === false) {
this._setRefreshState('restore')
}
}
},
mounted () {
var self = this
this._attached = true
this._scrollTopChanged(this.scrollTopNumber)
this._scrollLeftChanged(this.scrollLeftNumber)
this._scrollIntoViewChanged(this.scrollIntoView)
this.__handleScroll = function (e) {
event.preventDefault()
event.stopPropagation()
self._handleScroll.bind(self, event)()
}
var touchStart = null
var needStop = null
this.__handleTouchMove = function (event) {
var x = event.touches[0].pageX
var y = event.touches[0].pageY
var main = self.$refs.main
if (needStop === null) {
if (Math.abs(x - touchStart.x) > Math.abs(y - touchStart.y)) {
// 横向滑动
if (self.scrollX) {
if (main.scrollLeft === 0 && x > touchStart.x) {
needStop = false
return
} else if (main.scrollWidth === main.offsetWidth + main.scrollLeft && x < touchStart.x) {
needStop = false
return
}
needStop = true
} else {
needStop = false
}
} else {
// 纵向滑动
if (self.scrollY) {
if (main.scrollTop === 0 && y > touchStart.y) {
needStop = false
return
} else if (main.scrollHeight === main.offsetHeight + main.scrollTop && y < touchStart.y) {
needStop = false
return
}
needStop = true
} else {
needStop = false
}
}
}
if (needStop) {
event.stopPropagation()
}
if (self.refresherEnabled && self.refreshState === 'pulling') {
const dy = y - touchStart.y
self.refresherHeight = dy
let rotate = dy / self.refresherThreshold
if (rotate > 1) {
rotate = 1
} else {
rotate = rotate * 360
}
self.refreshRotate = rotate
self.$trigger('refresherpulling', event, {
deltaY: dy
})
}
}
this.__handleTouchStart = function (event) {
if (event.touches.length === 1) {
disableScrollBounce({
disable: true
})
needStop = null
touchStart = {
x: event.touches[0].pageX,
y: event.touches[0].pageY
}
if (self.refresherEnabled && self.refreshState !== 'refreshing' && self.$refs.main.scrollTop === 0) {
self.refreshState = 'pulling'
}
}
}
this.__handleTouchEnd = function (event) {
touchStart = null
disableScrollBounce({
disable: false
})
if (self.refresherHeight >= self.refresherThreshold) {
self._setRefreshState('refreshing')
} else {
self.refresherHeight = 0
self.$trigger('refresherabort', event, {})
}
}
this.$refs.main.addEventListener('touchstart', this.__handleTouchStart, passiveOptions)
this.$refs.main.addEventListener('touchmove', this.__handleTouchMove, passiveOptions)
this.$refs.main.addEventListener('scroll', this.__handleScroll, supportsPassive ? {
passive: false
} : false)
this.$refs.main.addEventListener('touchend', this.__handleTouchEnd, passiveOptions)
initScrollBounce()
},
activated () {
// 还原 scroll-view 滚动位置
this.scrollY && (this.$refs.main.scrollTop = this.lastScrollTop)
this.scrollX && (this.$refs.main.scrollLeft = this.lastScrollLeft)
},
beforeDestroy () {
this.$refs.main.removeEventListener('touchstart', this.__handleTouchStart, passiveOptions)
this.$refs.main.removeEventListener('touchmove', this.__handleTouchMove, passiveOptions)
this.$refs.main.removeEventListener('scroll', this.__handleScroll, supportsPassive ? {
passive: false
} : false)
this.$refs.main.removeEventListener('touchend', this.__handleTouchEnd, passiveOptions)
},
methods: {
scrollTo: function (t, n) {
var i = this.$refs.main
t < 0 ? t = 0 : n === 'x' && t > i.scrollWidth - i.offsetWidth ? t = i.scrollWidth - i.offsetWidth
: n === 'y' && t > i.scrollHeight - i.offsetHeight && (t = i.scrollHeight - i.offsetHeight)
var r = 0
var o = ''
n === 'x' ? r = i.scrollLeft - t : n === 'y' && (r = i.scrollTop - t)
if (r !== 0) {
this.$refs.content.style.transition = 'transform .3s ease-out'
this.$refs.content.style.webkitTransition = '-webkit-transform .3s ease-out'
if (n === 'x') {
o = 'translateX(' + r + 'px) translateZ(0)'
} else {
n === 'y' && (o = 'translateY(' + r + 'px) translateZ(0)')
}
this.$refs.content.removeEventListener('transitionend', this.__transitionEnd)
this.$refs.content.removeEventListener('webkitTransitionEnd', this.__transitionEnd)
this.__transitionEnd = this._transitionEnd.bind(this, t, n)
this.$refs.content.addEventListener('transitionend', this.__transitionEnd)
this.$refs.content.addEventListener('webkitTransitionEnd', this.__transitionEnd)
if (n === 'x') {
// if (e !== 'ios') {
i.style.overflowX = 'hidden'
// }
} else if (n === 'y') {
i.style.overflowY = 'hidden'
}
this.$refs.content.style.transform = o
this.$refs.content.style.webkitTransform = o
}
},
_handleTrack: function ($event) {
if ($event.detail.state === 'start') {
this._x = $event.detail.x
this._y = $event.detail.y
this._noBubble = null
return
}
if ($event.detail.state === 'end') {
this._noBubble = false
}
if (this._noBubble === null && this.scrollY) {
if (Math.abs(this._y - $event.detail.y) / Math.abs(this._x - $event.detail.x) > 1) {
this._noBubble = true
} else {
this._noBubble = false
}
}
if (this._noBubble === null && this.scrollX) {
if (Math.abs(this._x - $event.detail.x) / Math.abs(this._y - $event.detail.y) > 1) {
this._noBubble = true
} else {
this._noBubble = false
}
}
this._x = $event.detail.x
this._y = $event.detail.y
if (this._noBubble) {
$event.stopPropagation()
}
},
_handleScroll: function ($event) {
if (!($event.timeStamp - this._lastScrollTime < 20)) {
this._lastScrollTime = $event.timeStamp
const target = $event.target
this.$trigger('scroll', $event, {
scrollLeft: target.scrollLeft,
scrollTop: target.scrollTop,
scrollHeight: target.scrollHeight,
scrollWidth: target.scrollWidth,
deltaX: this.lastScrollLeft - target.scrollLeft,
deltaY: this.lastScrollTop - target.scrollTop
})
if (this.scrollY) {
if (target.scrollTop <= this.upperThresholdNumber && this.lastScrollTop - target.scrollTop > 0 && $event.timeStamp - this.lastScrollToUpperTime > 200) {
this.$trigger('scrolltoupper', $event, {
direction: 'top'
})
this.lastScrollToUpperTime = $event.timeStamp
}
if (target.scrollTop + target.offsetHeight + this.lowerThresholdNumber >= target.scrollHeight && this.lastScrollTop - target.scrollTop < 0 && $event.timeStamp - this.lastScrollToLowerTime > 200) {
this.$trigger('scrolltolower', $event, {
direction: 'bottom'
})
this.lastScrollToLowerTime = $event.timeStamp
}
}
if (this.scrollX) {
if (target.scrollLeft <= this.upperThresholdNumber && this.lastScrollLeft - target.scrollLeft > 0 && $event.timeStamp - this.lastScrollToUpperTime > 200) {
this.$trigger('scrolltoupper', $event, {
direction: 'left'
})
this.lastScrollToUpperTime = $event.timeStamp
}
if (target.scrollLeft + target.offsetWidth + this.lowerThresholdNumber >= target.scrollWidth && this.lastScrollLeft - target.scrollLeft < 0 && $event.timeStamp - this.lastScrollToLowerTime > 200) {
this.$trigger('scrolltolower', $event, {
direction: 'right'
})
this.lastScrollToLowerTime = $event.timeStamp
}
}
this.lastScrollTop = target.scrollTop
this.lastScrollLeft = target.scrollLeft
}
},
_scrollTopChanged: function (val) {
if (this.scrollY) {
if (this._innerSetScrollTop) {
this._innerSetScrollTop = false
} else {
if (this.scrollWithAnimation) {
this.scrollTo(val, 'y')
} else {
this.$refs.main.scrollTop = val
}
}
}
},
_scrollLeftChanged: function (val) {
if (this.scrollX) {
if (this._innerSetScrollLeft) {
this._innerSetScrollLeft = false
} else {
if (this.scrollWithAnimation) {
this.scrollTo(val, 'x')
} else {
this.$refs.main.scrollLeft = val
}
}
}
},
_scrollIntoViewChanged: function (val) {
if (val) {
if (!/^[_a-zA-Z][-_a-zA-Z0-9:]*$/.test(val)) {
console.group('scroll-into-view="' + val + '" 有误')
console.error('id 属性值格式错误。如不能以数字开头。')
console.groupEnd()
return
}
var element = this.$el.querySelector('#' + val)
if (element) {
var mainRect = this.$refs.main.getBoundingClientRect()
var elRect = element.getBoundingClientRect()
if (this.scrollX) {
var left = elRect.left - mainRect.left
var scrollLeft = this.$refs.main.scrollLeft
var x = scrollLeft + left
if (this.scrollWithAnimation) {
this.scrollTo(x, 'x')
} else {
this.$refs.main.scrollLeft = x
}
}
if (this.scrollY) {
var top = elRect.top - mainRect.top
var scrollTop = this.$refs.main.scrollTop
var y = scrollTop + top
if (this.scrollWithAnimation) {
this.scrollTo(y, 'y')
} else {
this.$refs.main.scrollTop = y
}
}
}
}
},
_transitionEnd: function (val, type) {
this.$refs.content.style.transition = ''
this.$refs.content.style.webkitTransition = ''
this.$refs.content.style.transform = ''
this.$refs.content.style.webkitTransform = ''
var main = this.$refs.main
if (type === 'x') {
main.style.overflowX = this.scrollX ? 'auto' : 'hidden'
main.scrollLeft = val
} else if (type === 'y') {
main.style.overflowY = this.scrollY ? 'auto' : 'hidden'
main.scrollTop = val
}
this.$refs.content.removeEventListener('transitionend', this.__transitionEnd)
this.$refs.content.removeEventListener('webkitTransitionEnd', this.__transitionEnd)
},
_setRefreshState (state) {
switch (state) {
case 'refreshing':
this.refresherHeight = this.refresherThreshold
this.$trigger('refresherrefresh', event, {})
break
case 'restore':
this.refresherHeight = 0
this.$trigger('refresherrestore', {}, {})
break
}
this.refreshState = state
},
getScrollPosition () {
const main = this.$refs.main
return {
scrollLeft: main.scrollLeft,
scrollTop: main.scrollTop
}
}
}
}
</script>
<style>
uni-scroll-view {
display: block;
width: 100%;
}
uni-scroll-view[hidden] {
display: none;
}
.uni-scroll-view {
position: relative;
-webkit-overflow-scrolling: touch;
width: 100%;
/* display: flex; 时在安卓下会导致scrollWidth和offsetWidth一样 */
height: 100%;
max-height: inherit;
}
.uni-scroll-view-content {
width: 100%;
height: 100%;
}
.uni-scroll-view-refresher {
position: relative;
overflow: hidden;
}
.uni-scroll-view-refresh {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-scroll-view-refresh-inner {
display: flex;
align-items: center;
justify-content: center;
line-height: 0;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #fff;
box-shadow: 0 1px 6px rgba(0, 0, 0, .117647), 0 1px 4px rgba(0, 0, 0, .117647);
}
.uni-scroll-view-refresh__spinner {
transform-origin: center center;
animation: uni-scroll-view-refresh-rotate 2s linear infinite;
}
.uni-scroll-view-refresh__spinner > circle {
stroke: currentColor;
stroke-linecap: round;
animation: uni-scroll-view-refresh-dash 2s linear infinite;
}
@keyframes uni-scroll-view-refresh-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes uni-scroll-view-refresh-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35px;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124px;
}
}
</style>