精华内容
下载资源
问答
  • 周视图日历计算方法

    千次阅读 2017-10-22 00:18:11
    周视图日历计算

    代码

    function WeekLayoutCalendar() {
        //当前周
        var cells = document.getElementById('currWeek').getElementsByTagName('div');
        //周长度
        var clen = cells.length;
        console.log(clen);
        //当前周的第一天
        var currentFirstDate;
        //new两个当天
        var myDate = new Date();
        var etDate = new Date();
        //当前天的日期的日
        today = myDate.getDate();
        console.log(today);
        var formatDate = function (date) {
            var year = date.getFullYear() + '年';
            var month = (date.getMonth() + 1) + '月';
            var day = date.getDate();
            return day;
        };
        var addDate = function (date, n) {
            date.setDate(date.getDate() + n);
            return date;
        };
        var setDate = function (date) {
            var week = date.getDay();
            date = addDate(date, week * -1);
            currentFirstDate = new Date(date);
            var currM = currentFirstDate.getMonth();
            var todayM = myDate.getMonth();
            document.getElementById('currYM').innerHTML = currentFirstDate.getFullYear() + '-' + (1 + currentFirstDate.getMonth() < 10 ? '0' + parseInt(1 + currentFirstDate.getMonth()) : 1 + currentFirstDate.getMonth());
            myDate.setDate(myDate.getDate() - myDate.getDay());
            for (var i = 0; i < clen; i++) {
                cells[i].innerHTML = formatDate(i == 0 ? date : addDate(date, 1));
                if (cells[i].innerHTML == today && currentFirstDate.getMonth() == myDate.getMonth() && currentFirstDate.getFullYear() == myDate.getFullYear()) {
                    cells[i].className = 'curr-day';
                    document.getElementById('currYM').innerHTML = myDate.getFullYear() + '-' + (1 + etDate.getMonth() < 10 ? '0' + parseInt(1 + etDate.getMonth()) : 1 + etDate.getMonth());
                }
                else {
                    cells[i].className = '';
                }
            }
        };
    
        document.getElementsByClassName('button-prev')[0].onclick = function () {
            setDate(addDate(currentFirstDate, -7));
        };
        document.getElementsByClassName('button-next')[0].onclick = function () {
            setDate(addDate(currentFirstDate, 7));
        };
        setDate(new Date());
    };
    
    展开全文
  • 周视图日历+日程Demo

    2015-05-07 15:43:35
    简单Android周视图日历 + 日程Demo,代码简单,日程用横向ListView(HorizontalListView)列表形式,用于参考
  • 本文给大家介绍了Javascript开发二维周视图日历的相关内容,即之前实现了一个月视图日历,我们今天来实现一个二维周视图的日历。 以下进行分析其中的关键部分。 结构准备 不同之处在于其在日历的基础上还有一个分类...
  • 您可以在下载2014年至2025年之间每年的“周日历” PDF。 为什么 我开始寻找一个星期日历,在其中可以使用一些“过时的”技巧:只是写下今天需要完成的工作,并跟踪任务的进度。 我以为这对圣诞节的某些亲戚来说可能...
  • 即之前实现了一个月视图日历,我们今天来实现一个二维周视图的日历。 以下进行分析其中的关键部分。 结构准备 不同之处在于其在日历的基础上还有一个分类轴,用于展示不同的类目,主要用于一周内的日程安排、会议...
        

    即之前实现了一个月视图日历,我们今天来实现一个二维周视图的日历。

    以下进行分析其中的关键部分。

    结构准备

    不同之处在于其在日历的基础上还有一个分类轴,用于展示不同的类目,主要用于一周内的日程安排、会议安排等。

    二维则和之前单独的有所不同,二维日历再切换日期时不用全部重新渲染,分类是不用变的,仅仅改变显示的日期即可。

    而且由于是二维的,插入的内容必定是同时属于一个分类和一个时间段的,内容肯定是可以跨越时间(即日期轴)的,因此不能直接将插入的内容像开始的日历一样直接放置在日历的格子中。而要进行单独的处理。

    另外,只要分类不变,日期和分类构成的网格是不用重绘的。

    考虑到以上情况,插入内容的和网格是需要分开来的,我将现成的日历弄成一下3D效果示意:

    即插入内容的层是单独放置在时间和分类构成的网格上方的。

    基于以上分析,先构建如下基本结构:

    <div class="ep-weekcalendar border">
        <!-- 头部 -->
        <div class="ep-weekcalendar-header">
            <div class="ep-weekcalendar-header-left"></div>
            <div class="ep-weekcalendar-header-center">
                <span class="ep-weekcalendar-header-btn ep-weekcalendar-header-btn-prev"></span>
                <span class="ep-weekcalendar-title">2017年12月04日 - 10日</span>
                <span class="ep-weekcalendar-header-btn ep-weekcalendar-header-btn-next"></span>
            </div>
            <div class="ep-weekcalendar-header-right"></div>
        </div>
        <!-- 主体 -->
        <div class="ep-weekcalendar-body">
            <!-- 分类区域 -->
            <div class="ep-weekcalendar-category-area">
                <div class="ep-weekcalendar-category-header">
                    <span class="ep-weekcalendar-category-title">车辆</span>
                </div>
                <ul class="ep-weekcalendar-category-list">
                </ul>
            </div>
            <!-- 内容区域 -->
            <div class="ep-weekcalendar-time-area">
                <!-- 每周日期渲染区域。切换日期时重新绘制内容 -->
                <div class="ep-weekcalendar-weeks"></div>
                <div class="ep-weekcalendar-main">
                    <!-- 分类和内容构建的网格区域,仅在分类改变时进行调整 -->
                    <div class="ep-weekcalendar-grid"> </div>
                    <!-- 可插入任意内容的区域,日期切换时清空,根据使用需求插入内容 -->
                    <div class="ep-weekcalendar-content"></div>
                </div>
            </div>
        </div>
        <!-- 底部 -->
        <div class="ep-weekcalendar-body"></div>
    </div>

    结构如上,实现代码就不用展示了。

    绘制实现

    初始好了必要的结构,我们接着进行日历的绘制工作。

    分类绘制

    首先要处理的是分类,周视图中,一周的天数是固定的,确定好分类才能绘制出主体部分的网格。

    对于分类,暂时考虑如下必要数据格式:

    {
        id: 'cate-1', // 分类ID
        name: '法拉利', // 分类名称
        content: '苏E00000' // 分类的具体描述
    }

    实现如下:

    {
        // 设置分类数据
        setCategory: function (data) {
            if (!(data instanceof Array)) {
                this.throwError('分类数据必须是一个数组');
                return;
            }
            this._categoryData = data;
    
            // 绘制分类
            this._renderCatagories();
            // 绘制其他需要改变的部分
            this._renderChanged();
        },
        // 左侧分类渲染
        _renderCatagories: function () {
            this._categoryListEl.innerHTML = '';
    
            var i = 0,
                data = this._categoryData,
                node = document.createElement('li'),
                cataEl;
            node.className = 'ep-weekcalendar-category';
    
            // 用行作为下标记录当前分类id集合
            this._categoryIndexs = [];
            // id为键记录索引
            this._categoryReocrds = {};
    
            while (i < data.length) {
                this._categoryIndexs.push(data[i].id);
                this._categoryReocrds[data[i].id] = i;
                cataEl = node.cloneNode(true);
                this._rendercategory(data[i], cataEl);
                i++;
            }
            // 分类重绘必定重绘网格和内容
            this._renderGrid();
            this._rednerContent();
        },
        _rendercategory: function (cate, cateEl) {
            cateEl.setAttribute('data-cateid', cate.id);
    
            var titleEl = document.createElement('span'),
                contentEl = document.createElement('span');
            titleEl.className = 'title';
            contentEl.className = 'content';
    
            titleEl.innerHTML = cate.name;
            contentEl.innerHTML = cate.content;
            cateEl.appendChild(titleEl);
            cateEl.appendChild(contentEl);
    
            this.fire('categoryRender', {
                categoryEl: cateEl,
                titleEl: titleEl,
                contentEl: contentEl
            });
    
            this._categoryListEl.appendChild(cateEl);
    
            this.fire('agterCategoryRender', {
                categoryEl: cateEl,
                titleEl: titleEl,
                contentEl: contentEl
            });
        }
    }

    上面通过设置分类数据 setCategory 作为入口,调用绘制分类方法,其中还调用了 _renderChanged 此方法用于重新绘制日历的可变部分,如标题、日期和其中的内容,会在之后进行介绍。

    日期绘制

    上面已经准备好了分类轴,还需要绘制出日期轴,对于周视图而言,一周的实现就非常简单了,根据一周的开始日期,依次渲染7天即可。 注意在绘制过程中提供日期的必要信息给相应事件,一遍使用者能够在事件中进行个性化处理。

    {
        // 渲染日历的星期
        _renderWeeks: function () {
            this._weeksEl.innerHTML = '';
            var i = 0,
                currDate = this._startDate.clone(),
                node = document.createElement('div'),
                week;
            node.className = 'ep-weekcalendar-week';
    
            // 单元格列作为下标记录日期
            this._dateRecords = [];
    
            while (i++ < 7) {
                // 更新记录日期
                this._dateRecords.push(currDate.clone());
    
                week = node.cloneNode(true);
                this._renderWeek(currDate, week);
                currDate.add(1, 'day');
            }
    
            // 切换日期 需要重绘内容区域
            this._rednerContent();
        },
    
        _renderWeek: function (date, node) {
            var dateText = date.format('YYYY-MM-DD'),
                day = date.isoWeekday();
    
            if (day > 5) {
                node.className += ' weekend';
            }
            if (date.isSame(this.today, 'day')) {
                node.className += ' today';
            }
    
            node.setAttribute('data-date', dateText);
            node.setAttribute('date-isoweekday', day);
    
            var ev = this.fire('dateRender', {
                // 当前完整日期
                date: dateText,
                // iso星期
                isoWeekday: day,
                // 显示的文本
                dateText: '周' + this._WEEKSNAME[day - 1] + ' ' + date.format('MM-DD'),
                // classname
                dateCls: node.className,
                // 日历el
                el: this.el,
                // 当前el
                dateEl: node
            });
    
            // 处理事件的修改
            node.innerHTML = ev.dateText;
            node.className = ev.dateCls;
    
            this._weeksEl.appendChild(node);
    
            this.fire('afterDateRender', {
                // 当前完整日期
                date: dateText,
                // iso星期
                isoWeekday: day,
                // 显示的文本
                dateText: node.innerHTML,
                // classname
                dateCls: node.className,
                // 日历el
                el: this.el,
                // 当前el
                dateEl: node
            });
        }
    }

    网格和内容

    上面已经准备好了二维视图中的两个轴,接着进行网格和内容层的绘制即可。

    网格

    此处以分类为Y方向(行),日期为X方向(列)来进行绘制:

    {
        // 右侧网格
        _renderGrid: function () {
            this._gridEl.innerHTML = '';
    
            var rowNode = document.createElement('div'),
                itemNode = document.createElement('span'),
                rowsNum = this._categoryData.length,
                i = 0,
                j = 0,
                row, item;
    
            rowNode.className = 'ep-weekcalendar-grid-row';
            itemNode.className = 'ep-weekcalendar-grid-item';
    
            while (i < rowsNum) {
                row = rowNode.cloneNode();
                row.setAttribute('data-i', i);
                j = 0;
    
                while (j < 7) {
                    item = itemNode.cloneNode();
                    // 周末标识
                    if (this.dayStartFromSunday) {
                        if (j === 0 || j === 6) {
                            item.className += ' weekend';
                        }
                    } else {
                        if (j > 4) {
                            item.className += ' weekend';
                        }
                    }
    
                    item.setAttribute('data-i', i);
                    item.setAttribute('data-j', j);
                    row.appendChild(item);
    
                    j++;
                }
    
                this._gridEl.appendChild(row);
    
                i++;
            }
    
            rowNode = itemNode = row = item = null;
        }
    }

    内容

    理论上来说,二维要支持跨行、跨列两种情况,即内容区域应该为一整块元素。但是结合到实际情况,跨时间的需求普遍存在(一个东西在一段时间内被连续使用)。跨分类并没有多大的实际意义,本来就要分开以分类来管理,再跨分类,又变得复杂了。而且即使一定要实现一段时间内同时在使用多个东西,也是可以直接实现的(分类A在XX时间段内被使用,B在XX时间段内被使用,只是此时XX正好相同而已)。

    因此此处仅处理跨时间情况,可将内容按行即分类进行绘制,这样在插入内容部件时,可以简化很多计算。

    {
        // 右侧内容
        _rednerContent: function () {
            this._contentEl.innerHTML = '';
    
            var i = 0,
                node = document.createElement('div'),
                row;
    
            node.className = 'ep-weekcalendar-content-row';
    
            while (i < this._categoryData.length) {
                row = node.cloneNode();
                row.setAttribute('data-i', i);
    
                this._contentEl.appendChild(row);
                ++i;
            }
    
            row = node = null;
    
        },
    
        // 日期切换时清空内容
        _clearContent: function () {
            var rows = this._contentEl.childNodes,
                i = 0;
    
            while (i < rows.length) {
                rows[i].innerHTML && (rows[i].innerHTML = '');
                ++i;
            }
    
            // 部件数据清空
            this._widgetData = {};
        }
    }

    如果一定要实现跨行跨列的情况,直接将内容绘制成一整块元素即可,但是在点击事件和插入内容部件时,需要同时计算对应的分类和日期时间。

    难点实现

    内容部件插入

    我们实现这个二维周视图日历的主要目的就是要支持插入任意的内容,上面已经准备好了插入内容的dom元素,这里要做的就是将数据绘制成dom放置在合适的位置。

    考虑必要的内容部件数据结构如下:

    {
        id: '数据标识',
        categoryId: '所属分类标识',
        title: '名称',
        content: '内容',
        start: '开始日期时间'
        end: '结束日期时间'
        bgColor: '展示的背景色'
    }

    由于上面在内容区域是直接按照分类作为绘制的,因此拿到数据后,对应的分类就已经存在了。重点要根据指定的开始和结束时间计算出开始和结束位置。

    考虑如下:

    • 考虑响应式,位置计算按照百分比计算
    • 一周的总时间是固定的,开始日期时间和这周开始日期时间的差额占总时间的百分比即开始位置的百分比
    • 结束日期时间和开始时间的差额占总时间的百分比即为结束时间距离最左侧的百分比
    • 注意处理开始和结束时间溢出本周的情况

    因此关于位置计算可以用如下代码处理:

    {
        // 日期时间分隔符 默认为空 对应格式为 '2017-11-11 20:00'
        // 对于'2017-11-11T20:00' 这样的格式务必指定正确的日期和时间之间的分隔符T
        _dateTimeSplit:' ',
        // 一周分钟数
        _WEEKMINUTES: 7 * 24 * 60,
        // 一周秒数
        _WEEKSECONDS: 7 * 24 * 3600,
        // 一天的分钟数秒数
        _DAYMINUTES: 24 * 60,
        _DAYSCONDS: 24 * 3600,
        // 计算位置的精度 取值second 或 minute
        posUnit: 'second',
        // 计算指定日期的分钟或秒数
        _getNumByUnits: function (dateStr) {
            var temp = dateStr.split(this._dateTimeSplit),
                date = temp[0];
    
            // 处理左侧溢出
            if (this._startDate.isAfter(date, 'day')) {
                // 指定日期在开始日期之前
                return 0;
            }
            // 右侧溢出直接算作第7天即可
            var times = (temp[1] || '').split(':'),
                days = (function (startDate) {
                    var currDate = startDate.clone(),
                        i = 0,
                        d = moment(date, 'YYYY-MM-DD');
                    while (i < 7) {
                        if (currDate.isSame(d, 'day')) {
                            return i;
                        } else {
                            currDate.add(1, 'day');
                            ++i;
                        }
                    }
    
                    console && console.error && console.error('计算天数时出错!');
                    return i;
                }(this._startDate)),
                hours = parseInt(times[0], 10) || 0,
                minutes = parseInt(times[1], 10) || 0,
                seconds = parseInt(times[2], 10) || 0,
                // 对应分钟数
                result = days * this._DAYMINUTES + hours * 60 + minutes;
    
            return this.posUnit == 'minute' ? result : (result * 60 + seconds);
        },
        // 计算日期时间的百分比位置
        _getPos: function (dateStr) {
            var p = this._getNumByUnits(dateStr) / (this.posUnit == 'minute' ? this._WEEKMINUTES : this._WEEKSECONDS);
    
            return p > 1 ? 1 : p;
        }
    }

    上面就拿到了一个数据所对应的开始位置和结束位置。基本上是已经完成了,但是还需要再处理一个情况:相同分类下的时间冲突问题。

    考虑以如下方式进行:

    1. 没添加一个就记录下其数据
    2. 新增的如果和当前分类下已有的存在时间重叠,则认为冲突。

    实现如下:

    {
        /**
         * 检查是否发生重叠
         *
         * @param {Object} data 当前要加入的数据
         * @returns false 或 和当前部件重叠的元素数组
         */
        _checkOccupied: function (data) {
    
            if (!this._widgetData[data.categoryId]) {
                return false;
            }
    
            var i = 0,
                cate = this._widgetData[data.categoryId],
                len = cate.length,
                result = false,
                occupied = [];
    
            for (; i < len; ++i) {
                // 判断时间是否存在重叠
                if (data.start < cate[i].end && data.end > cate[i].start) {
                    occupied.push(cate[i]);
                    result = true;
                }
            }
    
            return result ? occupied : false;
        }
    }

    完成以上两步就可以往我们的内容区域中插入了

    {
        // 缓存widget数据
        _cacheWidgetData: function (data) {
            if (!this._widgetData[data.categoryId]) {
                this._widgetData[data.categoryId] = [];
            }
            // 记录当前的
            this._widgetData[data.categoryId].push(data);
        },
        // 新增一个小部件
        addWidget: function (data) {
            var row = this._contentEl.childNodes[this._categoryReocrds[data.categoryId]];
    
            if (!row) {
                this.throwError('对应分类不存在,添加失败');
                return false;
            }
    
            // 先查找是否含有
            var $aim = jQuery('.ep-weekcalendar-content-widget[data-id="' + data.id + '"]', row);
    
            if ($aim.length) {
                // 已经存在则不添加
                return $aim[0];
            }
    
            // 创建部件
            var widget = document.createElement('div'),
                title = document.createElement('span'),
                content = document.createElement('p'),
                startPos = this._getPos(data.start),
                endPos = this._getPos(data.end),
                _data = {
                    categoryId: data.categoryId,
                    id: data.id,
                    start: startPos,
                    end: endPos,
                    el: widget,
                    data: data
                };
    
            widget.className = 'ep-weekcalendar-content-widget';
            title.className = 'ep-weekcalendar-content-widget-title';
            content.className = 'ep-weekcalendar-content-widget-content';
    
            widget.appendChild(title);
            widget.appendChild(content);
    
            // 通过绝对定位,指定其left和right来拉开宽度的方式来处理响应式
            // 可以通过样式设置一个最小宽度,来避免时间段过小时其中文本无法显示的问题
            widget.style.left = startPos * 100 + '%';
            widget.style.right = (1 - endPos) * 100 + '%';
            data.bgColor && (widget.style.backgroundColor = data.bgColor);
    
            data.id && widget.setAttribute('data-id', data.id);
            widget.setAttribute('data-start', data.start);
            widget.setAttribute('data-end', data.end);
    
            title.innerHTML = data.title;
            data.content && (content.innerHTML = data.content);
            widget.title = data.title;
    
            // 检查是否发生重叠
            var isoccupied = this._checkOccupied(_data);
    
            if (isoccupied) {
                // 触发重叠事件
                var occupiedEv = this.fire('widgetoccupied', {
                    occupiedWidgets: (function () {
                        var arr = [];
                        for (var i = 0, l = isoccupied.length; i < l; ++i) {
                            arr.push(isoccupied[i].el);
                        }
                        return arr;
                    })(),
                    currWidget: widget,
                    widgetData: data
                });
    
                // 取消后续执行
                if (occupiedEv.cancel) {
                    return false;
                }
            }
    
            // 缓存数据
            this._cacheWidgetData(_data);
    
            var addEv = this.fire('widgetAdd', {
                widgetId: data.id,
                categoryId: data.categoryId,
                start: data.start,
                end: data.end,
                startPos: startPos,
                endPos: endPos,
                widgetEl: widget
            });
    
            if (addEv.cancel) {
                return false;
            }
    
            row.appendChild(widget);
    
            this.fire('afterWidgetAdd', {
                widgetId: data.id,
                categoryId: data.categoryId,
                start: data.start,
                end: data.end,
                startPos: startPos,
                endPos: endPos,
                widgetEl: widget
            });
    
            return widget;
        },
    }

    点击事件和范围选择

    此控件不仅用于结果展示,还要可用于点击进行添加,需要处理其点击事件,但是由于要展示内容,内容是覆盖在分类和日期构成的网格之上的,用户的点击是点击不到网格元素的,必须要根据点击的位置进行计算来获取所点击的日期和所在分类。

    同时,由于展示的部件都是时间范围的,因此点击返回某天和某个分类是不够的,还需要能够支持鼠标按下拖动再松开,来直接选的一段时间。

    考虑到以上需求,点击事件不能直接使用 click 来实现,考虑使用 mousedownmouseup 来处理点击事件,同时需要在 mousemove 中实时给出用户响应。

    {
        _initEvent: function () {
            var me = this;
            // 点击的行索引
            var row,
                // 开始列索引
                columnStart,
                // 结束列索引
                columnEnd,
                // 是否在按下、移动、松开的click中
                isDurringClick = false,
                // 是否移动过 用于处理按下没有移动直接松开的过程
                isMoveing = false,
                $columns,
                // 网格左侧宽度
                gridLeft,
                // 每列的宽度
                columnWidth
            jQuery(this.el)
                // 按下鼠标 记录分类和开始列
                .on('mousedown.weekcalendar', '.ep-weekcalendar-content-row', function (e) {
                    isDurringClick = true;
                    gridLeft = jQuery(me._gridEl).offset().left;
                    columnWidth = jQuery(me._gridEl).width() / 7;
                    jQuery(me._gridEl).find('.ep-weekcalendar-grid-item').removeClass(me._selectedCls);
    
                    row = this.getAttribute('data-i');
                    $columns = jQuery(me._gridEl).find('.ep-weekcalendar-grid-row').eq(row).children();
    
                    columnStart = (e.pageX - gridLeft) / columnWidth >> 0;
    
                });
            // 移动和松开 松开鼠标 记录结束列 触发点击事件 
            // 不能直接绑定在日期容器上 否则鼠标移出日历后,松开鼠标,实际点击已经结束,但是日历上处理不到。
            jQuery('body')
                // 点击移动过程中 实时响应选中状态
                .on('mousemove.weekcalendar', function (e) {
                    if (!isDurringClick) {
                        return;
                    }
                    isMoveing = true;
    
                    // 当前列索引
                    var currColumn;
    
                    // mousemoveTimer = setTimeout(function () {
                    currColumn = (e.pageX - gridLeft) / columnWidth >> 0;
    
                    // 修正溢出
                    currColumn = currColumn > 6 ? 6 : currColumn;
                    currColumn = currColumn < 0 ? 0 : currColumn;
    
                    $columns.removeClass(me._selectedCls);
    
                    // 起止依次选中
                    var start = Math.min(columnStart, currColumn),
                        end = Math.max(columnStart, currColumn);
    
                    do {
                        $columns.eq(start).addClass(me._selectedCls);
                    } while (++start <= end);
                })
                // 鼠标松开
                .on('mouseup.weekcalendar', function (e) {
                    if (!isDurringClick) {
                        return;
                    }
    
                    var startIndex = -1,
                        endIndex = -1;
    
                    columnEnd = (e.pageX - gridLeft) / columnWidth >> 0;
    
                    columnEnd = columnEnd > 6 ? 6 : columnEnd;
    
                    // 没有移动过时
                    if (!isMoveing) {
                        startIndex = endIndex = columnEnd;
                        // 直接down up 没有move的过程则只会有一个选中的,直接以结束的作为处理即可
                        $columns.eq(columnEnd).addClass(me._selectedCls)
                            .siblings().removeClass(me._selectedCls);
                    } else {
                        startIndex = Math.min(columnStart, columnEnd);
                        endIndex = Math.max(columnStart, columnEnd);
                    }
    
                    // 触发点击事件
                    me.fire('cellClick', {
                        // 分类id 
                        categoryId: me._categoryIndexs[row],
                        // 时间1
                        startDate: me._dateRecords[startIndex].format('YYYY-MM-DD'),
                        // 日期2
                        endDate: me._dateRecords[endIndex].format('YYYY-MM-DD'),
                        // 行索引
                        rowIndex: row,
                        // 列范围
                        columnIndexs: (function (i, j) {
                            var arr = [];
                            while (i <= j) {
                                arr.push(i++);
                            }
                            return arr;
                        }(startIndex, endIndex))
                    });
    
                    row = columnStart = columnEnd = isMoveing = isDurringClick = false;
                });
        }
    }

    此过程要注意的问题是:mousedown 必须绑定在日历上,而 mouseupmousemove 则不能绑定在日历上,具体原因已经写在上面代码注释中了。

    另外需要注意,由于范围点击选择使用了 mousedownmouseup 来模拟,那么日历内容区域中插入的数据部件的点击事件也要用 mousedownmouseup 来模拟,因为 mouseup 触发比 click 早,如果使用 click ,会导致先触发日历上的日期点击或日期范围点击。

    使用

    此日历实现基于一个控件基类扩展而来,其必要功能仅为一套事件机制,可参考实现一套自定义事件机制

    实测一下效果吧:

    <div id="week-calendar" style="width:100%;height:80vh"></div>
    <script>
    var calendar = epctrl.init('WeekCalendar', {
        el: '#week-calendar',
        categoryTitle: '车辆',
        category: [{
            id: 'cate-1',
            name: '法拉利',
            content: '苏E00000'
        }, {
            id: 'cate-2',
            name: 'Lamborghini',
            content: '苏E00001'
        }, {
            id: 'cate-3',
            name: '捷豹',
            content: '苏E00002'
        }, {
            id: 'cate-4',
            name: '宾利',
            content: '苏E00003'
        }, {
            id: 'cate-5',
            name: 'SSC',
            content: '苏E00004'
        }],
        events: {
            // 日期变化时触发
            dateChanged: function (e) {
                var data = {
                    start: e.startDate,
                    end: e.endDate,
                };
    
                // 获取数据并逐个添加到日历上
                getData(data).done(function (data) {
                    $.each(data, function (i, item) {
                        calendar.addWidget(item);
                    });
                });
            },
            // 部件重叠时触发
            widgetOccupied: function (e) {
                // 冲突时禁止继续添加
                console.error(e.widgetData.categoryId + '分类下id为' + e.widgetData.id + '的部件和现有部件有重叠,取消添加');
                e.cancel = true;
            }
        }
    });
    calendar.on('dateClick', function (e) {
        alert(JSON.stringify({
            '开始时间': e.startDate,
            '结束时间': e.endDate,
            '分类id': e.categoryId,
            '行索引': e.rowIndex,
            '列索引范围': e.columnIndexs
        }, 0, 4));
    });
    </script>

    本文首发我的博客:https://blog.cdswyda.com/post/2017121022

    展开全文
  • 周视图日历 日视图日历 自定义样式 水平和垂直滚动 无限水平滚动 在xml预览窗口中实时预览自定义样式 谁使用 使用图书馆? 只是或。 用法 将库导入到您的项目中。 通过Maven抢 < groupId>...
  • react-h5-calendar git 库地址 造一个小轮子,核心文件不...支持周视图,周日历 支持月视图,月日历 支持左右滑动切换月份 支持上下滑动切换日历视图 支持日历上打点标记 基于dayjs处理日历逻辑 使用教程 yarn add react

    react-h5-calendar

    git 库地址

    造一个小轮子,核心文件不到三百行,一款基于react 的移动端 , mobile, h5 日历展示组件

    demo

    在这里插入图片描述

    扫描二维码直接查看demo

    在这里插入图片描述

    直接打开浏览器查看 https://kokiy.github.io/react-h5-calendar/

    react 移动端日历组件

    1. 支持周视图,周日历
    2. 支持月视图,月日历
    3. 支持左右滑动切换月份
    4. 支持上下滑动切换日历视图
    5. 支持日历上打点标记
    6. 基于dayjs处理日历逻辑

    使用教程

    yarn add react-h5-calendar

    import { MobileCalendar } from 'react-h5-calendar'
    export default class Demo extends Component {
     render() {
       return (
         <MobileCalendar
           onDateClick={date => this.setState({ currentDate: date.format('YYYY-MM-DD') })}
           currentDate={'2020-12-12'}
         />
       )
     }
    }
    

    参数设置

    参数 说明 默认值
    currentDate 当前选择的日期 比如2020-12-12 ‘当天’
    showType 展示类型支持monthweek month
    transitionDuration 切换日期的动画过渡时间 0.3
    onDateClick 日期点击回调 () => {}
    onTouchStart 滑动开始回调 () => {}
    onTouchMove 滑动过程中回调 () => {}
    onTouchEnd 滑动结束回调 () => {}
    markType 标记类型 支持dotcircle dot
    markDates 需要标记的日期数组 []

    markDates 参数说明

    const markDates = [
    { color: '#459', date: '2020-12-12', markType: 'circle' },
    { color: '#a8f', markType: 'dot', date: '2020-12-23' },
    { color: '#a5f', markType: 'circle', date: '2020-12-22' },
    { date: '2021-1-22' },
    ]
    
    1. 单个日期不传markType 默认取传入的Marktype
    2. 单个日期不传color 默认是#f00
    展开全文
  • Android仿MIUI周视图月视图切换日历

    千次下载 热门讨论 2015-05-20 09:40:57
    仿MIUI日历,只是单纯的日历部分,可周视图月视图切换,用于参考
  • 可以在月视图与周视图之间切换的calendar控件
  • android 日历周视图

    2015-12-24 11:12:01
    可以滑动,仿ios的日历周视图,优化bug
  • 自定义Android日历周视图,ViewPager 无限滑动
  • 上下滑动可以在周视图和月视图之前切换,左右滑动可以切换日期。
  • android 仿小米日历周视图左右滑动,月视图左右滑动,周视图月视图无缝切换;

    android 仿小米日历,周视图左右滑动,月视图左右滑动,周视图月视图无缝切换;

    http://download.csdn.net/detail/chen352602412/9556162



    插播广告:OTCBTC 是目前最流畅、最靠谱、最好用的场外交易平台,支持支付宝、微信、银行卡支付购买BTC、ETH、EOS、USDT、QTUM、ZEC、GXS、BCH 等数字币。现在注册,即可领取比特币红包! https://otcbtc.com/referrals/904529093

    展开全文
  • Android日历周视图,可以添加事件,viewpager无限滑动
  • WRCalendarView一个iOS的天日历周视图
  • 一个可切换周视图和月视图的vue日历组件,并且可以显示日程安排及事件标注
  • 支持设置默认视图,默认周日历或者月日历 支持状态固定,下拉刷新等 支持设置一开始的是周一还是周日 可设置日期区间,默认区间从1901-01-01到2099-12-31 支持农历,节气、法定节假日等 支持添加指示点及设置...
  • Android 自定义日历周视图

    千次阅读 2017-04-03 11:01:37
    简版如下: 知识点:viewpager无限滑动、日期的计算、自定义day(每个单元格...自定义 day视图  主要绘制显示的天和小蓝点 package cn.edu.sxu.www.customercalendar; import android.content.Context; import a
  • 仿ios的日历周视图.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • 请问日历控件fullcanlendar周视图左侧时间段 能自定义么,比方说开始时间6:00到18:00 但是我不想展示中间的11:00到12:00 这个有人自定过么
  • 页面一中的日历切换周视图和月视图效果无效,that.calendar.switchView('month').then(() => { console.log('我进来了') }); 该方法还可以调用,希望您能帮忙找找问题,...
  • NCalendar特点:3种常见日历交互方式,MIUI系统日历:miui9、miui10、华为emui,miui9和钉钉日历类似,华为emui和365日历类似月滑动切换,月不选中支持多选,设置多选的数量支持设置默认视图,默认周日历或者月...
  • dhtmlxScheduler是一个基于Web的类似于Outlook的日历日程控件。它完全由javascript/js/css...dhtmlxScheduler带有多种视图,包括天视图,周视图,月视图,年视图和日程表视图。用户可以通过拖拽的方式来改变日历的时...
  • 可以在月视图与周视图之间切换的calendar控件.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • Android日历周视图 可添加事件标记

    千次阅读 2017-04-03 13:31:59
    package cn.edu.sxu.www.customercalendar; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils;...import and

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 270
精华内容 108
关键字:

周视图日历