UNPKG

@icreate/ics-mui

Version:

京东风格的轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)

335 lines (334 loc) 11.8 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); import { reactive, ref, computed, watch, onMounted, toRefs, openBlock, createElementBlock, createElementVNode, normalizeStyle, Fragment, renderList, normalizeClass, toDisplayString, createCommentVNode } from "vue"; import { c as createComponent } from "./component-Dt_P47FR.js"; import { d as preventDefault, e as clamp } from "./util-Eu153hxh.js"; import { p as pxCheck } from "./pxCheck-DN6FYV6q.js"; import { u as useTouch } from "./index-I8tfW3Kf.js"; import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.js"; const { create } = createComponent("picker-column"); const _sfc_main = create({ props: { direction: { type: String, default: "horizontal" // vertical旋转90deg方向 }, // 当前选中项 value: [String, Number], columnsType: String, column: { type: Array, default: () => [] }, // 是否开启3D效果 threeDimensional: { type: Boolean, default: true }, swipeDuration: { type: [Number, String], default: 1e3 }, visibleOptionNum: { type: [Number, String], default: 7 }, optionHeight: { type: [Number, String], default: 36 }, fieldNames: { type: Object, default: () => ({}) }, // 特殊环境判断 taro: { type: Boolean, default: false } }, emits: ["click", "change"], setup(props, { emit }) { const touch = useTouch(); const state = reactive({ touchParams: { startX: 0, startY: 0, endY: 0, endX: 0, startTime: 0, endTime: 0, lastX: 0, lastY: 0, lastTime: 0 }, currIndex: 1, transformY: 0, scrollDistance: 0, rotation: 20 }); const roller = ref(null); const moving = ref(false); const touchDeg = ref(0); const touchTime = ref(0); const DEFAULT_DURATION = 200; const INERTIA_TIME = 300; const INERTIA_DISTANCE = 15; const touchRollerStyle = computed(() => { return { transition: `transform ${touchTime.value}ms cubic-bezier(0.17, 0.89, 0.45, 1)`, transform: `rotate3d(1, 0, 0, ${touchDeg.value})`, top: `calc(50% - ${+props.optionHeight / 2}px)` }; }); const touchTileStyle = computed(() => { const { optionHeight } = props; return { transition: `transform ${touchTime.value}ms cubic-bezier(0.17, 0.89, 0.45, 1)`, transform: `translate3d(0, ${state.scrollDistance}px, 0)`, top: `calc(50% - ${+optionHeight / 2}px)`, height: `${optionHeight}px` }; }); const setRollerStyle = (index) => { return `transform: rotate3d(1, 0, 0, ${-state.rotation * index}deg) translate3d(0px, 0px, 104px)`; }; const maskStyles = computed(() => { return { backgroundSize: `100% ${(+props.visibleOptionNum - 1) * +props.optionHeight / 2}px` }; }); const onTouchStart = (event) => { touch.start(event); if (moving.value && !props.taro) { const dom = roller.value; const { transform } = window.getComputedStyle(dom); if (props.threeDimensional) { const circle = Math.floor(parseInt(touchDeg.value) / 360); const cos = +transform.split(", ")[5]; const sin = +transform.split(", ")[6] < 0 ? 180 : 0; const endDeg = circle * 360 + Math.acos(cos) / Math.PI * 180 + sin; state.scrollDistance = -Math.abs((endDeg / state.rotation - 1) * +props.optionHeight); } else { state.scrollDistance = +transform.slice(7, transform.length - 1).split(", ")[5]; } } preventDefault(event, true); state.touchParams.startY = touch.deltaY.value; state.touchParams.startX = touch.deltaX.value; state.touchParams.startTime = Date.now(); state.transformY = state.scrollDistance; }; const onTouchMove = (event) => { touch.move(event); if (touch.isVertical()) { console.log("touch is vertical"); moving.value = true; preventDefault(event, true); } state.touchParams.lastY = touch.deltaY.value; state.touchParams.lastX = touch.deltaX.value; let move = 0; if (props.direction === "horizontal") { move = state.touchParams.lastY - state.touchParams.startY; } if (props.direction === "vertical") { move = state.touchParams.startX - state.touchParams.lastX; } setMove(move); }; const onTouchEnd = () => { state.touchParams.lastY = touch.deltaY.value; state.touchParams.lastX = touch.deltaX.value; state.touchParams.lastTime = Date.now(); let move = 0; if (props.direction === "horizontal") { move = state.touchParams.lastY - state.touchParams.startY; } if (props.direction === "vertical") { move = state.touchParams.startX - state.touchParams.lastX; } let moveTime = state.touchParams.lastTime - state.touchParams.startTime; if (moveTime <= INERTIA_TIME && Math.abs(move) > INERTIA_DISTANCE) { const distance = momentum(move, moveTime); setMove(distance, "end", +props.swipeDuration); return; } else { setMove(move, "end"); } setTimeout(() => { touch.reset(); moving.value = false; }, 0); }; const momentum = (distance, duration) => { const speed = Math.abs(distance / duration); distance = speed / 3e-3 * (distance < 0 ? -1 : 1); return distance; }; const isHidden = (index) => { if (index >= state.currIndex + 8 || index <= state.currIndex - 8) { return true; } else { return false; } }; const setTransform = (translateY = 0, type, time = DEFAULT_DURATION, deg) => { if (type === "end") { touchTime.value = time; } else { touchTime.value = 0; } touchDeg.value = deg; state.scrollDistance = translateY; }; const setMove = (move, type, time) => { const { optionHeight } = props; let updateMove = move + state.transformY; if (type === "end") { if (updateMove > 0) { updateMove = 0; } if (updateMove < -(props.column.length - 1) * +optionHeight) { updateMove = -(props.column.length - 1) * +optionHeight; } let endMove = Math.round(updateMove / +optionHeight) * +optionHeight; let deg = `${(Math.abs(Math.round(endMove / +optionHeight)) + 1) * state.rotation}deg`; setTransform(endMove, type, time, deg); state.currIndex = Math.abs(Math.round(endMove / +optionHeight)) + 1; } else { let deg = 0; let currentDeg = (-updateMove / +optionHeight + 1) * state.rotation; const maxDeg = (props.column.length + 1) * state.rotation; const minDeg = 0; deg = clamp(currentDeg, minDeg, maxDeg); if (minDeg < deg && deg < maxDeg) { setTransform(updateMove, null, void 0, deg + "deg"); state.currIndex = Math.abs(Math.round(updateMove / +optionHeight)) + 1; } } }; const setChooseValue = () => { emit("change", props.column[state.currIndex - 1]); }; const modifyStatus = (type) => { const { column } = props; let index = column.findIndex((columnItem) => columnItem[props.fieldNames.value] === props.value); state.currIndex = index === -1 ? 1 : index + 1; let move = index === -1 ? 0 : index * +props.optionHeight; type && setChooseValue(); setMove(-move); }; const stopMomentum = () => { if (!moving.value && !touchTime.value) return; moving.value = false; touchTime.value = 0; setChooseValue(); }; watch( () => props.column, () => { if (props.column && props.column.length > 0) { state.transformY = 0; modifyStatus(false); } }, { deep: true } ); watch( () => props.value, () => { state.transformY = 0; modifyStatus(false); }, { deep: true, immediate: true } ); onMounted(() => { modifyStatus(true); }); return __spreadProps(__spreadValues(__spreadValues({}, toRefs(state)), toRefs(props)), { setRollerStyle, isHidden, roller, onTouchStart, onTouchMove, onTouchEnd, touchRollerStyle, touchTileStyle, setMove, stopMomentum, pxCheck, maskStyles }); } }); function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("view", { class: "nut-picker__list", onTouchstart: _cache[1] || (_cache[1] = (...args) => _ctx.onTouchStart && _ctx.onTouchStart(...args)), onTouchmove: _cache[2] || (_cache[2] = (...args) => _ctx.onTouchMove && _ctx.onTouchMove(...args)), onTouchend: _cache[3] || (_cache[3] = (...args) => _ctx.onTouchEnd && _ctx.onTouchEnd(...args)) }, [ createElementVNode("view", { ref: "roller", class: "nut-picker-roller", style: normalizeStyle(_ctx.threeDimensional ? _ctx.touchRollerStyle : _ctx.touchTileStyle), onTransitionend: _cache[0] || (_cache[0] = (...args) => _ctx.stopMomentum && _ctx.stopMomentum(...args)) }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.column, (item, index) => { var _a; return openBlock(), createElementBlock(Fragment, { key: (_a = item[_ctx.fieldNames.value]) != null ? _a : index }, [ item && item[_ctx.fieldNames.text] && _ctx.threeDimensional ? (openBlock(), createElementBlock("view", { key: 0, class: normalizeClass(["nut-picker-roller-item", { "nut-picker-roller-item-hidden": _ctx.isHidden(index + 1), [item[_ctx.fieldNames.className]]: item[_ctx.fieldNames.className] }]), style: normalizeStyle(_ctx.setRollerStyle(index + 1)) }, toDisplayString(item[_ctx.fieldNames.text]), 7)) : createCommentVNode("", true), item && item[_ctx.fieldNames.text] && !_ctx.threeDimensional ? (openBlock(), createElementBlock("view", { key: 1, class: normalizeClass(["nut-picker-roller-item-tile", { [item[_ctx.fieldNames.className]]: item[_ctx.fieldNames.className] }]), style: normalizeStyle({ height: _ctx.pxCheck(_ctx.optionHeight), lineHeight: _ctx.pxCheck(_ctx.optionHeight) }) }, toDisplayString(item[_ctx.fieldNames.text]), 7)) : createCommentVNode("", true) ], 64); }), 128)) ], 36), createElementVNode("view", { class: "nut-picker-roller-mask", style: normalizeStyle(_ctx.maskStyles) }, null, 4) ], 32); } const IcsPickerColumn = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { IcsPickerColumn as I };