← Все материалы

AlgiViz 0.8.0 · Canvas / TypeScript

Пользовательские палитры canvas в AlgiViz 0.8.0

Автор: Grundy · Проверено: 19 октября 2026

Canvas не наследует цвета из CSS. Когда на стенде Grundyjs появились светлая и тёмная темы и выбор фона, визуализация алгоритма продолжала жить со своей палитрой. Сначала мы решили это отдельным renderer сайта, затем добавили переопределение цветов в AlgiViz 0.8.0 и убрали дублирующую отрисовку. Разберём проблему, изменение библиотеки и интеграцию с сохранением текущего кадра.

1. Двух тем оказалось недостаточно для палитры сайта

До версии 0.8.0 createArrayRenderer принимал только theme: light или dark. Светлая тема была полезна, но не позволяла согласовать canvas с произвольным фоном страницы, цветом текста и элементов. Изменение CSS-переменной само по себе не перерисовывает уже нарисованные пиксели. Нам понадобился единый источник цветов для CSS, примера алгоритма и сцены записи CanvasTake. Определение системной темы, сохранение выбора посетителя и запуск перерисовки при этом остаются задачами сайта.

2. Временное решение показало границу библиотеки

В AlgiViz уже были публичные arrayScene, createSceneProjector и createSceneRenderer. Через них сайт построил renderer со своими цветами, сохранив прежние шаги алгоритма и плеер. Решение работало, но дублировало геометрию столбцов, переходы, подписи и правила подсветки. Ради другой палитры не должно требоваться сопровождать вторую реализацию той же визуализации. Переиспользуемое изменение следовало внести в стандартный renderer массивов.

3. Переопределяем только нужные цвета

Установите @grundyjs/algiviz@0.8.0. Теперь импорт из /canvas принимает colors вместе с theme: переданные роли объединяются с выбранной встроенной темой. В примере настройки ниже обычные столбцы, активные элементы и отсортированная часть сохраняют цвета светлой темы. Пропущенные свойства и явно переданный undefined оставляют значение темы. Прежние вызовы, в которых задана только тема, и псевдоним createSortRenderer продолжают работать. Для частичной палитры экспортирован тип ArrayPaletteOverrides, для всех параметров — ArrayRendererOptions.

import { createArrayRenderer } from "@grundyjs/algiviz/canvas";

const renderer = createArrayRenderer({
    theme: "light",
    colors: {
        background: "#eef4c7",
        text: "#202438",
        held: "#87431d",
    },
});

4. Разделяем роли вместо одного акцента для всего

В ArrayPalette шесть цветов: background — фон canvas, text — подписи, bar — обычные элементы, sorted — окончательные позиции, active — подсвеченные операции, held — выбранный ключ. Полная палитра ниже — пример, а не обязательное оформление. Состояния должны различаться, а пояснение к визуализации — соответствовать цветам. Зелёная отсортированная область не должна сливаться с активным сравнением при смене акцента сайта. AlgiViz не проверяет контраст автоматически и не генерирует доступную палитру за приложение.

import type { ArrayPalette } from "@grundyjs/algiviz/canvas";

const palette: ArrayPalette = {
    background: "#f4f1fb",
    text: "#202438",
    bar: "#475569",
    sorted: "#047857",
    active: "#b45309",
    held: "#7c3aed",
};

5. Заменяем renderer, сохраняем текущий кадр

Renderer копирует палитру при создании. Последующее изменение исходного объекта colors не обновляет его цвета. Создайте новый renderer для новой темы и нарисуйте кадр, который уже хранится в представлении. Браузерный адаптер ниже принимает canvas с заранее настроенными размерами и начальный ArrayFrame из вашей временной шкалы. Следующие кадры передавайте в view.render(frame), а из переключателя темы вызывайте view.setPalette(theme, colors). Адаптер не создаёт и не перезапускает временную шкалу и не переводит её на нулевую позицию. Размеры canvas и обработка devicePixelRatio остаются в адаптере отображения приложения.

import { createArrayRenderer } from "@grundyjs/algiviz/canvas";
import type { ArrayPaletteOverrides, ArrayRendererOptions } from "@grundyjs/algiviz/canvas";
import type { ArrayFrame } from "@grundyjs/algiviz/array";

export function createPaletteView(canvas: HTMLCanvasElement, initialFrame: ArrayFrame) {
    const context = canvas.getContext("2d");
    if (!context) throw new Error("Canvas 2D is unavailable");

    let currentFrame = initialFrame;
    let renderer = createArrayRenderer({ theme: "light" });

    const render = (frame: ArrayFrame) => {
        currentFrame = frame;
        renderer.render(context, frame);
    };

    render(initialFrame);

    return {
        render,
        setPalette(theme: ArrayRendererOptions["theme"], colors: ArrayPaletteOverrides = {}) {
            renderer = createArrayRenderer({ theme, colors });
            render(currentFrame);
        },
    };
}

6. На сайте остаётся только адаптер цветов

Стенд вычисляет светлые и тёмные токены для CSS и canvas. SortingPlayer передаёт эти цвета стандартному renderer AlgiViz; отдельная отрисовка сцены удалена. На сайте фон canvas называется canvasBackground, а в библиотеке — background, поэтому оставшийся адаптер только сопоставляет имена свойств. Цвета операций отделены от выбранного посетителем акцента. Пример записи CanvasTake читает те же токены, но рисует свою сцену: поддержка палитры в AlgiViz не настраивает другую библиотеку автоматически.

import type { ArrayPalette } from "@grundyjs/algiviz/canvas";

type SiteCanvasColors = {
    canvasBackground: string;
    text: string;
    bar: string;
    sorted: string;
    active: string;
    held: string;
};

function arrayPalette(colors: SiteCanvasColors): ArrayPalette {
    return {
        background: colors.canvasBackground,
        text: colors.text,
        bar: colors.bar,
        sorted: colors.sorted,
        active: colors.active,
        held: colors.held,
    };
}

7. Проверяем состояния, геометрию и смену темы

На сайте проверены обе темы на кадрах start, compare и select, в том числе с выбранным ключом, повторами и отрицательным значением. Проверки охватывают фон, текст и все четыре роли элементов, сравнивают координаты отрисовки и подписи со стандартным renderer AlgiViz и подтверждают, что смена палитры не меняет кадр и снимки состояния. Проверки DPR также прошли. Для интеграции 0.8.0 прошли проверки алгоритмов, lint и production-сборка. Автоматические проверки не доказывают визуальную различимость любой пользовательской палитры. Дополнительно проверьте в браузере обе темы, остановленный кадр, воспроизведение и узкий экран. Перед выбором итоговой палитры оцените читаемость подписей и различимость цветов операций.

8. Что изменилось и что осталось приложению

В библиотеке появилась небольшая точка расширения, а не второй плеер или система тем конкретного сайта. Прежние вызовы сохраняют стандартные цвета. Сайт управляет выбором темы, его сохранением и перерисовкой; AlgiViz отвечает за стандартную отрисовку массива. Интеграция сейчас работает на минималистичном стенде: это не означает, что все страницы алгоритмов уже переведены на новую тему сайта. Дальше палитру можно подбирать в токенах, не копируя renderer массива заново.