laurens94 / vue-timeline-chart

A timeline component for Vue3
https://laurens94.github.io/vue-timeline-chart/
MIT License
36 stars 3 forks source link

Overlapping items are hidden #19

Open pappfer opened 1 week ago

pappfer commented 1 week ago

I'm using the range item type. When I have items in the same group with same start and end settings, I can only see one of those items, the others' --_width property gets set to 0 so they are in the DOM, but invisible.

Is it possible to - instead of hiding those - apply an offset, for example transform: translateY(-10px); or something like this so I can see all items?

laurens94 commented 3 days ago

Hi! Thanks for opening this issue.

The overlapping items are indeed something that would be nice to have fixed. However, the --_width property being set to 0 is unintended behaviour and I cannot seem to reproduce it. Would you mind sharing the code?

When implementing this feature, the row height should also dynamically adjust based on the amount of overlapping items within the viewport or within the whole dataset so that row heights don't jump during scrolling. Having an option that determines this behaviour would be nice.

pappfer commented 2 days ago

I attached 2 screenshots about current behavior. On the first you can see I have 5 items visible in the chart, while on the second you can see that there are 7 <div> DOM elements in that line. It's because 2 other items have exactly the same time range as the last 2 items displayed on the chart. On the 2nd screenshot you can see that it sets the --_width to 0px that's why it's invisible.

2024-11-20 15_14_35 2024-11-20 15_16_01

I really needed to solve this so temporarily I wrote an ugly function that makes the hidden items to display with an offset. This is the code and you can see a screenshot about the result below:

function applyOffsets() {
    console.log('Offsets applying...')
    setTimeout(() => {
        const items = document.querySelectorAll(".item.range");

        requestAnimationFrame(() => {
            let offset = 0;

            items.forEach((item, index) => {
                const currentWidth = window.getComputedStyle(item).getPropertyValue("--_width");

                if (currentWidth === "0px") {
                    const prevItem = index > 0 ? items[index - 1] : null;

                    if (prevItem) {
                        const prevLeft = window.getComputedStyle(prevItem).getPropertyValue("--_left");
                        const prevWidth = window.getComputedStyle(prevItem).getPropertyValue("--_width");

                        item.style.setProperty("--_left", prevLeft);
                        item.style.setProperty("--_width", prevWidth);

                        // Apply vertical offset for overlapping items
                        offset++;
                        item.style.transform = `translateY(-${offset * 0.5}rem)`;
                        item.setAttribute("data-offset-applied", "true");
                    }
                } else {
                    // Reset offset if the item does not overlap
                    offset = 0;
                    item.removeAttribute("data-offset-applied");
                }
            });
        });
    }, 100);
}

2024-11-20 15_20_28

And finally, this is part of the data I'm providing to the chart:

{
    "groups": [
        {
            "id": "group_2",
            "label": "Airlines"
        }
    ],
    "items": [
        {
            "id": "item_26_preparation_group_2",
            "dbId": 366,
            "field": "preparation",
            "label": "POBL",
            "title": "Preparation of brand list",
            "tooltip": "Preparation of brand list (17\/11\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1699574400000,
            "end": 1700179200000,
            "originalEnd": 1700179200000,
            "className": "item-type-preparation",
            "cssVariables": {
                "--item-background": "#FFC107"
            }
        },
        {
            "id": "item_26_sent_to_gatekeeper_group_2",
            "dbId": 366,
            "field": "sent_to_gatekeeper",
            "label": "BLSTGKAV",
            "title": "Brand list sent to gate keeper and valuations",
            "tooltip": "Brand list sent to gate keeper and valuations (22\/11\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1700179200000,
            "end": 1700611200000,
            "originalEnd": 1700611200000,
            "className": "item-type-sent_to_gatekeeper",
            "cssVariables": {
                "--item-background": "#17A2B8"
            }
        },
        {
            "id": "item_26_brand_list_returned_group_2",
            "dbId": 366,
            "field": "brand_list_returned",
            "label": "BLRRBR",
            "title": "Brand list returned & reviewed by RM",
            "tooltip": "Brand list returned & reviewed by RM (13\/12\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1700611200000,
            "end": 1702425600000,
            "originalEnd": 1702425600000,
            "className": "item-type-brand_list_returned",
            "cssVariables": {
                "--item-background": "#28A745"
            }
        },
        {
            "id": "item_26_brand_list_finalised_group_2",
            "dbId": 366,
            "field": "brand_list_finalised",
            "label": "BLF",
            "title": "Brand list finalised",
            "tooltip": "Brand list finalised (20\/12\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1702425600000,
            "end": 1703030400000,
            "originalEnd": 1703030400000,
            "className": "item-type-brand_list_finalised",
            "cssVariables": {
                "--item-background": "#007BFF"
            }
        },
        {
            "id": "item_26_sent_to_db_team_group_2",
            "dbId": 366,
            "field": "sent_to_db_team",
            "label": "STDT",
            "title": "Sent to DB team",
            "tooltip": "Sent to DB team (20\/12\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1703030400000,
            "end": 1703030400000,
            "originalEnd": 1703030400000,
            "className": "item-type-sent_to_db_team",
            "cssVariables": {
                "--item-background": "#6610f2"
            }
        },
        {
            "id": "item_26_reviewed_by_db_team_group_2",
            "dbId": 366,
            "field": "reviewed_by_db_team",
            "label": "RBDT",
            "title": "Reviewed by DB team",
            "tooltip": "Reviewed by DB team (27\/12\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1703030400000,
            "end": 1703635200000,
            "originalEnd": 1703635200000,
            "className": "item-type-reviewed_by_db_team",
            "cssVariables": {
                "--item-background": "#20C997"
            }
        },
        {
            "id": "item_26_list_confirmed_group_2",
            "dbId": 366,
            "field": "list_confirmed",
            "label": "LCAL",
            "title": "List confirmed and locked",
            "tooltip": "List confirmed and locked (27\/12\/2023)",
            "status": "",
            "group": "group_2",
            "type": "range",
            "start": 1703635200000,
            "end": 1703635200000,
            "originalEnd": 1703635200000,
            "className": "item-type-list_confirmed",
            "cssVariables": {
                "--item-background": "#343A40"
            }
        }
    ],
    "timelineData": {
        "initialViewportStart": 1698969600000,
        "initialViewportEnd": 1727827200000,
        "viewportMin": 1684281600000,
        "viewportMax": 1742860800000
    }
}