Как я могу использовать полосы прокрутки для перемещения по виртуальному холсту? - PullRequest
6 голосов
/ 01 ноября 2011

Я хочу создать плагин jQuery, который реализует виртуальный холст HTML5, то есть холст, который физически не больше (или не намного), чем его внешний вид на странице. Но содержимое того, что должно быть показано на холсте, может быть во много раз больше, чем холст, и будет динамически перерисовываться в зависимости от полос прокрутки.

Можно подумать, что это очень распространенная функциональность, но до сих пор я не смог найти примеров ни с плагинами jQuery, ни с чем-либо еще. Это очень похоже на то, что, например, SlickGrid делает для Div, кроме этого с холстом. Я могу придумать два решения:

  1. Используйте jQuery UI Slider для реализации полосы прокрутки как полностью отдельного элемента и используйте его событие для управления перерисовкой Canvas.

  2. Делай, что делает SlickGrid для Div. Создается впечатление, что элемент Div немного больше того, что отображается, и подключается для прокрутки событий для динамического добавления / удаления элемента в / из элемента Div. Но я не вижу, как она изменяет полосу прокрутки, чтобы она выглядела так, как будто в Div больше всего того, что отображается в данный момент.

Что бы вы порекомендовали? Пример кода будет принята с благодарностью.

Ответы [ 2 ]

5 голосов
/ 01 февраля 2013

Я копался в коде 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

Любые предложения по улучшению или упрощению приветствуются.

2 голосов
/ 02 июля 2013

Из моего личного опыта ваш вариант (1) является привлекательным выбором, но могут быть некоторые интересные моменты при превращении его в полезный плагин jQuery.

Я работал над системой визуализации финансовых данныхкоторый явно использует HTML5 Canvas для рисования графиков и диаграмм.У нас есть разные виртуальные «сцены» или «слайды» на холсте, которые «скользят» и «скользят» на холсте, так же, как вы перемещаетесь на большом виртуальном холсте.Все кнопки обработки событий нарисованы исключительно на холсте, который определяет, какой экран мы будем показывать, но у нас есть одна / две нормальные HTML-формы, которые принимают пользовательский ввод и выводят эти «слайды».Мы используем jQuery для обработки событий из этих текстовых полей, но коды jQuery глубоко вложены в другие коды рисования Canvas (в отличие от внешнего вызова, который был бы идеальным кандидатом для создания плагина).

Скольжениеили обновление холста это другое дело.Это связано с тем, что это зависит не только от события jQuery, которое запускает обновление, но также от Canvas Framework (простой код или KineticJS, EaselJS, jCotton и т. Д.), Который отвечает за обновление.Если вы используете фреймворк, вам также необходимо взаимодействовать с фреймворком.

Для простоты давайте предположим, что есть функция обратного вызова, которую вы можете вызвать для этого фреймворка Canvas с такими параметрами, как смещение движения (x,y), и каркас будет добавлять / удалять это смещение к позициям x и y всех объектов, нарисованных на холсте, большинство каркасов рисования Canvas также имеют функцию render(), которую она периодически вызывает, чтобы в следующий раз рисовать сценурезультаты автоматически отобразятся (в вашем случае, прокручивая виртуальный холст).

Таким образом, все сводится не только к написанию его в качестве плагина jQuery, но и к его привязке к определенной платформе Canvas, например KineticJS илидругие.

Если вы используете базовые функции Canvas вместо какой-либо из этих структур, тогда это другая история, вы можете написать свои собственные функции рендеринга и обновления для холста, но в этом случае это будет ограничиватьпотенциальный пользователь, чтобы придерживаться ограничений вашего DrawIng функции, если вы не предоставляете API для их расширения;но опять же, это означает, что вы пишете свою собственную платформу Canvas:)

Я не уверен, правильно ли я понял вашу проблему, в этом случае вы можете спокойно проигнорировать мой совет :), но если яПравильно, мое мнение будет таким: создание такого плагина потребует также привязки к среде Canvas, чтобы сделать его действительно полезным.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...