taro3.x: h5-MovableView兼容解决
MovableView不支持h5,使用onTouchMove实现拖拽
main.tsx
import React, { useEffect, useState } from 'react'
import Taro from '@tarojs/taro'
import {
View,
Image,
Text,
Label,
CheckboxGroup,
Checkbox,
MovableArea,
MovableView
} from '@tarojs/components'
import classnames from 'classnames'
import find from 'lodash/find'
import includes from 'lodash/includes'
import api from '@services/api'
import app from '@services/request'
import './index.scss'
interface ISandState {
value: string
text: string
checked: boolean
}
const INIT_SAND_STATE: ISandState[] = [
{
value: '1',
text: '在售',
checked: true
},
{
value: '2',
text: '待售',
checked: true
},
{
value: '3',
text: '售完',
checked: true
}
]
interface IShowState {
show: boolean
text: string
}
const INIT_SAND_DATA = {
sandBuilding: []
}
const INIT_SHOW_STATE = { show: true, text: '收起' }
interface IProps {
houseId: string,
outerWidth?: number,
outerHeight: number,
currentBuilding?: any,
setCurrentBuilding: (any) => void,
updateSandBuilding: (any) => void
}
let lastPointX: number = 0
let lastPointY: number = 0
let imgTop: number = 0
let imgLeft: number = 0
let maxLeft: number = 0
let maxTop: number = 0
const SandCommon = (props: IProps) => {
const { houseId, outerHeight, currentBuilding = {} } = props
const [movableView, setMovableView] = useState<any>({})
const [showState, setShowState] = useState<IShowState>(INIT_SHOW_STATE)
const [sandState, setSandState] = useState<ISandState[]>(INIT_SAND_STATE)
const [sandData, setSandData] = useState<any>(INIT_SAND_DATA)
const [sandBuilding, setSandBuilding] = useState<any>(INIT_SAND_DATA.sandBuilding)
const [current, setCurrent] = useState<any>({})
const screenWidth = Taro.getSystemInfoSync().screenWidth
const outerWidth = props.outerWidth ? props.outerWidth : screenWidth
useEffect(() => {
fetchSand()
}, [houseId])
useEffect(() => {
setCurrent(currentBuilding)
}, [currentBuilding])
const setImageRealSize = (fang_sand_pic: string) => {
Taro.getImageInfo({
src: fang_sand_pic,
success: (result: any) => {
setMovableView({
width: result.width,
height: result.height,
centerX: (outerWidth - result.width) / 2,
centerY: (outerHeight - result.height) / 2
})
}
})
}
const fetchSand = () => {
app.request({
url: app.areaApiUrl(api.getHouseSand),
data: {
id: houseId
}
}, { loading: false }).then((result: any) => {
setSandData(result)
setImageRealSize(result.fang_sand_pic)
showSandBuilding(INIT_SAND_STATE, result.sandBuilding)
props.updateSandBuilding(result.sandBuilding)
})
}
const toggleShowState = () => {
setShowState({
show: !showState.show,
text: showState.show ? '展开' : '收起'
})
}
const handleCheckboxChange = (e: any) => {
const values = e.detail.value
for (const item of sandState) {
if (includes(values, item.value)) {
item.checked = true
} else {
item.checked = false
}
}
setSandState(sandState)
showSandBuilding(sandState, sandData.sandBuilding)
}
const showSandBuilding = (sandState, allSandBUilding) => {
let sandBuilding: any[] = []
for (const item of allSandBUilding) {
const target = find(sandState, { value: item.sale_status })
if (target.checked) {
sandBuilding.push(item)
}
}
setSandBuilding(sandBuilding)
}
const switchCurrent = (item: any) => {
props.setCurrentBuilding(item)
}
const handleTouchStart = (e: any) => {
const sandView: any = document.getElementsByClassName('sand-view')[0]
maxLeft = outerWidth - movableView.width
maxTop = outerHeight - movableView.height
lastPointX = e.touches[0].clientX;
lastPointY = e.touches[0].clientY;
imgLeft = parseFloat(sandView.style.left)
imgTop = parseFloat(sandView.style.top)
}
const handleTouchMove = (e: any) => {
e.preventDefault();
let changeX = e.touches[0].clientX - lastPointX;
let changeY = e.touches[0].clientY - lastPointY;
let disX = imgLeft + changeX;
let disY = imgTop + changeY;
setMovableView({
...movableView,
centerX: Math.max(Math.min(disX, 0), maxLeft),
centerY: Math.max(Math.min(disY, 0), maxTop)
})
}
const renderSandBuilding = () => {
return sandBuilding.map((item: any, index: number) => (
<View
key={index}
style={item.style}
className={classnames('sand-item', `sale-status-${item.sale_status}`, current.id === item.id && 'actived')}
onClick={() => switchCurrent(item)}
>
<Text>{item.name}</Text>
<Text className="triangle-down"></Text>
</View>
))
}
const renderMovableView = () => {
const { width, height, centerX, centerY } = movableView
return IS_H5 ?
(
<View className="sand-area">
<View
className="sand-view"
style={{
width: `${width}px`,
height: `${height}px`,
left: `${centerX}px`,
top: `${centerY}px`
}}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
>
<Image className="taro-image" src={sandData.fang_sand_pic} />
{renderSandBuilding()}
</View>
</View>
) :
(
<MovableArea className="sand-area">
<MovableView
x={centerX}
y={centerY}
style={{ width, height }}
className="sand-view"
direction="all"
animation={false}
>
<Image className="taro-image" src={sandData.fang_sand_pic} />
{renderSandBuilding()}
</MovableView>
</MovableArea>
)
}
return (
<View className="sand-card" style={{ width: '100%', height: `${outerHeight}px` }}>
{renderMovableView()}
<View className="sand-state">
<CheckboxGroup
onChange={handleCheckboxChange}
className={classnames('sand-state-box', !showState.show && 'hide')}
>
{
sandState.map((item: any, index: any) => (
<Label
key={index}
for={index}
className={classnames('check-label', `sale-status-${item.value}`)}
>
<Checkbox
id={index}
className="check-box"
value={item.value}
checked={item.checked}
>
</Checkbox>
<Text className="check-text">{item.text}</Text>
</Label>
))
}
</CheckboxGroup>
<View className="sand-state-btn" onClick={toggleShowState}>{showState.text}</View>
</View>
</View>
)
}
export default SandCommon

浙公网安备 33010602011771号