无法使用`window.scrollY`或`window.pageYOffset`获取滚动位置

时间:2019-07-17 07:11:30

标签: javascript reactjs

问题

我需要获取滚动位置,以便可以根据其切换工具提示位置。

这是我的工具提示的外观:

tooltip

但是当我向下滚动时,我希望它向下切换,但是现在并没有发生想要的事情:向上切换

解决问题的方法

我尝试使用window.scrollYwindow.pageYOffset来获取滚动位置,但是无论我滚动多少,它都将其记录为0

可能的解决方案

我尝试提及this question 但是删除height: 100%属性对我不起作用。

代码

import React, { Component } from 'react'
import ReactMarkdown from 'react-markdown'
import styled from 'styled-components'

import glossary from '../Documentation/glossary'

class Tooltip extends Component {
  state = {
    hover: false,
    timeout: null,
    width: 400,
    margin: -70,
    pointMargin: -15
  }

  tooltipWidthEval = () => {
    const markdownBody = document.getElementsByClassName('markdown-body')[0]
    const maxWidth = markdownBody.offsetLeft + markdownBody.clientWidth
    const container = document.getElementsByClassName('tooltip-container')[0]
    const tooltipWidth = container.offsetLeft + this.state.width
    if (tooltipWidth > maxWidth) {
      this.setState({
        margin: -340,
        pointMargin: 260
      })
    } else {
      this.setState({
        margin: -70,
        pointMargin: -15
      })
    }
  }

  hoverIn = () => {
    console.log(window.scrollY)
    if (this.state.interval) {
      clearTimeout(this.state.interval)
      this.setState(
        {
          interval: null,
          hover: true
        },
        this.tooltipWidthEval
      )
    } else {
      this.setState(
        {
          hover: true
        },
        this.tooltipWidthEval
      )
    }
  }

  hoverOut = () => {
    this.setState({
      interval: setTimeout(() => {
        this.setState({
          hover: false
        })
      }, 100)
    })
  }

  render() {
    const { text } = this.props
    let header = ''
    let description = ''
    glossary.contents.forEach(glossaryItem => {
      if (glossaryItem.match.includes(text)) {
        header = glossaryItem.name
        description = glossaryItem.desc
      }
    })
    return (
      <>
        <HighlightedText
          onMouseOver={this.hoverIn}
          onMouseLeave={this.hoverOut}
        >
          {text}
        </HighlightedText>
        {this.state.hover && (
          <TooltipContainer
            className="tooltip-container"
            onMouseOver={this.hoverIn}
            onMouseLeave={this.hoverOut}
          >
            <TooltipText
              margin={this.state.margin}
              width={this.state.width}
              pointMargin={this.state.pointMargin}
            >
              <div className="header">{header}</div>
              <ReactMarkdown source={description} />
            </TooltipText>
          </TooltipContainer>
        )}
      </>
    )
  }
}

const HighlightedText = styled.span`
  border-bottom: 1px black dotted;
`

const TooltipContainer = styled.div`
  position: absolute;
  display: inline-block;
  z-index: 300000000;
  background-color: white;
`

const TooltipText = styled.div`
  padding: 8px 10px;
  border: 1px solid #d1d5da;
  border-radius: 3px;
  background-color: white;
  position: absolute;
  z-index: 1;
  bottom: 90%;
  margin-left: ${props => props.margin || -70}px;
  width: ${props => props.width || 400}px;

  &:after,
  &:before {
    content: '';
    position: absolute;
    top: 100%;
    border-style: solid;
    margin-left: ${props => props.pointMargin || -15}px;
  }

  &:after {
    left: 10%;
    border-width: 10px;
    border-color: white transparent transparent transparent;
  }
  &:before {
    left: 10%;
    border-width: 11px;
    border-color: #d1d5da transparent transparent transparent;
  }

  .header {
    font-size: 1.3em;
    font-weight: bold;
  }
`

export default Tooltip

P.S。我想如果仅由于项目不使用jQuery就使用javascript解决了问题,

1 个答案:

答案 0 :(得分:2)

如果我做对了,实际上是在滚动容器(例如div或类似的东西),而不是页面本身。在这种情况下,您可以使用scrollTop来获得滚动偏移,如前面的注释中所述。

但是,您需要为要滚动的元素获取该属性( window.scrollTop)。因此,如果您的内容在div中,则需要从该元素获取scrollTop属性。这是一个工作示例,其中我从元素获取滚动位置:

const container = document.getElementById('container');

container.addEventListener('scroll', () => {
	console.log(container.scrollTop);
});
#container {
  height: 300px;
  border: 1px solid lightgray;
  overflow-y: auto;
  padding: 10px;
}
#content {
  background: linear-gradient(0deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%);
  height: 1000px;
}
<div id="container">
  <div id="content">
  
  </div>
</div>