jQuery - 选择覆盖在图像上的不可见文本,ala GMail PDF 查看器

发布于 2024-10-01 10:41:54 字数 223 浏览 5 评论 0原文

我将不可见的文本叠加在图像之上。是否有 jQuery 插件(或类似插件)允许用户选择图像上的区域(也选择覆盖的文本)并能够复制内容。

现在,我已将每个字符放入其自己的 标记中。问题是当用户选择时,它有时会选择所有覆盖的文本(除非用户使用鼠标非常精确),有时图像本身也会被选中,等等。

类似于 GMail 的 PDF 查看器的解决方案会很好。建议?

I'm overlaying invisible text on top of an image. Is there a jQuery plugin (or similar) that will allow users to select an area on the image (which also selects the overlaid text) and be able to copy the content.

Right now, I have placed each character in its own <span /> tag. Problem is when user selects, it sometimes select all the overlaid text (unless user is extremely precise with his/her mouse), sometimes the image itself becomes selected, etc.

A solution similar to GMail's PDF viewer would be nice. Suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

念三年u 2024-10-08 10:41:54

Google 似乎从 pdf 中知道文件中各种 x,y 文本偏移量的位置。当您选择一堆行时,它会在“文本”所在的图像上放置一组绝对定位的“选择”div(它们具有 highlight-pane 类)。当您选择文本时,它会使用您所选择的内容填充 #selection-content 文本区域,并选择其中的文本(尝试使用 window.getSelection().anchorNode< /code> 在 Chrome 中,例如)。除了这些选择叠加之外,还有一个图像.page-image。我敢打赌他们实际上使用窗口来捕获他们关心的所有鼠标手势(我假设mousedownmouseup)。 (这是一个 pdf 文档示例< /a>)

如果您对元素进行绝对定位,则可以检测 mousedownmousemovemouseup,找出跨度元素 mouse结束(或最接近),并用这两个元素之间的所有内容填充文本区域。如果您只想使用单词粒度,我怀疑有人会抱怨(用跨度包围每个单词,而不是每个字母)。

编辑:昨晚我有点好奇,编写了一个非常天真的版本。它只执行 mousedownmouseup,并且在 IE 中不起作用(我不想调试它:)

在 jsfiddle 上查看。

您可能想要添加的功能:

  1. 检查基于位置的匹配的更好方法;我只是看它是否包含在盒子里。
  2. mousemove 上的动态更新
  3. 基于行而不是基于跨度
  4. 您仍然可以通过背景颜色进行选择,但根据元素的排列方式,它可能看起来不太好。还需要支持透明度。

Google seems to know from a pdf where the various x,y text offsets are in the file. When you select a bunch of lines, it places a set of absolutely positioned "selection" divs over the image where the "text" is (they have class highlight-pane). When you select text, it fills in a #selection-content textarea with the contents of what you have selected, and selects the text in it (try using window.getSelection().anchorNode in Chrome, e.g.). Besides those selection overlays, there is just an image .page-image. I bet they actually use window to capture all the mouse gestures they care about (I assume mousedown and mouseup). (Here's an example pdf document)

If you're absolute-positioning the elements, you could detect mousedown, mousemove and mouseup, figure out the span elements mouse is over (or nearest to), and fill in a textarea with the contents of all content between those two elements. If you want to just use word-granularity, I doubt anyone would complain (surround each word with a span, rather than each letter).

Edit: I got kinda curious last night and coded up a really naive version. It only does mousedown and mouseup, and it doesn't work in IE (I don't feel like debugging it :)

Check it out on jsfiddle.

Features you might want to add:

  1. Some better way of checking for position-based matches; I just do whether it's included in the box.
  2. Dynamic updating on mousemove
  3. Line-based rather than span-based
  4. You could still do selecting by background color, but depending on how your elements are arranged it might not look very good. Also would need to support transparency.
此刻的回忆 2024-10-08 10:41:54

这是一个使用我对上一个问题的回答的简单示例: http:// /www.jsfiddle.net/yijian/83​​W7X/2/embedded/result

var selected = [];

function drawSelection(){
    if(selected.length){
        selected.sort(function(a, b){
            if(a.sourceIndex){
                return a.sourceIndex - b.sourceIndex;
            } else if(a.compareDocumentPosition){
                if(a.compareDocumentPosition(b) == Node.DOCUMENT_POSITION_PRECEDING){
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        var range = rangy.createRange(),
            sel = rangy.getSelection();

        range.setStart(selected[0].children[0], 0);
        range.setEnd(selected[selected.length - 1].children[0], 1);
        sel.setSingleRange(range);
    }
}

$('ul').selectable({
    delay: 100,
    selecting: function(event, ui) {
        if(ui.selecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.selecting, selected) === -1) {
            selected.push(ui.selecting);
            drawSelection();
        }
    },
    unselecting: function(event, ui){
        if(ui.unselecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.unselecting, selected) > -1){
            selected.splice($.inArray(ui.unselecting, selected), 1);
            drawSelection();
        }
    }
});

它将 jQuery UI 的 Selectable 与 Tim Down 优秀的 Rangy 库混合在一起,创建与您要求的类似的东西。我认为。你问的不是很清楚。

该代码保留当前选定的 li 元素的数组。代码的第二部分添加了相关的事件处理程序和选项。每次选择或取消选择元素时都会调用drawSelection函数。该函数首先按 DOM 中的位置对所有元素进行排序,然后继续从第一个选定的 li 到最后一个选定的内容进行选择。

代码,例如 theazureshadow 的< /a> 只是概念验证,因为我正在抽象实际上应该是为相当重的 Rangy 库选择 li 的简单任务。它的性能也不是很好,需要进行一些重构。

Here's a simple example using my answer to your previous question: http://www.jsfiddle.net/yijiang/83W7X/2/embedded/result

var selected = [];

function drawSelection(){
    if(selected.length){
        selected.sort(function(a, b){
            if(a.sourceIndex){
                return a.sourceIndex - b.sourceIndex;
            } else if(a.compareDocumentPosition){
                if(a.compareDocumentPosition(b) == Node.DOCUMENT_POSITION_PRECEDING){
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        var range = rangy.createRange(),
            sel = rangy.getSelection();

        range.setStart(selected[0].children[0], 0);
        range.setEnd(selected[selected.length - 1].children[0], 1);
        sel.setSingleRange(range);
    }
}

$('ul').selectable({
    delay: 100,
    selecting: function(event, ui) {
        if(ui.selecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.selecting, selected) === -1) {
            selected.push(ui.selecting);
            drawSelection();
        }
    },
    unselecting: function(event, ui){
        if(ui.unselecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.unselecting, selected) > -1){
            selected.splice($.inArray(ui.unselecting, selected), 1);
            drawSelection();
        }
    }
});

It mixes jQuery UI's Selectable with Tim Down's excellent Rangy library to create something similar to what you asked for. I think. What you asked for wasn't exactly clear.

The code keeps an array of currently selected li elements. The second part of the code adds in the relevant event handlers and options. The drawSelection function is called every time an element is selected or deselected. The function first sorts all elements by their position in the DOM, then proceeds to draw a selection from the first selected li to the last.

The code, like theazureshadow's, is proof-of-concept only, since I'm abstracting what really should be the simple task of selecting the lis to the rather heavy Rangy library. It also does not perform very well and could do with some refactoring.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文