The react calendar component drags and drops some logic/elements

Target

In the first half we implement a calendar component that renders a month view of the year. One of the APIs is cellAppend, which can write content to the calendar content area.

 

The code example is as follows:

<Calendar
        cellAppend={(cellData) =>
         判断在某这个日期展示 && (
            <div className="cell-append-demo-outer">
                今天
            </div>
          )
        }
      />

Well, our goal here is to

  • Realize the rendering of a date, such as the 11th to the 20th, and then this date can be dragged.
  • The starting position of this date can be stretched left and right, so that the time period can be increased or decreased
  • Similarly, the end of the date can also be stretched
  • New date: Start dragging in the blank space of each day in the calendar, and a new date can be created in a blank area dragged out.

We only implement the basic situation, because there will be a lot of judgment involved, such as multiple tasks overlapping and how to reorder them.

render time period

This is very simple, the data we render must be an array, similar to:

const eventList = [
  {
    id: 12, // 这段日期的唯一标识id
    startTime: "2018-04-4", // 日期起始
    endTime: "2018-04-15",// 日期结束
    displayName: "日程1",
    userId: 1, // 用户id
  },
  {
    id: 15, // 这段日期的唯一标识id
    startTime: "2018-04-05",
    endTime: "2018-04-06",
    displayName: "日程2",
    userId: 2, // 用户id
  },
];

Well, according to our cellAppend API, we only need to render like this

<Calendar
        cellAppend={(cellData) => {
          eventList.map(event=>{
             计算event.startTime和endTime间隔几天(利用dayjs现成的API)
             然后for循环,遍历这几天 {
                 利用cellData判断是否是for循环的这一天
                 如果是,就渲染出来,渲染的时候需要判断,这是开始,中间还是结束
                 因为UI的展示不一样
             }
             
          })
        }
        }
      />

Well, we can render various time periods according to the above code. Note that because the height of the calendar is limited, for example, if there are 100 tasks on the same day, it will exceed its height. Generally, I look at google calendar, react-big- Calender, outlook calendar, etc. will list this situation as there are xxx tasks, for example, there are 23 tasks, which are folded.

In fact, I think there is no way for this to be folded. Even if it is folded, there will be some difficult situations. For example, I have a date from the 1st to the 4th. It must be folded on the first day because the row There are too many tasks, and there is no need to fold them in 2-4 days. This situation is not easy to see at a glance, because it is folded, but I have seen mainstream calendar implementations, and I can’t solve this problem. So if we do it, we can only do this at most. Let me write the code again.

<Calendar
        cellAppend={(cellData) => {
          eventList.map(event=>{
             计算event.startTime和endTime间隔几天(利用dayjs现成的API)
             然后for循环,遍历这几天 {
                 利用cellData判断是否是for循环的这一天
                 如果是,就渲染出来,渲染的时候需要判断,这是开始,中间还是结束
                + 这里还要判断这个单元格目前的任务数是否超出了,如果超出,就不需要把这个任务展示出来
             }
             
          })
        }
        }
      />

new date

By the way, we use the react-dnd library for dragging and dropping. We will use this library to monitor whether each date cell is in the hover state. For example, I want to create a new task from 1st to 4th , are all blank dates, I mouse down, and then move while down, which is equivalent to a drag event. Drag the mouse from No. 1 to No. 4. At this time, the drag is over, and a box pops up, allowing me to fill in the name of the new task.

This is the interaction of the new date.

So we need to monitor the hover during the drag process, which is actually the dragover event.

Here we need to pay attention to a logic. For example, if I drag and drop from No. 1 to No. 4, there will be a UI change from No. 1 to No. 4. For example, a light blue background indicates that it is being created. I cannot simply write as long as It is light blue where I drag it. It is possible to reach the 4th, and I drag it to the 3rd. At this time, the blue background of the 4th will be canceled.

So we have to change the way of thinking, because we know the date of hover, then we can calculate the distance between the date of hover and the date of the dragging starting point, that is, how many days are separated, then I only need to know how many days to the right the positive number is. It is blue, and the negative number is how many days to the left it becomes blue.

Then in the dragend event, re-render the calendar component. We have written the logic of rendering the date segment above, so a new date is created.

Of course, we can also support clicking on a certain date, creating a new date in the pop-up box, and the click event has been supported by the code in our previous article, so I won’t say much about it.

Drag the date itself

This requires us to add drag events to all rendered date segments, which is probably the case if we use react-dnd


// Cell组件
const [ { }, dragRef ] = useDrag({
    collect: {
        这个cell的数据,比如id,startTime这些
    }
})

<div ref={dragRef}> 日期 </div>

// 日历组件
<Calendar
        cellAppend={(cellData) => {
          eventList.map(event=>{
             return <Cell组件>
             }
             
          })
        }
        }
      />

Well, when dragging, we actually change the startTime and endTime of the current date. At this time, we can re-render our calendar component. Of course, we need a state to indicate that the date is being dragged. When dragEnd, reset this state place.

Of course, this also needs to be monitored by the dragover event, mainly relying on the drag state variable to tell dragover that it is the date of dragging, not the new date.

Drag and stretch the start and end positions of this date

Dates such as a task from the 3rd to the 4th, I drag from the 3rd to the left, which means to extend the task a little bit, which is also a relatively common user demand. How to do this.

In fact, we need to create a transparent element to cover the " Diagnostic Proof Picture " at the top of the date segment, so that we can add a drag event to this element.

The dragging logic is similar to the above, that is, a new state called dragging front, such as DRAG_FORWARD, is needed, and it is listened to on the dragover event.

Guess you like

Origin blog.csdn.net/dageliuqing/article/details/127913673