javascript - 如何使用滚动条在虚拟 Canvas 上平移?

标签 javascript jquery html canvas

我想创建一个实现虚拟 HTML5 Canvas 的 jQuery 插件,即一个物理上不比它在页面上的外观大(或大不了多少)的 Canvas 。但是要在 Canvas 上显示的内容可能比 Canvas 大很多倍,并且会根据滚动条动态重绘。

您可能会认为这是非常常见的功能,但到目前为止我还无法找到使用 jQuery 插件或其他方式的示例。这与例如SlickGrid 对 Div 起作用,除了这是与 Canvas 一起使用的。我可以想到两种解决方案:

  1. 使用 jQuery UI Slider 将滚动条实现为一个完全独立的元素,并使用其事件来控制 Canvas 重绘。

  2. 做 SlickGrid 为 Div 所做的一切。它似乎使一个 Div 比显示的内容稍大,并且 Hook 滚动事件以动态地向 Div 添加/删除元素。但我看不出它是如何修改滚动条以使其看起来好像 Div 中还有更多当前显示的内容。

你会推荐什么?示例代码将不胜感激。

最佳答案

我深入研究了 SlickGrid 代码并使用了方法 2)(某种程度上)——我的想法是这样的:

/*
    jensk@migselv.com

    Simple virtual CANVAS controlled by a native scrollbar made with two DIVs
    Uses jCanvas by Caleb Evans (http://calebevans.me/projects/jcanvas/index.php)
    Thanks to Michael Leibman of SlickGrid fame for ideas.

    Still need to clean it up (get rid of hardcoded values) and make it a nice, configurable
    jQuery component.

    Currently also redraws the entire canvas on each scroll event. Could be optimized to 
    do real browser scrolling and only redrawing the needed parts.

    Another gotcha is that since it is the zero width DIVs that causes the scroll events,
    mouse wheel, trackpad, touchscreen etc. scrolling over the Canvas will not work - only
    the scrollbar is active. To solve this, one could make the Canvas larger inside a 
    smaller DIV too, catch scroll events from it and perform redrawing and setting the DIV's
    scrollTop accordingly.    
*/

var h = 10000; // virtual canvas height
var vp = 400; // viewport height
var viewport, fakescrolldiv, canvas;

function onScroll() {
    var scrollTop = viewport.scrollTop();
    console.log("onScroll scrollTop=" + scrollTop);


    $("canvas").clearCanvas();

    // Red box top
    $("canvas").drawRect({
        fillStyle: "#F00",
        x: 150,
        y: 20 - scrollTop,
        width: 100,
        height: 100,
        fromCenter: false
    });

    // Green box middle
    $("canvas").drawRect({
        fillStyle: "#0F0",
        x: 150,
        y: 140 - scrollTop,
        width: 100,
        height: 100,
        fromCenter: false
    });

    // Blue box bottom
    $("canvas").drawRect({
        fillStyle: "#00F",
        x: 150,
        y: 260 - scrollTop,
        width: 100,
        height: 100,
        fromCenter: false
    });

    var i = 0;
    for (i = 0; i <= 396; i++) {
        $("canvas").drawLine({
            strokeStyle: "#000",
            strokeWidth: 1,
            x1: 0,
            y1: i,
            x2: (scrollTop + i) % 50,
            y2: i
        });
        if ((scrollTop + i) % 50 === 0) {
            $("canvas").drawText({
                fillStyle: "#729fcf",
                text: (scrollTop + i).toString(),
                align: "left",
                baseline: "top",
                font: "normal 12pt Verdana",
                x: 60,
                y: i
            });

        }
    }
}

$(function() {
    viewport = $("#viewport");
    fakescrolldiv = $("#fakescrolldiv");
    canvas = $("#gfx");

    viewport.css("height", vp);
    fakescrolldiv.css("height", h);

    viewport.scroll(onScroll);
    viewport.trigger("scroll");
});

Live demo

非常感谢任何改进或简化的建议。

关于javascript - 如何使用滚动条在虚拟 Canvas 上平移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7964031/

相关文章:

javascript - jQuery 将事件绑定(bind)到具有动态类的元素

javascript - 为什么这些 JavaScript 代码片段虽然都遇到了错误,但表现却不同?

javascript - 如何将 JavaScript 数组信息导出到 csv(在客户端)?

javascript - 在 Vue3-carousel 中显示多个图像

javascript - 将元素附加到兄弟

包含 HTML 的侧边菜单会干扰页面间距

jquery 悬停 div 并显示另一个 div 然后保持该 div 打开

javascript - 将表行加载到数组的数组

javascript - 如何使用 jQuery 切换隐藏的叠加层

javascript - 逗号分隔的电话号码验证