From e79c5da820e241bcbbef20e462091e1a49b0462a Mon Sep 17 00:00:00 2001 From: yajun Date: Thu, 20 Oct 2022 10:50:48 +0800 Subject: [PATCH 1/3] =?UTF-8?q?TASK=EF=BC=9A=20#113920-Feature=20component?= =?UTF-8?q?=20datepicker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/picker/README.md | 12 + src/components/picker/datepicker.css.ts | 416 ++++++++ src/components/picker/datepicker.ts | 1249 +++++++++++++++++++++++ src/components/picker/timepicker.css.ts | 156 --- src/components/picker/timepicker.ts | 250 ----- src/index.ts | 2 +- src/test/panels/picker/picker.ts | 9 +- 7 files changed, 1684 insertions(+), 410 deletions(-) create mode 100644 src/components/picker/datepicker.css.ts create mode 100644 src/components/picker/datepicker.ts delete mode 100644 src/components/picker/timepicker.css.ts delete mode 100644 src/components/picker/timepicker.ts diff --git a/src/components/picker/README.md b/src/components/picker/README.md index c49a295..bd219bb 100644 --- a/src/components/picker/README.md +++ b/src/components/picker/README.md @@ -51,3 +51,15 @@ blue ``` + +# PickerBase + +包含正常的picker选择器以及时间选择器(可分为只有时间、只有日期和时间日期都有三种显示) + +效果 +- 伪3D显示,三种日期选择: +(1)只有日期:年月日(yyyy-mm-dd) +(2)只有时间:时分秒(h-m-s) +(3)日期和时间:年月日时分秒(yyyy-mm-dd-h-m-s) + + diff --git a/src/components/picker/datepicker.css.ts b/src/components/picker/datepicker.css.ts new file mode 100644 index 0000000..035d644 --- /dev/null +++ b/src/components/picker/datepicker.css.ts @@ -0,0 +1,416 @@ +import { css } from "lit"; + +export default css` +.p-scroll{ + position: fixed; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + font-family: -apple-system,Helvetica Neue,Helvetica,Arial,sans-serif; + -webkit-tap-highlight-color: rgba(0,0,0,0); + font-size: 14px; + z-index: 9; +} +.p-select-mask{ + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + cursor: pointer; + background: rgba(0,0,0,.7); + -webkit-animation: p-scroll-fade-in .3s ease both; +} +.p-scroll.hide .p-select-mask{ + -webkit-animation: p-scroll-fade-out .3s ease both; +} +.p-select-wrap{ + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: -webkit-flex; + -webkit-align-items: center; + -webkit-justify-content: center; +} +.p-select-main{ + display: -webkit-flex; + -webkit-flex-direction: column; + position: absolute; + bottom: 0; + left: 0; + right: 0; + z-index: 2; + background: #fff; + box-shadow: 0 -5px 10px rgba(0,0,0,.1); + -webkit-animation: p-scroll-in .3s ease both; +} +.p-scroll.hide .p-select-main{ + -webkit-animation: p-scroll-out .3s ease both; +} +@-webkit-keyframes p-scroll-in { + 0%{ -webkit-transform: translate3d(0,100%,0);} + 100%{ -webkit-transform: translate3d(0,0,0);} +} +@-webkit-keyframes p-scroll-out { + 0%{ -webkit-transform: translate3d(0,0,0);} + 100%{ -webkit-transform: translate3d(0,100%,0);} +} +@-webkit-keyframes p-scroll-fade-in { + 0%{ opacity: 0;} + 100%{ opacity: 1;} +} +@-webkit-keyframes p-scroll-fade-out { + 0%{ opacity: 1;} + 100%{ opacity: 0;} +} +.p-select-head{ + position: relative; + height: 45px; + line-height: 45px; + display: -webkit-flex; + -webkit-align-items: center; + -webkit-justify-content: space-between; + background: #f2f2f2; + z-index: 5; +} +.p-select-head:before{ + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + -webkit-transform: scaleY(.5); + background-color: #d5d5d6; +} +.p-select-title{ + -webkit-flex: 1; + font-size: 18px; + color: #333; + text-align: center; +} +.p-select-head a{ + display: block; + padding: 0 15px; + height: 45px; + line-height: 45px; + font-size: 18px; + text-decoration: none; + color: #007aff; +} +.p-select-foot{ + position: relative; + display: -webkit-flex; + -webkit-align-items: center; + background-color: #fff; +} +.p-select-foot:before{ + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1px; + background-color: #d5d5d6; + -webkit-transform: scaleY(0.5); +} +.p-select-foot a{ + position: relative; + display: block; + height: 45px; + line-height: 45px; + font-size: 18px; + text-decoration: none; + color: #007aff; + -webkit-flex: 1; + text-align: center; +} +.p-select-foot a:before{ + content: ""; + position: absolute; + top: 0; + right: 0; + height: 100%; + width: 1px; + background-color: #d5d5d6; + -webkit-transform: scaleX(0.5); +} +.p-select-foot a:last-child:before{ + display: none; +} +.p-select-body{ + position: relative; + margin: 20px auto; + width: 100%; + display: -webkit-flex; + -webkit-align-items: center; + -webkit-justify-content: center; + overflow: hidden; + box-sizing: border-box; +} +.p-select-body ul{ + list-style-type: none; +} +.p-select-item { + position: relative; + display: -webkit-flex; + -webkit-align-items: center; + height: 170px; + text-align: center; + /* overflow: hidden; */ +} +.p-select-col{ + height: 100%; + position: relative; +} +.p-select-ul { + margin: 0; + padding: 0; + position: relative; +} +.p-select-list, +.p-select-wheel, +.p-select-line{ + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 34px; + margin-top: -17px; + box-sizing: border-box; + -webkit-transition: all .3s; +} +.p-select-wheel { + padding: 0; + -webkit-transform-style: preserve-3d; + height: 34px; + z-index: 1; + +} +.p-select-list{ + position: relative; + top: 68px; + margin-top: 0; + z-index: 45; +} +.p-select-line { + height: 34px; + z-index: 100; + pointer-events: none; + box-sizing: border-box; +} +.p-select-line:before, +.p-select-line:after{ + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 1px; + -webkit-transform: scaleY(.5); + background: #a5a5a5; +} +.p-select-line:after{ + top: auto; + bottom: 0; +} +.p-select-label{ + margin: 0 -5px; + min-width: 10px; + display: -webkit-flex; + -webkit-align-items: center; + -webkit-justify-content: center; + box-sizing: border-box; + white-space: nowrap; + z-index: 100; + color: #666; +} +.p-select-label span{ + display: block; + position: relative; + top: -3px; + font-size: 22px; + font-weight: normal; + text-align: center; + z-index: 50; +} + +.p-select-ul>li, +.p-select-wheel>li{ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + padding: 0 10px; + line-height: 34px; + font-size: 21px; + box-sizing: border-box; + cursor: pointer; + -webkit-user-select: none; + text-align: center; +} +.p-select-ul>li{ + color: #666; + font-size: 22px; +} +.p-select-wheel>li { + -webkit-backface-visibility: hidden; + position: absolute; + top: 0; + color: #999; +} +.p-select-wheel>li:active{ + /* opacity: .7;*/ +} +.p-select-wheel>li.visible{ + display: list-item; +} +.p-select-time-split-1{ + position: relative; + top: 0; + right: 0; + bottom: 15px; + margin: 0 15px; + width: 1px; + height: 160px; + -webkit-transform: scaleX(.7) translateZ(200px); + background: -webkit-linear-gradient(90deg,#fff,#ccc 15%,#ccc 85%,#fff); +} + +/*is3d*/ +.p-select-wrap.p-3d .p-select-body{ + -webkit-perspective: 1200; +} +.p-select-wrap.p-3d .p-select-list{ + height: 34px; + overflow:hidden; + background-color: #fff; +} +.p-select-wrap.p-3d .p-select-ul>li, +.p-select-wrap.p-3d .p-select-label{ + color: #2a2b2c; +} +.p-select-wrap.p-3d .p-select-body:before{ + content: ""; + position: absolute; + top: -15px; + bottom: -15px; + left: 0; + right: 0; + background: -webkit-linear-gradient(#fff,rgba(255,255,255,0) 52%,rgba(2555,255,255,0) 48%,#fff); + pointer-events: none; + -webkit-transform: translate3d(0,0,120px); + z-index: 5; +} +.p-select-wrap.p-3d .p-select-line:before{ + top: 1px; +} +.p-select-wrap.p-3d .p-select-line:after{ + bottom: 1px; +} + + +.p-select-wrap.dark .p-select-main, +.p-select-wrap.dark .p-select-body{ + background-color: #080808; +} +.p-select-wrap.dark .p-select-body:before{ + background: -webkit-linear-gradient(#080808,rgba(8,8,8,0) 52%,rgba(8,8,8,0) 48%,#080808); +} +.p-select-wrap.dark .p-select-head{ + background-color: #1c1c1c; + border-bottom: none; +} +.p-select-wrap.dark .p-select-head:before{ + background-color: transparent; +} +.p-select-wrap.dark .p-select-head a{ + color: #ff8400; +} +.p-select-wrap.dark .p-select-list, +.p-select-wrap.dark .p-select-ul>li, +.p-select-wrap.dark .p-select-wheel>li{ + background-color: #080808; +} +.p-select-wrap.dark .p-select-line:before, +.p-select-wrap.dark .p-select-line:after{ + background-color: #444; +} +.p-select-wrap.dark .p-select-time-split-1{ + background: -webkit-linear-gradient(90deg,transparent,#333 15%,#333 85%,transparent); +} +.p-select-wrap.dark .p-select-title, +.p-select-wrap.dark .p-select-label, +.p-select-wrap.dark .p-select-ul>li{ + color: #fff; +} +.p-select-wrap.dark .p-select-foot{ + border-top: none; + background-color: #444; +} +.p-select-wrap.dark .p-select-foot a{ + color: #ff8400; +} +.p-select-wrap.dark .p-select-foot:before, +.p-select-wrap.dark .p-select-foot a:before{ + background-color: #444; +} + +/*center*/ +.p-center{ + position: relative; + top: auto; + left: auto; + -webkit-transform: none; + width: auto; +} +.p-center .p-select-head{ + background-color: #f2f2f2; +} +.p-center .p-select-body{ + min-width: 300px; + padding: 0 25px; + box-sizing: border-box; + background-color: #fff; +} +.p-center .p-select-body:before{ + background: -webkit-linear-gradient(#f7f7f7,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#f7f7f7); +} +.p-center .p-select-main{ + position: relative; + margin: auto; + bottom: auto; + max-width: 400px; + border-radius: 10px; + overflow: hidden; + -webkit-animation: p-scroll-fade-in .3s ease both; +} +.p-scroll.hide .p-center .p-select-main{ + -webkit-animation: p-scroll-fade-out .3s ease both; +} +.p-center .p-select-line{ + border-color: #ccc; +} +.p-center .p-select-list{ + background-color: #fff; +} + + +/*center dark*/ +.p-center.dark .p-select-wrap.dark{ + border: none; +} +.p-center.dark .p-select-head{ + background-color: #000; +} +.p-center.dark .p-select-head:before{ + background-color: #444; +} +.p-center.dark .p-select-foot{ + background-color: #000; +} + +` \ No newline at end of file diff --git a/src/components/picker/datepicker.ts b/src/components/picker/datepicker.ts new file mode 100644 index 0000000..691d8fa --- /dev/null +++ b/src/components/picker/datepicker.ts @@ -0,0 +1,1249 @@ +import { + LitElement, + CSSResultArray, + html, + HTMLTemplateResult, + TemplateResult, + nothing, +} from 'lit' +import {customElement, property, query} from 'lit/decorators.js' +import datepickerCss from './datepicker.css.js' + +function extend(...args: any[]) { + let name, options, src, copy + let length = arguments.length + let target = arguments[0] + for (let i = 1; i < length; i++) { + options = arguments[i] + if (options != null) { + for (name in options) { + src = target[name] + copy = options[name] + if (copy !== undefined) { + target[name] = copy + } + } + } + } + return target +} + +function isPC() { + let userAgentInfo = navigator.userAgent + let Agents = [ + 'Android', + 'iPhone', + 'SymbianOS', + 'Windows Phone', + 'iPad', + 'iPod', + ] + let flag = true + for (let i = 0; i < Agents.length; i++) { + if (userAgentInfo.indexOf(Agents[i]) > 0) { + flag = false + break + } + } + return flag +} + +// picker初始选项 +export interface options { + wheels: pickerwheel[] + container: string + scrollType: string + background: string + display: string + headTitle: string + init: Function + getResult: Function + save: Function + cancel: Function + showLabel?: boolean + labelType?: string + headResult?: false + date?: boolean + time?: boolean + beginYear?: number + endYear?: number + startDate?: '' +} + +// 时间选择器选项——此处后续优化部分 +export interface opt { + container: string + scrollType: string + background: string + showLabel: boolean + labelType: string + display: string + headResult: boolean + date: boolean + time: boolean + beginYear: number + endYear: number + startDate: string + save: Function + cancel: Function +} + +export type itemdate = { + value: number + display: number +} + +// 定义滚轮内容类型 +export type pickerwheel = { + // 无限滚动 + infinite: boolean + // 被选项 + selected: number + // 滚轮数据 + data: Array + label?: string +} + +export type Result = { + value: number + display: number + dataIndex?: number +} + +export type rs = { + result: Result[] + scrollIdx?: number + scrollEvt: any[] +} + +@customElement('star-pickerbase') +export class PickerBase extends LitElement { + public static override get styles(): CSSResultArray { + return [datepickerCss] + } + + // 主题样式、小时制、滚动显示模式 + // @property({type: String}) thememodel = '' + // @property({type: String}) timepickertype = '' + // @property({type: String}) scolltype = '' + @property({type: String}) type = 'base' + + public target: any + public self = this + public clickTarget!: NodeListOf + public option: options = { + // 滚轮数组 + wheels: [], + container: 'body', + scrollType: '3d', + background: 'light', + display: 'bottom', + headTitle: '', + init: function () {}, + getResult: function () {}, + save: function () {}, + cancel: function () {}, + } + // 行数、选项栏高度、选项大小? + public rows = 5 + public itemHeight: number = 34 + public itemSize2d: number = 9 + public itemSize3d: number = 9 + public scrolltest: any + // 3d样式下滚动时的倾斜角度 + public scroll3dAngle = 360 / (this.itemSize3d * 2) + public rs: rs = { + result: [], + scrollEvt: [], + } + + getselectedIdx!: Function + generateItems!: Function + createEL!: Function + snap!: Function + getVal!: Function + destroy!: Function + init!: Function + + constructor() { + super() + const _this = this + // 遍历获取滚轮上被选项的index值 + this.getselectedIdx = function getselectedIdx(wheel: pickerwheel) { + let index = 0 + for (let i = 0; i < wheel.data.length; i++) { + if (wheel.data[i].value == wheel.selected) { + index = i + break + } else { + index = 0 + } + } + return index + } + // 选项生成 + function generateItems( + wheel: pickerwheel, + start: number, + end: number, + is3d: boolean + ) { + let data = wheel.data + let html = '', + value, + display, + len = data.length, + infinite = wheel.infinite, + selectedIdx = _this.getselectedIdx(wheel) + //选中的位置 + start += selectedIdx + end += selectedIdx + + for (let i = start; i <= end; i++) { + let idx = (i < 0 ? len + (i % len) : i) % len + value = data[idx].value + display = data[idx].display + + if (is3d) { + let deg = 0 + let show = 'list-item' + deg = (-(i - selectedIdx) * _this.scroll3dAngle) % 360 + + if (!infinite) { + if (i < 0 || i > len - 1) { + show = 'none' + } else { + show = 'list-item' + } + } + html += + '
  • ' + + display + + '
  • ' + } else { + let opacity = 1 + if (!infinite) { + if (i < 0 || i > len - 1) { + opacity = 0 + } else { + opacity = 1 + } + } + html += + '
  • ' + + display + + '
  • ' + } + } + return html + } + function createEL(wheels: pickerwheel[]) { + let html = '' + html += + '
    ' + html += '
    ' + html += '
    ' + if (_this.option.display != 'center') { + html += + '取消' + } + if (_this.option.headTitle != '') { + html += + '
    ' + _this.option.headTitle + '
    ' + } + if (_this.option.display != 'center') { + html += + '确认' + } + html += '
    ' + html += '
    ' + html += + '
    ' + for (let i = 0; i < wheels.length; i++) { + let label = wheels[i].label + html += '
    ' + html += '
    ' + html += + '
    ' + html += '
      ' + html += generateItems( + wheels[i], + -_this.itemSize2d, + _this.itemSize2d, + false + ) + html += '
    ' + html += '
    ' + if (_this.option.scrollType == '3d') { + html += '
      ' + html += generateItems( + wheels[i], + -_this.itemSize3d, + _this.itemSize3d, + true + ) + html += '
    ' + } + html += '
    ' + if (label) { + html += + '
    ' + + label + + '
    ' + } + html += '
    ' + } + html += '
    ' + if (_this.option.display == 'center') { + html += '
    ' + html += + '取消' + html += + '确认' + html += '
    ' + } + html += '
    ' + html += '
    ' + html += '
    ' + + let node = document.createElement('div') + node.className = 'p-scroll' + node.innerHTML = html + _this.shadowRoot!.querySelector(_this.option.container)!.appendChild(node) + } + function snap(pos: number) { + let pos1 = Math.round(pos), + n1 = Math.round(pos1 % _this.itemHeight), + n2 = _this.itemHeight / 2 + + if (Math.abs(n1) < n2) { + return pos - n1 + } else { + return pos - n1 + (pos1 > 0 ? _this.itemHeight : -_this.itemHeight) + } + } + function getVal( + pos: number, + data: itemdate[], + infinite: boolean, + selectedIdx: number + ) { + let len = data.length, + index1 = + (Math.round(-pos / _this.itemHeight) - + _this.itemSize2d + + selectedIdx) % + len, + index = index1 < 0 ? len + index1 : index1, + dataIndex = + Math.round(-pos / _this.itemHeight) - _this.itemSize2d + selectedIdx, + result = { + value: data[index].value, + display: data[index].display, + dataIndex: dataIndex, + } + return result + } + // item定位 + function getPosition(el:any) { + let style = getComputedStyle(el), + matrix = style.transform, + px + let matrixlist = matrix.split(')')[0].split(', ') + px = Number(matrixlist[13] || matrixlist[5]) + return px + } + function destroy() { + _this.rs = { + result: [], + scrollIdx: 0, + scrollEvt: [], + } + let box = _this.shadowRoot!.querySelector('.p-scroll') + box!.className += ' hide' + setTimeout(function () { + box!.remove() + }, 300) + } + class Scroll { + el: any = 'test' + wheel: any + index: any + opt: any + defaultScrollY: any + constructor(el?: any, wheel?: any, index?: any, opt?: any) { + this.el = el + this.wheel = wheel + this.index = index + this.opt = extend( + { + data: this.wheel.data, + scrollEl2d: el.querySelector('.p-select-ul'), + item2d: el.querySelectorAll('.p-select-ul li'), + scrollY: -_this.itemHeight * _this.itemSize2d, + marginTop: 0, + dataLen: this.wheel.data.length, + lastY: 1, + moveY: 0, + current: 0, + infinite: this.wheel.infinite, + rotateX: 0, + selectedIdx: _this.getselectedIdx(wheel), + transTimer: null, + scrollTimer: null, + clickDown: false, + inertia: true, + }, + opt + ) + if (_this.option.scrollType == '3d') { + this.opt.scrollEl3d = el.querySelector('.p-select-wheel') + this.opt.item3d = el.querySelectorAll('.p-select-wheel li') + } + this.defaultScrollY = this.opt.scrollY + this.init() + } + + init() { + this.Run(0, this.opt.scrollY) + if (isPC()) { + this.el.addEventListener( + 'mousedown', + this.touchStart.bind(this), + false + ) + this.el.addEventListener( + 'mousemove', + this.touchMove.bind(this), + false + ) + this.el.addEventListener('mouseup', this.touchEnd.bind(this), false) + } else { + this.el.addEventListener( + 'touchstart', + this.touchStart.bind(this), + false + ) + this.el.addEventListener( + 'touchmove', + this.touchMove.bind(this), + false + ) + this.el.addEventListener('touchend', this.touchEnd.bind(this), false) + this.el.addEventListener( + 'touchcancel', + this.touchEnd.bind(this), + false + ) + } + + let self = this + if (_this.option.scrollType == '3d') { + //3d点击事件 + this.itemClick(this.opt.item3d) + } else { + //2d点击事件 + this.itemClick(this.opt.item2d) + } + } + itemClick(itemObj:any) { + let self = this + for (let i = 0; i < itemObj.length; i++) { + itemObj[i].addEventListener( + 'click', + function (e:any) { + self.opt.inertia = false + let curIdx = Number(e.target.dataset.index) + let lastIdx = _this.rs.result[self.index].dataIndex as number + let diff = curIdx - lastIdx + self.cusTouch(diff) + }, + false + ) + } + } + Run(interval:any, pos:any) { + if (interval == 0) { + this.opt.scrollEl2d.style.webkitTransition = 'none' + if (_this.option.scrollType == '3d') { + this.opt.scrollEl3d.style.webkitTransition = 'none' + } + } else { + this.opt.scrollEl2d.style.webkitTransition = + 'transform cubic-bezier(0.190, 1.000, 0.220, 1.000) ' + + interval + + 'ms' + if (_this.option.scrollType == '3d') { + this.opt.scrollEl3d.style.webkitTransition = + 'transform cubic-bezier(0.190, 1.000, 0.220, 1.000) ' + + interval + + 'ms' + } + } + this.opt.scrollEl2d.style.webkitTransform = + 'translate3d(0,' + pos + 'px, 0)' + if (_this.option.scrollType == '3d') { + pos = Math.round( + -(pos * (_this.scroll3dAngle / _this.itemHeight)) - 180 + ) + this.opt.scrollEl3d.style.webkitTransform = + 'rotateX(' + pos + 'deg) translate3d(0,0,0)' + } + } + scrollDone() { + clearInterval(this.opt.scrollTimer) + clearTimeout(this.opt.transTimer) + } + onMove(pos?: number, cusDiff?: boolean) { + let self = this, + pos1 = pos || getPosition(this.opt.scrollEl2d), + index = Math.round(-pos1 / _this.itemHeight) - _this.itemSize2d, + diff = index - this.opt.current + if (cusDiff != undefined || diff) { + this.opt.current = index + + //2D + for (let i = 0; i < this.opt.item2d.length; i++) { + let item = this.opt.item2d[i] + let index = Number(item.getAttribute('data-index')) + diff, + len = self.opt.dataLen, + idx = (index < 0 ? len + (index % len) : index) % len, + val = self.opt.data[idx].value, + display = self.opt.data[idx].display + + if (!self.opt.infinite) { + if (index < 0 || index > len - 1) { + item.style.opacity = '0' + } else { + item.style.opacity = '1' + } + } + + item.setAttribute('data-index', index) + item.setAttribute('data-val', val) + item.innerText = display + } + + if (_this.option.scrollType == '3d') { + //3D + for (let i = 0; i < this.opt.item3d.length; i++) { + let item = this.opt.item3d[i] + let index = Number(item.getAttribute('data-index')) + diff, + len = self.opt.dataLen, + idx = (index < 0 ? len + (index % len) : index) % len, + val = self.opt.data[idx].value, + deg = -(index - self.opt.selectedIdx) * _this.scroll3dAngle, + display = self.opt.data[idx].display + if (!self.opt.infinite) { + if (index < 0 || index > len - 1) { + item.style.display = 'none' + } else { + item.style.display = 'list-item' + } + } + item.setAttribute('data-index', index) + item.setAttribute('data-val', val) + item.setAttribute('data-idx', idx) + item.innerText = display + item.style.webkitTransform = + 'rotateX(' + + deg + + 'deg) translateZ(' + + (_this.itemHeight * _this.rows) / 2 + + 'px)' + } + } + + //2d margin-top + this.opt.marginTop += diff * _this.itemHeight + this.opt.scrollEl2d.style.marginTop = this.opt.marginTop + 'px' + } + } + touchStart(e:any) { + if (e.type == 'touchstart') { + this.opt.startY = e.targetTouches['0'].clientY + } else { + this.opt.startY = e.clientY + this.opt.clickDown = true + } + this.opt.startTime = new Date() + } + touchMove(e:any) { + if (e.type == 'touchmove') { + e.preventDefault() + for (let i = 0; i < e.targetTouches.length; i++) { + this.opt.curY = e.targetTouches[i].clientY + } + } else { + if (this.opt.clickDown) { + this.opt.curY = e.clientY + } else { + return false + } + } + + this.opt.moveY = this.opt.curY - this.opt.startY + this.opt.distance = this.opt.scrollY + this.opt.moveY + + if (this.opt.curY < this.opt.lastY) { + //move up + this.opt.direction = 1 + } else if (this.opt.curY > this.opt.lastY) { + //move down + this.opt.direction = -1 + } + + if (this.opt.direction) { + this.onMove() + this.opt.lastY = this.opt.curY + this.Run(0, this.opt.distance) + } + } + touchEnd(e:any) { + if (e.type == 'touchend') { + this.opt.lastY = e.changedTouches['0'].clientY + } else { + if (this.opt.clickDown) { + this.opt.lastY = e.clientY + this.opt.clickDown = false + } else { + return false + } + } + this.opt.endTime = new Date() + + let self = this, + interval = this.opt.endTime - this.opt.startTime, + speed = 500, + addPos = 0 + + //模拟惯性 + if (this.opt.inertia && interval < 300) { + speed = Math.abs(this.opt.moveY / interval) + speed = Math.round(speed * 1000) + addPos = (speed / 3) * (this.opt.moveY < 0 ? -1 : 1) + speed = speed < 500 ? 500 : speed + } else { + addPos = this.opt.moveY + this.opt.inertia = true + } + + this.opt.scrollY += snap(addPos) + this.opt.moveY = 0 + + clearInterval(this.opt.scrollTimer) + this.opt.scrollTimer = setInterval(function () { + self.onMove() + }, 100) + + clearTimeout(this.opt.transTimer) + this.opt.transTimer = setTimeout(function () { + self.onMove() + self.scrollDone() + }, speed) + + //非无限滚动阈值 + if (!this.opt.infinite) { + let maxScroll = + this.opt.selectedIdx * _this.itemHeight - + _this.itemHeight * _this.itemSize2d + let minScroll = + this.opt.selectedIdx * _this.itemHeight - + _this.itemHeight * (this.opt.dataLen - 1) - + _this.itemHeight * _this.itemSize2d + if (this.opt.scrollY > maxScroll) { + this.opt.scrollY = maxScroll + } else if (this.opt.scrollY < minScroll) { + this.opt.scrollY = minScroll + } + } + + this.Run(speed, this.opt.scrollY) + + let res = getVal( + this.opt.scrollY, + this.opt.data, + this.opt.infinite, + this.opt.selectedIdx + ) + _this.rs.result[this.index] = res + _this.rs.scrollIdx = this.index + _this.option.getResult(_this.rs) + } + cusTouch(diff:any) { + let e1 = { + clientY: 0, + targetTouches: [{clientY: 0}], + type: 'click', + } + let e2 = { + clientY: -_this.itemHeight * diff, + targetTouches: [{clientY: -_this.itemHeight * diff}], + type: 'click', + } + let e3 = { + clientY: -_this.itemHeight * diff, + changedTouches: [{clientY: -_this.itemHeight * diff}], + type: 'click', + } + this.touchStart(e1) + this.touchMove(e2) + this.touchEnd(e3) + } + scrollTo(val:any, interval:any) { + this.wheel.selected = val + let selectedIdx = _this.getselectedIdx(this.wheel) + let diff = this.opt.selectedIdx - selectedIdx + this.opt.scrollY = this.defaultScrollY + diff * _this.itemHeight + this.Run(interval, this.opt.scrollY) + this.onMove(this.opt.scrollY, true) + } + removeItem(valArr:any) { + let data = this.opt.data, + resultVal = _this.rs.result[this.index].value, + removeLen = 0, + moveEnd = false + + for (let i = 0; i < data.length; i++) { + for (let j = 0; j < valArr.length; j++) { + if (data[i].value == valArr[j]) { + //移除 + data.splice(i--, 1) + removeLen++ + } else { + if (valArr[j] == resultVal) { + moveEnd = true + } + } + } + } + + if (moveEnd) { + _this.rs.result[this.index] = { + value: data[data.length - 1].value, + display: data[data.length - 1].display, + } + } + this.opt.dataLen = data.length + this.scrollTo(_this.rs.result[this.index].value, 0) + } + appendItem(valArr:any) { + let data = this.opt.data + + //去重 + for (let i = 0; i < data.length; i++) { + for (let j = 0; j < valArr.length; j++) { + if (data[i].value == valArr[j].value) { + valArr.splice(j--, 1) + } + } + } + + //添加 + for (let i = 0; i < valArr.length; i++) { + data.push(valArr[i]) + } + + this.opt.dataLen = data.length + this.scrollTo(_this.rs.result[this.index].value, 0) + } + } + this.init = function init(wheels:any, target:any, isInput:any) { + //创建DOM + createEL(wheels) + let el = _this.shadowRoot!.querySelectorAll('.p-select-item') + for (let i = 0; i < el.length; i++) { + //滚动事件 + let scroll = new Scroll(el[i], wheels[i], i) + + //初始结果 + let res = getVal( + scroll.opt.scrollY, + scroll.opt.data, + scroll.opt.infinite, + scroll.opt.selectedIdx + ) + _this.rs.result.push(res) + _this.rs.scrollEvt.push(scroll) + _this.rs.scrollIdx = 0 + } + //传出初始结果 + _this.option.init(_this.rs) + + let submitBtn = _this.shadowRoot!.querySelector('.p-select-submit-btn'), + cancelBtn = _this.shadowRoot!.querySelector('.p-select-cancel-btn'), + mask = _this.shadowRoot!.querySelector('.p-select-mask') + submitBtn!.addEventListener( + 'click', + function () { + let attr_rs = [], + display = [] + for (let i = 0; i < _this.rs.result.length; i++) { + attr_rs.push(_this.rs.result[i].value) + display.push(_this.rs.result[i].display) + } + target.setAttribute('data-value', attr_rs) + + if (target.isInput) { + target.value = display + } else { + target.innerText = display + } + + _this.option.getResult(_this.rs) + _this.option.save(_this.rs, target) + _this.target = target + destroy() + }, + false + ) + cancelBtn!.addEventListener( + 'click', + function () { + _this.option.cancel() + destroy() + }, + false + ) + mask!.addEventListener( + 'click', + function () { + _this.option.cancel() + destroy() + }, + false + ) + _this.shadowRoot!.querySelector('.p-scroll')!.addEventListener( + 'touchmove', + function (e) { + e.preventDefault() + }, + false + ) + } + } + + public initPicker(el: string, opt: any) { + const _this = this + this.clickTarget = _this.shadowRoot!.querySelectorAll( + el + ) as NodeListOf + this.option = extend(this.option, opt) + for (let i = 0; i < this.clickTarget.length; i++) { + let item = this.clickTarget[i], + wheels = this.option.wheels, + isInput = item.localName == 'input' || item.localName == 'textarea', + attr_rs = item.getAttribute('data-value') + if (attr_rs) { + attr_rs = attr_rs.split(',') + let display = [] + for (let j = 0; j < attr_rs.length; j++) { + wheels[j].selected = attr_rs[j] + let idx = this.getselectedIdx(wheels[j]) + display.push(wheels[j].data[idx].display) + } + if (isInput) { + item.value = display + } else { + item.innerText = display + } + } + if (isInput) { + item.setAttribute('readonly', 'readonly') + item.setAttribute('unselectable', 'on') + } + item.addEventListener( + 'click', + () => { + let target = item, + wheelsCopy = JSON.parse(JSON.stringify(wheels)), + attr_rs = target.getAttribute('data-value') + target.isInput = isInput + if (isInput) { + target.blur() + } + if (attr_rs) { + let attr_rs1 = attr_rs.split(',') + for (let j = 0; j < attr_rs1.length; j++) { + wheelsCopy[j].selected = attr_rs1[j] + } + this.init(wheelsCopy, target, isInput) + } else { + this.init(wheels, target, isInput) + } + }, + false + ) + } + } + + public addZero(num: number): number { + return num < 10 ? num : num + } + + public opt: opt = { + container: 'body', + scrollType: '3d', + background: 'light', + showLabel: true, //显示label + labelType: 'symbol', //symbol符号 text文字 split分割(需date和time同时存在) + display: 'bottom', + headResult: false, + date: true, + time: true, + beginYear: new Date().getFullYear() - 100, + endYear: new Date().getFullYear() + 100, + startDate: '', + save: function () {}, + cancel: function () {}, + } + public d = new Date() + public year = this.d.getFullYear() + public month = this.d.getMonth() + 1 + public day = this.d.getDate() + public hour = this.d.getHours() + public minute = this.d.getMinutes() + // 年份阈值 + public beginYear: number = this.opt.beginYear + public endYear: number = this.opt.endYear + // 年月日时分数据数组 + public yearData: itemdate[] = [] + public monthData: itemdate[] = [] + public dayData: itemdate[] = [] + public hourData: itemdate[] = [] + public minuteData: itemdate[] = [] + public lastValue!: string + public wheels: pickerwheel[] = [ + { + infinite: false, + selected: this.addZero(this.year), + label: '-', + data: this.yearData, + }, + { + infinite: true, + selected: this.addZero(this.month), + label: '-', + data: this.monthData, + }, + { + infinite: true, + selected: this.addZero(this.day), + label: '', + data: this.dayData, + }, + { + infinite: true, + selected: this.addZero(this.hour), + label: ':', + data: this.hourData, + }, + { + infinite: true, + selected: this.addZero(this.minute), + label: '', + data: this.minuteData, + }, + ] + // 年、月、日、时、分,数据初始化初始化 + public initDateInfo() { + // 年 + for (let i = this.beginYear; i <= this.endYear; i++) { + this.yearData.push({value: this.addZero(i), display: this.addZero(i)}) + } + // 月 + for (let i = 1; i <= 12; i++) { + this.monthData.push({value: this.addZero(i), display: this.addZero(i)}) + } + // 日 + for (let i = 1; i <= 31; i++) { + this.dayData.push({value: this.addZero(i), display: this.addZero(i)}) + } + // 时 + for (let i = 0; i <= 23; i++) { + this.hourData.push({value: this.addZero(i), display: this.addZero(i)}) + } + // 分 + for (let i = 0; i <= 59; i++) { + this.minuteData.push({value: this.addZero(i), display: this.addZero(i)}) + } + // 判断显示日期/时间 + if (!this.opt.date) { + this.wheels.splice(0, 3) + } + if (!this.opt.time) { + this.wheels.splice(3, 5) + this.wheels[2].label = ' ' + } + // Label控制 + if (!this.opt.showLabel) { + for (let i = 0; i < this.wheels!.length; i++) { + delete this.wheels[i].label + } + } else { + if (this.opt.labelType == 'text') { + let text = ['年', '月', '日', '时', '分', '秒'] + for (let i = 0; i < this.wheels.length; i++) { + this.wheels[i].label = text[i] + } + } + if (this.opt.labelType == 'split' && this.opt.date && this.opt.time) { + for (let i = 0; i < this.wheels.length; i++) { + delete this.wheels[i].label + } + this.wheels[2].label = '
    ' + } + } + } + + // 判断闰年 + public isLeepTear(year: number) { + if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { + return true + } else { + return false + } + } + + // 判断大小月 + public bigSmallMonth(dayObj:any, year: number, month: String) { + let smallMonth = + month == '04' || month == '06' || month == '09' || month == '11' + dayObj.appendItem([ + {value: '29', display: '29'}, + {value: '30', display: '30'}, + {value: '31', display: '31'}, + ]) + if (smallMonth) { + dayObj.removeItem(['31']) + } else if (month == '02') { + if (this.isLeepTear(year)) { + dayObj.removeItem(['30', '31']) + } else { + dayObj.removeItem(['29', '30', '31']) + } + } + } + + //获取结果 + public getLastVal(result:any) { + if (result.length == 5) { + this.lastValue = + result[0].display + + '-' + + result[1].display + + '-' + + result[2].display + + ' ' + + result[3].display + + ':' + + result[4].display + } else if (result.length == 3) { + this.lastValue = + result[0].display + '-' + result[1].display + '-' + result[2].display + } else { + this.lastValue = result[0].display + ':' + result[1].display + } + if (this.opt.headResult) { + let title = this.shadowRoot!.querySelector( + '.p-select-title' + ) as HTMLElement + title.innerText = this.lastValue + } + } + + public initTimePicker(el: string, opt: any) { + this.initDateInfo() + const _this = this + this.clickTarget = _this.shadowRoot!.querySelectorAll( + el + ) as NodeListOf + this.option = extend(this.option, opt) + for (let i = 0; i < this.clickTarget.length; i++) { + let item = this.clickTarget[i], + wheels = this.option.wheels, + isInput = item.localName == 'input' || item.localName == 'textarea', + attr_rs = item.getAttribute('data-value') + if (attr_rs) { + attr_rs = attr_rs.split(',') + let display = [] + for (let j = 0; j < attr_rs.length; j++) { + wheels[j].selected = attr_rs[j] + let idx = this.getselectedIdx(wheels[j]) + display.push(wheels[j].data[idx].display) + } + if (isInput) { + item.value = display + } else { + item.innerText = display + } + } + if (isInput) { + item.setAttribute('readonly', 'readonly') + item.setAttribute('unselectable', 'on') + } + item.addEventListener( + 'click', + () => { + let target = item, + wheelsCopy = JSON.parse(JSON.stringify(wheels)), + attr_rs = target.getAttribute('data-value') + target.isInput = isInput + if (isInput) { + target.blur() + } + if (attr_rs) { + let attr_rs1 = attr_rs.split(',') + for (let j = 0; j < attr_rs1.length; j++) { + wheelsCopy[j].selected = attr_rs1[j] + } + this.init(wheelsCopy, target, isInput) + } else { + this.init(wheels, target, isInput) + } + }, + false + ) + } + console.log(this.wheels) + } + + @query('.inp') _input: any + + firstUpdated() { + let test = '.' + (this._input as HTMLElement).classList[1] + switch (test) { + case '.js-picker': + return this.initPicker(test, { + container: '.screen', + wheels: [ + { + infinite: true, + // selected: 3, + data: [ + {value: 0, display: '选项一'}, + {value: 1, display: '选项二'}, + {value: 2, display: '选项三'}, + {value: 3, display: '选项四'}, + {value: 4, display: '选项五'}, + {value: 5, display: '选项六'}, + {value: 6, display: '选项七'}, + ], + }, + ], + }) + case '.js-time': { + return this.initTimePicker(test, { + wheels: this.wheels, + scrollType: this.opt.scrollType, + background: this.opt.background, + display: this.opt.display, + headTitle: this.opt.headResult ? 1 : '', + container: '.screen', + init: (rs:any) => { + if (this.opt.date) { + var year = rs.result[0].value + var month = rs.result[1].value + this.bigSmallMonth(rs.scrollEvt[2], year, month) + } + this.getLastVal(rs.result) + }, + getResult: (rs:any) => { + var n1 = this.opt.date && (rs.scrollIdx == 0 || rs.scrollIdx == 1) + ;(this.year = rs.result[0].value), (this.month = rs.result[1].value) + if (n1) { + this.bigSmallMonth(rs.scrollEvt[2], this.year, (this.month.toString())) + } + this.getLastVal(rs.result) + }, + save: (rs:any, target:any) => { + if (target.isInput) { + target.value = this.lastValue + } else { + target.innerText = this.lastValue + } + + this.opt.save(this.lastValue, target) + }, + cancel: () => { + this.opt.cancel() + }, + }) + } + } + } + + public getBase(): HTMLTemplateResult { + return html` +
    +
    Picker
    + +
    + ` + } + + public getDatePicker(): HTMLTemplateResult { + return html` +
    +
    DatePicker
    + +
    + ` + } + + public render() { + switch (this.type) { + case 'base': + return this.getBase() + case 'datepicker': + return this.getDatePicker() + default: + console.error('unhanled 【star-button】 type') + return nothing + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'star-pickerbase': PickerBase + } +} diff --git a/src/components/picker/timepicker.css.ts b/src/components/picker/timepicker.css.ts deleted file mode 100644 index 15d4f99..0000000 --- a/src/components/picker/timepicker.css.ts +++ /dev/null @@ -1,156 +0,0 @@ -import {css, CSSResult} from 'lit' - -export const timepickerStyles: CSSResult = css` - :host { - display: block; - } - * { - margin: 0; - padding: 0; - } - .btn { - height: 32px; - padding: 0 15px; - text-align: center; - font-size: 14px; - line-height: 32px; - color: #1890ff; - border: none; - background: #fff; - border-radius: 2px; - cursor: pointer; - } - .mask { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 999; - background: rgba(0, 0, 0, 0.6); - animation: fadeIn 0.3s forwards; - } - .slide-box { - position: fixed; - left: 0; - right: 0; - bottom: 30%; - padding: 15px; - border-radius: 20px; - background: #fff; - user-select: none; - text-align: center; - } - .fade-in { - animation: fadeIn 0.3s forwards; - } - @keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } - } - .fade-out { - animation: fadeOut 0.3s forwards; - } - @keyframes fadeOut { - from { - opacity: 10; - } - to { - opacity: 0; - } - } - .slide-up { - animation: slideUp 0.3s forwards; - } - @keyframes slideUp { - from { - transform: translate3d(0, 100%, 0); - } - to { - transform: translate3d(0, 0, 0); - } - } - - .slide-down { - animation: slideDown 0.3s forwards; - } - @keyframes slideDown { - from { - transform: translate3d(0, 0, 0); - } - to { - transform: translate3d(0, 100%, 0); - } - } - h4 { - height: 24px; - margin-bottom: 16px; - font-size: 16px; - line-height: 24px; - text-align: center; - } - .picker-group { - display: flex; - } - .picker-column { - position: relative; - flex: 1; - height: 200px; - margin: 0 auto; - overflow: hidden; - touch-action: none; - } - .picker-column::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - z-index: 1; - height: 79px; - border-bottom: 1px solid #ebebeb; - background: linear-gradient( - to bottom, - rgba(255, 255, 255, 0.9), - rgba(255, 255, 255, 0.6) - ); - } - .picker-column::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - right: 0; - z-index: 1; - height: 79px; - border-top: 1px solid #ebebeb; - background: linear-gradient( - to bottom, - rgba(255, 255, 255, 0.6), - rgba(255, 255, 255, 0.9) - ); - } - li { - list-style: none; - font-size: 14px; - line-height: 40px; - text-align: center; - } - .picker_label { - margin: 15px auto 0; - } - .btn-cancel { - display: block; - margin: 15px auto 0; - float: left - } - .btn-sure { - display: block; - margin: 15px auto 0; - float: right; - } -` diff --git a/src/components/picker/timepicker.ts b/src/components/picker/timepicker.ts deleted file mode 100644 index 292954e..0000000 --- a/src/components/picker/timepicker.ts +++ /dev/null @@ -1,250 +0,0 @@ -import {LitElement, CSSResultArray, html} from 'lit' -import {customElement} from 'lit/decorators.js' -import {timepickerStyles} from './timepicker.css' - -export class Picker { - public options: any - public isPointerdown: boolean - public itemHeight: number - public maxY: number - public minY: number - public lastY: number - public diffY: number - public translateY: number - public friction: number - public distanceY: number - public result: any - constructor(options: any) { - this.options = Object.assign({}, options) - this.isPointerdown = false - this.itemHeight = 40 // 列表项高度 - this.maxY = this.itemHeight * 2 - this.minY = this.itemHeight * (3 - this.options.list.length) - this.lastY = 0 - this.diffY = 0 - this.translateY = 0 // 当前位置 - this.friction = 0.95 // 摩擦系数 - this.distanceY = 0 // 滑动距离 - this.result = this.options.list[0] - this.render() - this.bindEventListener() - } - render() { - let html = '' - for (const item of this.options.list) { - html += '
  • ' + item + '
  • ' - } - this.options.pickerContent.innerHTML = html - this.options.pickerContent.style.transform = - 'translate3d(0px, ' + this.maxY + 'px, 0px)' - } - handlePointerdown(e: PointerEvent) { - // 如果是鼠标点击,只响应左键 - if (e.pointerType === 'mouse' && e.button !== 0) { - return - } - this.options.pickerColumn.setPointerCapture(e.pointerId) - this.isPointerdown = true - this.lastY = e.clientY - this.diffY = 0 - this.distanceY = 0 - this.getTransform() - this.options.pickerContent.style.transform = - 'translate3d(0px, ' + this.translateY + 'px, 0px)' - this.options.pickerContent.style.transition = 'none' - } - handlePointermove(e: PointerEvent) { - if (this.isPointerdown) { - this.diffY = e.clientY - this.lastY - this.translateY += this.diffY - this.lastY = e.clientY - this.options.pickerContent.style.transform = - 'translate3d(0px, ' + this.translateY + 'px, 0px)' - } - } - handlePointerup() { - if (this.isPointerdown) { - this.isPointerdown = false - this.getTranslateY() - // 滑动距离与时长成正比且最短时长为300ms - const duration = Math.max(Math.abs(this.distanceY) * 1.5, 300) - this.options.pickerContent.style.transition = - 'transform ' + duration + 'ms ease' - this.options.pickerContent.style.transform = - 'translate3d(0px, ' + this.translateY + 'px, 0px)' - } - } - handlePointercancel() { - if (this.isPointerdown) { - this.isPointerdown = false - } - } - bindEventListener() { - this.handlePointerdown = this.handlePointerdown.bind(this) - this.handlePointermove = this.handlePointermove.bind(this) - this.handlePointerup = this.handlePointerup.bind(this) - this.handlePointercancel = this.handlePointercancel.bind(this) - this.options.pickerColumn.addEventListener( - 'pointerdown', - this.handlePointerdown - ) - this.options.pickerColumn.addEventListener( - 'pointermove', - this.handlePointermove - ) - this.options.pickerColumn.addEventListener( - 'pointerup', - this.handlePointerup - ) - this.options.pickerColumn.addEventListener( - 'pointercancel', - this.handlePointercancel - ) - } - getTransform() { - const transform = window - .getComputedStyle(this.options.pickerContent) - .getPropertyValue('transform') - this.translateY = parseFloat(transform.split(',')[5]) - } - getTranslateY() { - let speed = this.diffY - while (Math.abs(speed) > 1) { - speed *= this.friction - this.distanceY += speed - } - // 边界判断 - let y = this.translateY + this.distanceY - if (y > this.maxY) { - this.translateY = this.maxY - this.distanceY = this.maxY - this.translateY - } else if (y < this.minY) { - this.translateY = this.minY - this.distanceY = this.minY - this.translateY - } else { - this.translateY = y - } - // 计算停止位置使其为itemHeight的整数倍 - let i = Math.round(this.translateY / this.itemHeight) - this.translateY = i * this.itemHeight - this.result = this.options.list[2 - this.translateY / this.itemHeight] - } -} - -@customElement('star-timepicker') -export class TimePicker extends LitElement { - public static override get styles(): CSSResultArray { - return [timepickerStyles] - } - - public openState:number = 0 - - // test - protected firstUpdated() { - const btnOpen = this.shadowRoot!.querySelector('.btn-open') as HTMLElement - const btnSure = this.shadowRoot!.querySelector('.btn-sure') as HTMLElement - const btnCancel = this.shadowRoot!.querySelector( - '.btn-cancel' - ) as HTMLElement - const mask = this.shadowRoot!.querySelector('.mask') as HTMLElement - const slide = this.shadowRoot!.querySelector('.slide-box') as HTMLElement - if(this.openState==1){ - - } - btnOpen.addEventListener('click', function () { - mask.hidden = false - mask.classList.add('fade-in') - slide.classList.add('slide-up') - }, true) - // 点击非选择器区域关闭选择器 - // mask.addEventListener('click', function (e) { - // let elm = e.target as HTMLElement - // if (elm.className.includes('mask')) { - // mask.classList.remove('fade-in') - // mask.classList.add('fade-out') - // slide.classList.remove('slide-up') - // slide.classList.add('slide-down') - // } - // }) - btnCancel.addEventListener('click', function (e) { - let elm = e.target as HTMLElement - if (elm.className.includes('btn-cancel')) { - mask.classList.remove('fade-in') - mask.classList.add('fade-out') - slide.classList.remove('slide-up') - slide.classList.add('slide-down') - } - }, true) - mask.addEventListener('animationend', function (e) { - let elm = e.target as HTMLElement - if (elm.className.includes('fade-out')) { - mask.hidden = true - mask.classList.remove('fade-out') - slide.classList.remove('slide-down') - } - }, true) - btnSure.addEventListener('click', function (e) { - var a = new Date() - alert(hourPicker.result + ' : ' + minutePicker.result + a) - e.preventDefault() - }, true) - // 调用方式 - function createList(start: number, end: number) { - const list = [] - for (let i = start; i < end; i++) { - list[i] = i < 10 ? '0' + i : '' + i - } - return list - } - const hours = createList(0, 24), - minutes = createList(0, 60) - const pickerColumns = this.shadowRoot!.querySelectorAll('.picker-column') - const pickerContents = this.shadowRoot!.querySelectorAll('.picker-content') - const hourPicker = new Picker({ - pickerColumn: pickerColumns[0], - pickerContent: pickerContents[0], - list: hours, - }) - const minutePicker = new Picker({ - pickerColumn: pickerColumns[1], - pickerContent: pickerContents[1], - list: minutes, - }) - } - - render() { - return html` - - - ` - } -} - -declare global { - interface HTMLElementTagNameMap { - 'star-timepicker': TimePicker - } -} diff --git a/src/index.ts b/src/index.ts index 7b7eb9e..96fc603 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,7 +26,7 @@ import './components/pattern-view/pattern-view' import './components/overlay/active-overlay' import './components/battery/battery' import './components/battery-square/battery-square' -import './components/picker/timepicker' +import './components/picker/datepicker' @customElement('settings-app') export class SettingsApp extends LitElement { @query('star-animate-section#root') private rootSection!: StarAnimateSection diff --git a/src/test/panels/picker/picker.ts b/src/test/panels/picker/picker.ts index 8fb52f9..439580c 100644 --- a/src/test/panels/picker/picker.ts +++ b/src/test/panels/picker/picker.ts @@ -1,7 +1,7 @@ import {html, LitElement, CSSResultArray} from 'lit' import {customElement} from 'lit/decorators.js' import {sharedPickerStyles} from '../shared-picker-styles' -import '../../../components/picker/timepicker' +import '../../../components/picker/datepicker' @customElement('panel-picker') export class PanelPicker extends LitElement { @@ -72,8 +72,11 @@ export class PanelPicker extends LitElement { + + ` From 905f7f31345e9f687027b94da4ecdf155f52a647 Mon Sep 17 00:00:00 2001 From: yajun Date: Thu, 20 Oct 2022 15:08:46 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E6=9C=88=E5=88=A4=E6=96=AD=E6=9D=A1=E4=BB=B6=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/picker/datepicker.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/picker/datepicker.ts b/src/components/picker/datepicker.ts index 691d8fa..92722d6 100644 --- a/src/components/picker/datepicker.ts +++ b/src/components/picker/datepicker.ts @@ -3,7 +3,6 @@ import { CSSResultArray, html, HTMLTemplateResult, - TemplateResult, nothing, } from 'lit' import {customElement, property, query} from 'lit/decorators.js' @@ -70,7 +69,7 @@ export interface options { startDate?: '' } -// 时间选择器选项——此处后续优化部分 +// 时间选择器选项——此处为后续优化部分 export interface opt { container: string scrollType: string @@ -90,7 +89,7 @@ export interface opt { export type itemdate = { value: number - display: number + display: string } // 定义滚轮内容类型 @@ -915,8 +914,8 @@ export class PickerBase extends LitElement { } } - public addZero(num: number): number { - return num < 10 ? num : num + public addZero(num: number){ + return num < 10 ? '0' + num : String(num) } public opt: opt = { @@ -987,23 +986,23 @@ export class PickerBase extends LitElement { public initDateInfo() { // 年 for (let i = this.beginYear; i <= this.endYear; i++) { - this.yearData.push({value: this.addZero(i), display: this.addZero(i)}) + this.yearData.push({value: i, display: this.addZero(i)}) } // 月 for (let i = 1; i <= 12; i++) { - this.monthData.push({value: this.addZero(i), display: this.addZero(i)}) + this.monthData.push({value: i, display: this.addZero(i)}) } // 日 for (let i = 1; i <= 31; i++) { - this.dayData.push({value: this.addZero(i), display: this.addZero(i)}) + this.dayData.push({value: i, display: this.addZero(i)}) } // 时 for (let i = 0; i <= 23; i++) { - this.hourData.push({value: this.addZero(i), display: this.addZero(i)}) + this.hourData.push({value: i, display: this.addZero(i)}) } // 分 for (let i = 0; i <= 59; i++) { - this.minuteData.push({value: this.addZero(i), display: this.addZero(i)}) + this.minuteData.push({value: i, display: this.addZero(i)}) } // 判断显示日期/时间 if (!this.opt.date) { @@ -1044,9 +1043,9 @@ export class PickerBase extends LitElement { } // 判断大小月 - public bigSmallMonth(dayObj:any, year: number, month: String) { + public bigSmallMonth(dayObj:any, year: number, month: number) { let smallMonth = - month == '04' || month == '06' || month == '09' || month == '11' + month == 4 || month == 6 || month == 9 || month == 11 dayObj.appendItem([ {value: '29', display: '29'}, {value: '30', display: '30'}, @@ -1054,7 +1053,7 @@ export class PickerBase extends LitElement { ]) if (smallMonth) { dayObj.removeItem(['31']) - } else if (month == '02') { + } else if (month == 2) { if (this.isLeepTear(year)) { dayObj.removeItem(['30', '31']) } else { From 432e860d283e28e6e422eb6ebd24f48a8e96e382 Mon Sep 17 00:00:00 2001 From: yajun Date: Thu, 20 Oct 2022 16:30:08 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=80=BC=E7=B1=BB=E5=9E=8B=E5=8F=8A=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=B1=9E=E6=80=A7=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/picker/datepicker.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/picker/datepicker.ts b/src/components/picker/datepicker.ts index 92722d6..edcbd01 100644 --- a/src/components/picker/datepicker.ts +++ b/src/components/picker/datepicker.ts @@ -105,7 +105,7 @@ export type pickerwheel = { export type Result = { value: number - display: number + display: string dataIndex?: number } @@ -953,31 +953,31 @@ export class PickerBase extends LitElement { public wheels: pickerwheel[] = [ { infinite: false, - selected: this.addZero(this.year), + selected: this.year, label: '-', data: this.yearData, }, { infinite: true, - selected: this.addZero(this.month), + selected: this.month, label: '-', data: this.monthData, }, { infinite: true, - selected: this.addZero(this.day), + selected: this.day, label: '', data: this.dayData, }, { infinite: true, - selected: this.addZero(this.hour), + selected: this.hour, label: ':', data: this.hourData, }, { infinite: true, - selected: this.addZero(this.minute), + selected: this.minute, label: '', data: this.minuteData, }, @@ -1189,7 +1189,7 @@ export class PickerBase extends LitElement { var n1 = this.opt.date && (rs.scrollIdx == 0 || rs.scrollIdx == 1) ;(this.year = rs.result[0].value), (this.month = rs.result[1].value) if (n1) { - this.bigSmallMonth(rs.scrollEvt[2], this.year, (this.month.toString())) + this.bigSmallMonth(rs.scrollEvt[2], this.year, this.month) } this.getLastVal(rs.result) },