【问题标题】:How to enable div to appear over the selected text?如何使 div 出现在选定的文本上?
【发布时间】:2018-07-15 21:21:50
【问题描述】:

我正在使用 VueJS 创建一个应用程序,以在用户选择的文本上生成工具提示。我想在用户选择的文本上准确显示工具提示。我正在使用Tippy.js 创建工具提示

代码如下:

const giphy = require('giphy-api')('Here goes the API key');

export default {
  data () {
    return {
      
    }
  },

  mounted() {
    const template = document.querySelector('#template');
    const initialText = template.textContent;
    
    let that = this;

    const tip = tippy('.tip', {
      animation: 'shift-toward',
      arrow: true,
      html: '#template',
      trigger: 'click',
      onShow() {
        
        // `this` inside callbacks refers to the popper element
        const content = this.querySelector('.tippy-content');
        
        if(tip.loading || content.innerHTML !== initialText) 
          return;
        
        tip.loading = true;

        var self = that;
        
        $('#app').mouseup(function() {
          let selection = self.getSelected();

          if (selection != "") {

            giphy.translate(`${selection}`)
            .then(function (response) {
              // Assigning the url from response object to the url
              const url = response.data.images.fixed_width_small.url;
              content.innerHTML = `<img width="100" height="100" src="${url}">`
              tip.loading = false
            })
            .catch(function(error){
              content.innerHTML = 'Loading failed'
              tip.loading = false
            });

          }
        });
      },

      onHidden() {
        const content = this.querySelector('.tippy-content');
        content.innerHTML = initialText;
      }
    })

  },

  methods: {
    // Function to get the selected text
    getSelected() {
      let selectedText = "", selection;
      
      if (window.getSelection) {
        selectedText = "" + window.getSelection();
      } 
      else if ( (selection = document.selection) && selection.type == "Text") {
        selectedText = selection.createRange().text;
      }
      return selectedText;
    }

  }
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
    <div class="tip">
      <h1>Fifa World Cup 2018</h1>
      <h4 style="margin-top:40px;">Winner is France</h4>
      <span style="margin-top:10px;">Runner up is Croatia</span>
    </div>

    <div>
      <div id="template" style="display: none">
        Loading tooltip...
      </div>
    </div>

  </div>

id="template" 的 div 是构成工具提示的 div。到目前为止,我只设法让它出现在文本所在的 div 的中心。如何确保工具提示恰好出现在所选文本上方?有人可以帮我吗?

【问题讨论】:

  • 脚本错误,不起作用。

标签: javascript html css vue.js vuejs2


【解决方案1】:
  1. 在应用上注册mouseup 事件处理程序

  2. 在处理程序中调用window.getSelection().getRangeAt(0).getBoundingClientRect() 以获取文本选择的边界矩形

  3. 将文本选择的边界矩形作为“虚拟元素”传递给tippy,文档:https://atomiks.github.io/tippyjs/ (crtl+f "virtual element")

前 2 步的 vanilla JS 示例:

let p = document.querySelector('p');
let div = document.querySelector('div');

document.documentElement.addEventListener('mouseup', () => {
    console.log(p);
    let selection = getSelection();
    console.log(selection);
    if (!selection.isCollapsed && selection.rangeCount > 0) {
        let range = selection.getRangeAt(0);
        console.log(range);
        let rangeRect = range.getBoundingClientRect();
        console.log(rangeRect);
        console.log(div);
        div.style.top = rangeRect.top+'px';
        div.style.left = rangeRect.left+'px';
        div.style.width = rangeRect.width+'px';
        div.style.height = rangeRect.height+'px';
    } else {
        div.style.top = 0;
        div.style.left = 0;
        div.style.width = 0;
        div.style.height = 0;
    }
});
body {
    padding: 20px;
    position: relative;
}

div {
    border: 2px red solid;
    position: absolute;
    pointer-events: none;
    top: -999px;
    left: -999px;
}

p {
    width: 500px;
}
<div></div>
<h1> try selecting some of the text below </h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>

【讨论】:

  • 你能编辑上面的代码并告诉我怎么做吗?我真的很感激。这样,我就能弄清楚我需要做什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多