DEV Community

方帅
方帅

Posted on

VTable table component, how to listen for mouse hover events on the elements?

Question Description

When customizing cell content using customLayout, including Text and Image, I would like to have some custom logic when hovering over the Image. Currently, the mouse-enter event for the cell cannot distinguish between specific targets.

Image description

For DOM elements in JavaScript, the mouseenter event is triggered only once when the mouse pointer enters (moves over) the element. So is there an event like mouseenter_cell to monitor specified content in custom cells?

Solution

You can bind the mouseenter and mouseleave events to the image dom of the custom layout 'customLayout'.

Image description

Code example

You can paste it into the official editor to test:
https://visactor.io/vtable/demo/custom-render/custom-cell-layout-jsx

const VGroup = VTable.VGroup;
const VText = VTable.VText;
const VImage = VTable.VImage;
const VTag = VTable.VTag;

const option = {
  container: document.getElementById('container'),
  columns: [
    {
      field: 'bloggerId',
      title: 'bloggerId'
    },
    {
      field: 'bloggerName',
      title: 'bloggerName',
      width: 330,
      customLayout: args => {
        const { table, row, col, rect } = args;
        const { height, width } = rect || table.getCellRect(col, row);
        const record = table.getRecordByRowCol(col, row);
        // const jsx = jsx;
        const container = (
          <VGroup
            attribute={{
              id: 'container',
              width,
              height,
              display: 'flex',
              flexWrap: 'nowrap',
              justifyContent: 'flex-start',
              alignContent: 'center'
            }}
          >
            <VGroup
              id="container-right"
              attribute={{
                id: 'container-right',
                width: width - 60,
                height,
                fill: 'yellow',
                opacity: 0.1,
                display: 'flex',
                flexWrap: 'nowrap',
                flexDirection: 'column',
                justifyContent: 'space-around',
                alignItems: 'center'
              }}
            >
              <VGroup
                attribute={{
                  id: 'container-right-top',
                  fill: 'red',
                  opacity: 0.1,
                  width: width - 60,
                  height: height / 2,
                  display: 'flex',
                  flexWrap: 'wrap',
                  justifyContent: 'flex-start',
                  alignItems: 'center'
                }}
              >
                <VText
                  attribute={{
                    id: 'bloggerName',
                    text: record.bloggerName,
                    fontSize: 13,
                    fontFamily: 'sans-serif',
                    fill: 'black',
                    textAlign: 'left',
                    textBaseline: 'top',
                    boundsPadding: [0, 0, 0, 10]
                  }}
                ></VText>
                <VImage
                  attribute={{
                    id: 'location-icon',
                    width: 15,
                    height: 15,
                    image:
                      '<svg t="1684484908497" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2429" width="200" height="200"><path d="M512 512a136.533333 136.533333 0 1 1 136.533333-136.533333 136.533333 136.533333 0 0 1-136.533333 136.533333z m0-219.272533a81.92 81.92 0 1 0 81.92 81.92 81.92 81.92 0 0 0-81.92-81.92z" fill="#0073FF" p-id="2430"></path><path d="M512 831.214933a27.306667 27.306667 0 0 1-19.2512-8.055466l-214.493867-214.357334a330.5472 330.5472 0 1 1 467.490134 0l-214.357334 214.357334a27.306667 27.306667 0 0 1-19.387733 8.055466z m0-732.091733a275.933867 275.933867 0 0 0-195.106133 471.04L512 765.269333l195.106133-195.106133A275.933867 275.933867 0 0 0 512 99.1232z" fill="#0073FF" p-id="2431"></path><path d="M514.321067 979.490133c-147.456 0-306.107733-37.000533-306.107734-118.3744 0-45.602133 51.746133-81.92 145.681067-102.4a27.306667 27.306667 0 1 1 11.605333 53.384534c-78.370133 17.066667-102.673067 41.915733-102.673066 49.015466 0 18.432 88.064 63.761067 251.4944 63.761067s251.4944-45.192533 251.4944-63.761067c0-7.3728-25.258667-32.768-106.496-49.834666a27.306667 27.306667 0 1 1 11.195733-53.384534c96.6656 20.343467 150.186667 56.9344 150.186667 103.2192-0.273067 80.964267-158.9248 118.3744-306.3808 118.3744z" fill="#0073FF" p-id="2432"></path></svg>',
                    boundsPadding: [0, 0, 0, 10],
                    cursor: 'pointer'
                  }}
                  stateProxy={stateName => {
                    if (stateName === 'hover') {
                      return {
                        background: {
                          fill: 'green',
                          cornerRadius: 5,
                          expandX: 1,
                          expandY: 1
                        }
                      };
                    }
                  }}
                  onPointerEnter={event => {
                    event.currentTarget.addState('hover', true, false);
                    event.currentTarget.stage.renderNextFrame();
                  }}
                  onPointerLeave={event => {
                    event.currentTarget.removeState('hover', false);
                    event.currentTarget.stage.renderNextFrame();
                  }}
                ></VImage>
                <VText
                  attribute={{
                    id: 'locationName',
                    text: record.city,
                    fontSize: 11,
                    fontFamily: 'sans-serif',
                    fill: '#6f7070',
                    textAlign: 'left',
                    textBaseline: 'top'
                  }}
                ></VText>
              </VGroup>
            </VGroup>
          </VGroup>
        );

        // decode(container)
        return {
          rootContainer: container,
          renderDefault: false
        };
      }
    },
    {
      field: 'fansCount',
      title: 'fansCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'worksCount',
      title: 'worksCount',
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'viewCount',
      title: 'viewCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'viewCount',
      title: 'viewCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: '',
      title: 'operation',
      width: 100,
      icon: ['favorite', 'message']
    }
  ],
  records: [
    {
      bloggerId: 6,
      bloggerName: 'Virtual anchor bird',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg',
      introduction:
        'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.',
      fansCount: 900,
      worksCount: 12,
      viewCount: 8,
      city: 'Happy City',
      tags: ['music', 'performance', 'variety']
    }
  ],
  defaultRowHeight: 80
};

const instance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option);
window.tableInstance = instance;
Enter fullscreen mode Exit fullscreen mode

documents

demo: https://visactor.io/vtable/demo/custom-render/custom-cell-layout-jsx
Relevant api:https://visactor.io/vtable/option/ListTable-columns-text#customLayout
Tutorial:https://visactor.io/vtable/guide/custom_define/custom_layout
github:https://github.com/VisActor/VTable

Top comments (1)

Collapse
 
raajaryan profile image
Deepak Kumar

Hello everyone,

I hope you're all doing well. I recently launched an open-source project called the Ultimate JavaScript Project, and I'd love your support. Please check it out and give it a star on GitHub: Ultimate JavaScript Project. Your support would mean a lot to me and greatly help in the project's growth.

Thank you!